all repos — mgba @ c59bfd173d3c197916fe267a734120a40ec0787f

mGBA Game Boy Advance Emulator

src/platform/sdl/gl-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 "gl-common.h"
  9
 10#include "gba/supervisor/thread.h"
 11#ifdef M_CORE_GB
 12#include "gb/gb.h"
 13#endif
 14#include "platform/opengl/gl.h"
 15
 16static void _doViewport(int w, int h, struct VideoBackend* v) {
 17	v->resized(v, w, h);
 18	v->clear(v);
 19	v->swap(v);
 20	v->clear(v);
 21}
 22
 23#ifdef M_CORE_GBA
 24static bool mSDLGLInitGBA(struct mSDLRenderer* renderer);
 25static void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user);
 26#endif
 27#ifdef M_CORE_GB
 28static bool mSDLGLInitGB(struct mSDLRenderer* renderer);
 29static void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user);
 30#endif
 31static void mSDLGLDeinit(struct mSDLRenderer* renderer);
 32
 33#ifdef M_CORE_GBA
 34void mSDLGLCreate(struct mSDLRenderer* renderer) {
 35	renderer->init = mSDLGLInitGBA;
 36	renderer->deinit = mSDLGLDeinit;
 37	renderer->runloop = mSDLGLRunloopGBA;
 38}
 39
 40bool mSDLGLInitGBA(struct mSDLRenderer* renderer) {
 41	mSDLGLCommonInit(renderer);
 42
 43	renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 44	renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
 45
 46	GBAGLContextCreate(&renderer->gl);
 47	renderer->gl.d.user = renderer;
 48	renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
 49	renderer->gl.d.filter = renderer->filter;
 50	renderer->gl.d.swap = mSDLGLCommonSwap;
 51	renderer->gl.d.init(&renderer->gl.d, 0);
 52
 53	_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
 54	return true;
 55}
 56
 57void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user) {
 58	struct GBAThread* context = user;
 59	SDL_Event event;
 60	struct VideoBackend* v = &renderer->gl.d;
 61
 62	while (context->state < THREAD_EXITING) {
 63		while (SDL_PollEvent(&event)) {
 64			GBASDLHandleEvent(context, &renderer->player, &event);
 65#if SDL_VERSION_ATLEAST(2, 0, 0)
 66			// Event handling can change the size of the screen
 67			if (renderer->player.windowUpdated) {
 68				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
 69				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
 70				renderer->player.windowUpdated = 0;
 71			}
 72#endif
 73		}
 74
 75		if (GBASyncWaitFrameStart(&context->sync)) {
 76			v->postFrame(v, renderer->d.outputBuffer);
 77		}
 78		GBASyncWaitFrameEnd(&context->sync);
 79		v->drawFrame(v);
 80		v->swap(v);
 81	}
 82}
 83#endif
 84
 85#ifdef M_CORE_GB
 86void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
 87	renderer->init = mSDLGLInitGB;
 88	renderer->deinit = mSDLGLDeinit;
 89	renderer->runloop = mSDLGLRunloopGB;
 90}
 91
 92bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
 93	mSDLGLCommonInit(renderer);
 94
 95	// TODO: Pass texture size along
 96	renderer->gb.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 97	renderer->gb.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
 98
 99	GBAGLContextCreate(&renderer->gl);
100	renderer->gl.d.user = renderer;
101	renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
102	renderer->gl.d.filter = renderer->filter;
103	renderer->gl.d.swap = mSDLGLCommonSwap;
104	renderer->gl.d.init(&renderer->gl.d, 0);
105
106	_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
107	return true;
108}
109
110void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) {
111	struct GB* gb = user;
112	SDL_Event event;
113	struct VideoBackend* v = &renderer->gl.d;
114	int activeKeys = 0;
115	gb->keySource = &activeKeys;
116
117	while (true) {
118		int64_t frameCounter = gb->video.frameCounter;
119		while (gb->video.frameCounter == frameCounter) {
120			LR35902Tick(gb->cpu);
121		}
122		while (SDL_PollEvent(&event)) {
123			// TODO: Refactor out
124			if (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) {
125				int key;
126#if !defined(BUILD_PANDORA) && SDL_VERSION_ATLEAST(2, 0, 0)
127				key = GBAInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.scancode);
128#else
129				key = GBAInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.sym);
130#endif
131				if (key != GBA_KEY_NONE) {
132					if (event.type == SDL_KEYDOWN) {
133						activeKeys |= 1 << key;
134					} else {
135						activeKeys &= ~(1 << key);
136					}
137				}
138			}
139
140#if SDL_VERSION_ATLEAST(2, 0, 0)
141			// Event handling can change the size of the screen
142			if (renderer->player.windowUpdated) {
143				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
144				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
145				renderer->player.windowUpdated = 0;
146			}
147#endif
148		}
149
150		v->postFrame(v, renderer->gb.outputBuffer);
151		v->drawFrame(v);
152		v->swap(v);
153	}
154}
155#endif
156
157void mSDLGLDeinit(struct mSDLRenderer* renderer) {
158	if (renderer->gl.d.deinit) {
159		renderer->gl.d.deinit(&renderer->gl.d);
160	}
161	free(renderer->d.outputBuffer);
162#if SDL_VERSION_ATLEAST(2, 0, 0)
163	SDL_GL_DeleteContext(renderer->glCtx);
164#endif
165}