all repos — mgba @ 28268a601bcd1fcc71389c1b8a278dd69bcefd9f

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			mSDLHandleEventGBA(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	struct mCoreThread* context = user;
133	SDL_Event event;
134	struct VideoBackend* v = &renderer->gl.d;
135	renderer->audio.psg = &((struct GB*) renderer->core->board)->audio;
136
137	while (context->state < THREAD_EXITING) {
138		while (SDL_PollEvent(&event)) {
139			mSDLHandleEvent(context, &renderer->player, &event);
140#if SDL_VERSION_ATLEAST(2, 0, 0)
141			// Event handling can change the size of the screen
142			if (renderer->player.windowUpdated) {
143				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
144				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
145				renderer->player.windowUpdated = 0;
146			}
147#endif
148		}
149
150		if (mCoreSyncWaitFrameStart(&context->sync)) {
151			v->postFrame(v, renderer->outputBuffer);
152		}
153		mCoreSyncWaitFrameEnd(&context->sync);
154		v->drawFrame(v);
155		v->swap(v);
156	}
157	renderer->audio.psg = 0;
158}
159
160void mSDLGLDeinitGB(struct mSDLRenderer* renderer) {
161	if (renderer->gl.d.deinit) {
162		renderer->gl.d.deinit(&renderer->gl.d);
163	}
164	free(renderer->outputBuffer);
165#if SDL_VERSION_ATLEAST(2, 0, 0)
166	SDL_GL_DeleteContext(renderer->glCtx);
167#endif
168}
169#endif