all repos — mgba @ 4e64b4fde474693d6175335efbc142c98e08c163

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
115	while (true) {
116		int64_t frameCounter = gb->video.frameCounter;
117		while (gb->video.frameCounter == frameCounter) {
118			LR35902Tick(gb->cpu);			
119		}
120		while (SDL_PollEvent(&event)) {
121#if SDL_VERSION_ATLEAST(2, 0, 0)
122			// Event handling can change the size of the screen
123			if (renderer->player.windowUpdated) {
124				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
125				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
126				renderer->player.windowUpdated = 0;
127			}
128#endif
129		}
130
131		v->postFrame(v, renderer->gb.outputBuffer);
132		v->drawFrame(v);
133		v->swap(v);
134	}
135}
136#endif
137
138void mSDLGLDeinit(struct mSDLRenderer* renderer) {
139	if (renderer->gl.d.deinit) {
140		renderer->gl.d.deinit(&renderer->gl.d);
141	}
142	free(renderer->d.outputBuffer);
143#if SDL_VERSION_ATLEAST(2, 0, 0)
144	SDL_GL_DeleteContext(renderer->glCtx);
145#endif
146}