all repos — mgba @ 953335846b9a6dca420875cfd5edaea055eae681

mGBA Game Boy Advance Emulator

src/platform/sdl/sw-sdl.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 "core/thread.h"
  9#include "core/version.h"
 10#include "util/arm-algo.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#if !SDL_VERSION_ATLEAST(2, 0, 0)
 24#ifdef COLOR_16_BIT
 25	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
 26#else
 27	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
 28#endif
 29#endif
 30
 31	unsigned width, height;
 32	renderer->core->desiredVideoDimensions(renderer->core, &width, &height);
 33#if SDL_VERSION_ATLEAST(2, 0, 0)
 34	renderer->window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen));
 35	SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
 36	renderer->player.window = renderer->window;
 37	renderer->sdlRenderer = SDL_CreateRenderer(renderer->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
 38#ifdef COLOR_16_BIT
 39#ifdef COLOR_5_6_5
 40	renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
 41#else
 42	renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR1555, SDL_TEXTUREACCESS_STREAMING, width, height);
 43#endif
 44#else
 45	renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height);
 46#endif
 47
 48	int stride;
 49	SDL_LockTexture(renderer->sdlTex, 0, (void**) &renderer->outputBuffer, &stride);
 50	renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, stride / BYTES_PER_PIXEL);
 51#else
 52	SDL_Surface* surface = SDL_GetVideoSurface();
 53	SDL_LockSurface(surface);
 54
 55	if (renderer->ratio == 1) {
 56		renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL);
 57	} else {
 58#ifdef USE_PIXMAN
 59		renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
 60		renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width);
 61#ifdef COLOR_16_BIT
 62#ifdef COLOR_5_6_5
 63		pixman_format_code_t format = PIXMAN_r5g6b5;
 64#else
 65		pixman_format_code_t format = PIXMAN_x1b5g5r5;
 66#endif
 67#else
 68		pixman_format_code_t format = PIXMAN_x8b8g8r8;
 69#endif
 70		renderer->pix = pixman_image_create_bits(format, width, height,
 71		    renderer->outputBuffer, width * BYTES_PER_PIXEL);
 72		renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);
 73
 74		pixman_transform_t transform;
 75		pixman_transform_init_identity(&transform);
 76		pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
 77		pixman_image_set_transform(renderer->pix, &transform);
 78		pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
 79#else
 80		return false;
 81#endif
 82	}
 83#endif
 84
 85	return true;
 86}
 87
 88void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user) {
 89	struct mCoreThread* context = user;
 90	SDL_Event event;
 91#if !SDL_VERSION_ATLEAST(2, 0, 0)
 92	SDL_Surface* surface = SDL_GetVideoSurface();
 93#endif
 94
 95	while (context->state < THREAD_EXITING) {
 96		while (SDL_PollEvent(&event)) {
 97			mSDLHandleEvent(context, &renderer->player, &event);
 98		}
 99
100		if (mCoreSyncWaitFrameStart(&context->sync)) {
101#if SDL_VERSION_ATLEAST(2, 0, 0)
102			SDL_UnlockTexture(renderer->sdlTex);
103			SDL_RenderCopy(renderer->sdlRenderer, renderer->sdlTex, 0, 0);
104			SDL_RenderPresent(renderer->sdlRenderer);
105			int stride;
106			SDL_LockTexture(renderer->sdlTex, 0, (void**) &renderer->outputBuffer, &stride);
107			renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, stride / BYTES_PER_PIXEL);
108#else
109#ifdef USE_PIXMAN
110			if (renderer->ratio > 1) {
111				pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix,
112				    0, 0, 0, 0, 0, 0,
113				    renderer->viewportWidth, renderer->viewportHeight);
114			}
115#else
116			switch (renderer->ratio) {
117#if defined(__ARM_NEON) && COLOR_16_BIT
118			case 2:
119				_neon2x(surface->pixels, renderer->outputBuffer, width, height);
120				break;
121			case 4:
122				_neon4x(surface->pixels, renderer->outputBuffer, width, height);
123				break;
124#endif
125			case 1:
126				break;
127			default:
128				abort();
129			}
130#endif
131			SDL_UnlockSurface(surface);
132			SDL_Flip(surface);
133			SDL_LockSurface(surface);
134#endif
135		}
136		mCoreSyncWaitFrameEnd(&context->sync);
137	}
138}
139
140void mSDLSWDeinit(struct mSDLRenderer* renderer) {
141	if (renderer->ratio > 1) {
142		free(renderer->outputBuffer);
143	}
144#if !SDL_VERSION_ATLEAST(2, 0, 0)
145	SDL_Surface* surface = SDL_GetVideoSurface();
146	SDL_UnlockSurface(surface);
147#ifdef USE_PIXMAN
148	pixman_image_unref(renderer->pix);
149	pixman_image_unref(renderer->screenpix);
150#endif
151#endif
152}