all repos — mgba @ 2770b654f5f1fe70ac5ddcf1d0742ef004345781

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#include <mgba-util/arm-algo.h>
 12
 13static bool mSDLSWInit(struct mSDLRenderer* renderer);
 14static void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user);
 15static void mSDLSWDeinit(struct mSDLRenderer* renderer);
 16
 17void mSDLSWCreate(struct mSDLRenderer* renderer) {
 18	renderer->init = mSDLSWInit;
 19	renderer->deinit = mSDLSWDeinit;
 20	renderer->runloop = mSDLSWRunloop;
 21}
 22
 23bool mSDLSWInit(struct mSDLRenderer* renderer) {
 24#ifdef COLOR_16_BIT
 25	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->player.fullscreen));
 26#else
 27	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->player.fullscreen));
 28#endif
 29	SDL_WM_SetCaption(projectName, "");
 30
 31	unsigned width, height;
 32	renderer->core->desiredVideoDimensions(renderer->core, &width, &height);
 33	SDL_Surface* surface = SDL_GetVideoSurface();
 34	SDL_LockSurface(surface);
 35
 36	if (renderer->ratio == 1) {
 37		renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL);
 38	} else {
 39#ifdef USE_PIXMAN
 40		renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
 41		renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width);
 42#ifdef COLOR_16_BIT
 43#ifdef COLOR_5_6_5
 44		pixman_format_code_t format = PIXMAN_r5g6b5;
 45#else
 46		pixman_format_code_t format = PIXMAN_x1b5g5r5;
 47#endif
 48#else
 49		pixman_format_code_t format = PIXMAN_x8b8g8r8;
 50#endif
 51		renderer->pix = pixman_image_create_bits(format, width, height,
 52		    renderer->outputBuffer, width * BYTES_PER_PIXEL);
 53		renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);
 54
 55		pixman_transform_t transform;
 56		pixman_transform_init_identity(&transform);
 57		pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
 58		pixman_image_set_transform(renderer->pix, &transform);
 59		pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
 60#else
 61		return false;
 62#endif
 63	}
 64
 65	return true;
 66}
 67
 68void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user) {
 69	struct mCoreThread* context = user;
 70	SDL_Event event;
 71	SDL_Surface* surface = SDL_GetVideoSurface();
 72
 73	while (mCoreThreadIsActive(context)) {
 74		while (SDL_PollEvent(&event)) {
 75			mSDLHandleEvent(context, &renderer->player, &event);
 76		}
 77
 78		if (mCoreSyncWaitFrameStart(&context->impl->sync)) {
 79#ifdef USE_PIXMAN
 80			if (renderer->ratio > 1) {
 81				pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix,
 82				    0, 0, 0, 0, 0, 0,
 83				    renderer->viewportWidth, renderer->viewportHeight);
 84			}
 85#else
 86			switch (renderer->ratio) {
 87#if defined(__ARM_NEON) && COLOR_16_BIT
 88			case 2:
 89				_neon2x(surface->pixels, renderer->outputBuffer, width, height);
 90				break;
 91			case 4:
 92				_neon4x(surface->pixels, renderer->outputBuffer, width, height);
 93				break;
 94#endif
 95			case 1:
 96				break;
 97			default:
 98				abort();
 99			}
100#endif
101			SDL_UnlockSurface(surface);
102			SDL_Flip(surface);
103			SDL_LockSurface(surface);
104		}
105		mCoreSyncWaitFrameEnd(&context->impl->sync);
106	}
107}
108
109void mSDLSWDeinit(struct mSDLRenderer* renderer) {
110	if (renderer->ratio > 1) {
111		free(renderer->outputBuffer);
112#ifdef USE_PIXMAN
113		pixman_image_unref(renderer->pix);
114		pixman_image_unref(renderer->screenpix);
115#endif
116	}
117	SDL_Surface* surface = SDL_GetVideoSurface();
118	SDL_UnlockSurface(surface);
119}