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