all repos — mgba @ 33a4c45f3ff72c83a3f68b5f4e5730764018a743

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#include "core/thread.h"
 12#include "platform/opengl/gl.h"
 13
 14#define GB_GBA_CENTER ((VIDEO_HORIZONTAL_PIXELS - GB_VIDEO_HORIZONTAL_PIXELS + VIDEO_HORIZONTAL_PIXELS * (VIDEO_VERTICAL_PIXELS - GB_VIDEO_VERTICAL_PIXELS)) / 2)
 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
 24#include "gba/gba.h"
 25
 26static bool mSDLGLInitGBA(struct mSDLRenderer* renderer);
 27#endif
 28#ifdef M_CORE_GB
 29#include "gb/gb.h"
 30
 31static bool mSDLGLInitGB(struct mSDLRenderer* renderer);
 32#endif
 33
 34static void mSDLGLRunloop(struct mSDLRenderer* renderer, void* user);
 35static void mSDLGLDeinit(struct mSDLRenderer* renderer);
 36
 37#ifdef M_CORE_GBA
 38void mSDLGLCreateGBA(struct mSDLRenderer* renderer) {
 39	renderer->init = mSDLGLInitGBA;
 40	renderer->deinit = mSDLGLDeinit;
 41	renderer->runloop = mSDLGLRunloop;
 42}
 43
 44bool mSDLGLInitGBA(struct mSDLRenderer* renderer) {
 45	mSDLGLCommonInit(renderer);
 46
 47	renderer->outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 48	memset(renderer->outputBuffer, 0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 49	renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, VIDEO_HORIZONTAL_PIXELS);
 50
 51	GBAGLContextCreate(&renderer->gl);
 52	renderer->gl.d.user = renderer;
 53	renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
 54	renderer->gl.d.filter = renderer->filter;
 55	renderer->gl.d.swap = mSDLGLCommonSwap;
 56	renderer->gl.d.init(&renderer->gl.d, 0);
 57
 58	_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
 59	return true;
 60}
 61#endif
 62
 63#ifdef M_CORE_GB
 64void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
 65	renderer->init = mSDLGLInitGB;
 66	renderer->deinit = mSDLGLDeinit;
 67	renderer->runloop = mSDLGLRunloop;
 68}
 69
 70bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
 71	mSDLGLCommonInit(renderer);
 72
 73	// TODO: Pass texture size along
 74	renderer->outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 75	memset(renderer->outputBuffer, 0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 76	renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer + GB_GBA_CENTER, VIDEO_HORIZONTAL_PIXELS);
 77
 78	GBAGLContextCreate(&renderer->gl);
 79	renderer->gl.d.user = renderer;
 80	renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
 81	renderer->gl.d.filter = renderer->filter;
 82	renderer->gl.d.swap = mSDLGLCommonSwap;
 83	renderer->gl.d.init(&renderer->gl.d, 0);
 84
 85	_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
 86	return true;
 87}
 88#endif
 89
 90void mSDLGLRunloop(struct mSDLRenderer* renderer, void* user) {
 91	struct mCoreThread* context = user;
 92	SDL_Event event;
 93	struct VideoBackend* v = &renderer->gl.d;
 94
 95	while (context->state < THREAD_EXITING) {
 96		while (SDL_PollEvent(&event)) {
 97			mSDLHandleEvent(context, &renderer->player, &event);
 98#if SDL_VERSION_ATLEAST(2, 0, 0)
 99			// Event handling can change the size of the screen
100			if (renderer->player.windowUpdated) {
101				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
102				_doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
103				renderer->player.windowUpdated = 0;
104			}
105#endif
106		}
107
108		if (mCoreSyncWaitFrameStart(&context->sync)) {
109			v->postFrame(v, renderer->outputBuffer);
110		}
111		mCoreSyncWaitFrameEnd(&context->sync);
112		v->drawFrame(v);
113		v->swap(v);
114	}
115}
116
117void mSDLGLDeinit(struct mSDLRenderer* renderer) {
118	if (renderer->gl.d.deinit) {
119		renderer->gl.d.deinit(&renderer->gl.d);
120	}
121	free(renderer->outputBuffer);
122#if SDL_VERSION_ATLEAST(2, 0, 0)
123	SDL_GL_DeleteContext(renderer->glCtx);
124#endif
125}