all repos — mgba @ 92c6b90b03f8c04b53312bf2273d86a9783ee073

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	renderer->audio.psg = &context->gba->audio.psg;
 69
 70	while (context->state < THREAD_EXITING) {
 71		while (SDL_PollEvent(&event)) {
 72			GBASDLHandleEvent(context, &renderer->player, &event);
 73#if SDL_VERSION_ATLEAST(2, 0, 0)
 74			// Event handling can change the size of the screen
 75			if (renderer->player.windowUpdated) {
 76				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
 77				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
 78				renderer->player.windowUpdated = 0;
 79			}
 80#endif
 81		}
 82
 83		if (mCoreSyncWaitFrameStart(&context->sync)) {
 84			v->postFrame(v, renderer->d.outputBuffer);
 85		}
 86		mCoreSyncWaitFrameEnd(&context->sync);
 87		v->drawFrame(v);
 88		v->swap(v);
 89	}
 90
 91	renderer->audio.psg = 0;
 92}
 93
 94void mSDLGLDeinitGBA(struct mSDLRenderer* renderer) {
 95	if (renderer->gl.d.deinit) {
 96		renderer->gl.d.deinit(&renderer->gl.d);
 97	}
 98	free(renderer->d.outputBuffer);
 99#if SDL_VERSION_ATLEAST(2, 0, 0)
100	SDL_GL_DeleteContext(renderer->glCtx);
101#endif
102}
103#endif
104
105#ifdef M_CORE_GB
106void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
107	renderer->init = mSDLGLInitGB;
108	renderer->deinit = mSDLGLDeinitGB;
109	renderer->runloop = mSDLGLRunloopGB;
110}
111
112bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
113	mSDLGLCommonInit(renderer);
114
115	// TODO: Pass texture size along
116	renderer->outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
117	memset(renderer->outputBuffer, 0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
118	renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer + GB_GBA_CENTER, VIDEO_HORIZONTAL_PIXELS);
119
120	GBAGLContextCreate(&renderer->gl);
121	renderer->gl.d.user = renderer;
122	renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
123	renderer->gl.d.filter = renderer->filter;
124	renderer->gl.d.swap = mSDLGLCommonSwap;
125	renderer->gl.d.init(&renderer->gl.d, 0);
126
127	_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
128	return true;
129}
130
131void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) {
132	UNUSED(user);
133	SDL_Event event;
134	struct VideoBackend* v = &renderer->gl.d;
135	int activeKeys = 0;
136	renderer->audio.psg = &((struct GB*) renderer->core->board)->audio;
137
138	while (true) {
139		renderer->core->runFrame(renderer->core);
140		while (SDL_PollEvent(&event)) {
141			// TODO: Refactor out
142			if (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) {
143				int key;
144#if !defined(BUILD_PANDORA) && SDL_VERSION_ATLEAST(2, 0, 0)
145				key = mInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.scancode);
146#else
147				key = mInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.sym);
148#endif
149				if (key != GBA_KEY_NONE) {
150					if (event.type == SDL_KEYDOWN) {
151						activeKeys |= 1 << key;
152					} else {
153						activeKeys &= ~(1 << key);
154					}
155				}
156			}
157			if (event.type == SDL_QUIT) {
158				return;
159			}
160
161#if SDL_VERSION_ATLEAST(2, 0, 0)
162			// Event handling can change the size of the screen
163			if (renderer->player.windowUpdated) {
164				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
165				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
166				renderer->player.windowUpdated = 0;
167			}
168#endif
169		}
170		renderer->core->setKeys(renderer->core, activeKeys);
171
172		v->postFrame(v, renderer->outputBuffer);
173		v->drawFrame(v);
174		v->swap(v);
175	}
176	renderer->audio.psg = 0;
177}
178
179void mSDLGLDeinitGB(struct mSDLRenderer* renderer) {
180	if (renderer->gl.d.deinit) {
181		renderer->gl.d.deinit(&renderer->gl.d);
182	}
183	free(renderer->outputBuffer);
184#if SDL_VERSION_ATLEAST(2, 0, 0)
185	SDL_GL_DeleteContext(renderer->glCtx);
186#endif
187}
188#endif