all repos — mgba @ bc1a094bead8ffa1d9d03beebfa8676511d7ac0b

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