all repos — mgba @ 8ec9ebf7d8b51a19155948e4b5aaf068fa334f32

mGBA Game Boy Advance Emulator

src/platform/sdl/sw-sdl1.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "main.h"
  7
  8#include <mgba/core/core.h>
  9#include <mgba/core/thread.h>
 10#include <mgba/core/version.h>
 11
 12static bool mSDLSWInit(struct mSDLRenderer* renderer);
 13static void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user);
 14static void mSDLSWDeinit(struct mSDLRenderer* renderer);
 15
 16void mSDLSWCreate(struct mSDLRenderer* renderer) {
 17	renderer->init = mSDLSWInit;
 18	renderer->deinit = mSDLSWDeinit;
 19	renderer->runloop = mSDLSWRunloop;
 20}
 21
 22bool mSDLSWInit(struct mSDLRenderer* renderer) {
 23#ifdef COLOR_16_BIT
 24	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->player.fullscreen));
 25#else
 26	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->player.fullscreen));
 27#endif
 28	SDL_WM_SetCaption(projectName, "");
 29
 30	unsigned width, height;
 31	renderer->core->desiredVideoDimensions(renderer->core, &width, &height);
 32	SDL_Surface* surface = SDL_GetVideoSurface();
 33	SDL_LockSurface(surface);
 34
 35	if (renderer->ratio == 1) {
 36		renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL);
 37	} else {
 38#ifdef USE_PIXMAN
 39		renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
 40		renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width);
 41#ifdef COLOR_16_BIT
 42#ifdef COLOR_5_6_5
 43		pixman_format_code_t format = PIXMAN_r5g6b5;
 44#else
 45		pixman_format_code_t format = PIXMAN_x1b5g5r5;
 46#endif
 47#else
 48		pixman_format_code_t format = PIXMAN_x8b8g8r8;
 49#endif
 50		renderer->pix = pixman_image_create_bits(format, width, height,
 51		    renderer->outputBuffer, width * BYTES_PER_PIXEL);
 52		renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);
 53
 54		pixman_transform_t transform;
 55		pixman_transform_init_identity(&transform);
 56		pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
 57		pixman_image_set_transform(renderer->pix, &transform);
 58		pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
 59#else
 60		return false;
 61#endif
 62	}
 63
 64	return true;
 65}
 66
 67void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user) {
 68	struct mCoreThread* context = user;
 69	SDL_Event event;
 70	SDL_Surface* surface = SDL_GetVideoSurface();
 71
 72	while (mCoreThreadIsActive(context)) {
 73		while (SDL_PollEvent(&event)) {
 74			mSDLHandleEvent(context, &renderer->player, &event);
 75		}
 76
 77		if (mCoreSyncWaitFrameStart(&context->impl->sync)) {
 78#ifdef USE_PIXMAN
 79			if (renderer->ratio > 1) {
 80				pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix,
 81				    0, 0, 0, 0, 0, 0,
 82				    renderer->viewportWidth, renderer->viewportHeight);
 83			}
 84#else
 85			if (renderer->ratio != 1) {
 86				abort();
 87			}
 88#endif
 89			SDL_UnlockSurface(surface);
 90			SDL_Flip(surface);
 91			SDL_LockSurface(surface);
 92		}
 93		mCoreSyncWaitFrameEnd(&context->impl->sync);
 94	}
 95}
 96
 97void mSDLSWDeinit(struct mSDLRenderer* renderer) {
 98	if (renderer->ratio > 1) {
 99		free(renderer->outputBuffer);
100#ifdef USE_PIXMAN
101		pixman_image_unref(renderer->pix);
102		pixman_image_unref(renderer->screenpix);
103#endif
104	}
105	SDL_Surface* surface = SDL_GetVideoSurface();
106	SDL_UnlockSurface(surface);
107}