all repos — mgba @ fc0109282b81c5fac6a108b4636192d8efe2b345

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