all repos — mgba @ 04281f9f111137f1c6449fa904ab64b033ba3db6

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