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);
26static void mSDLGLDeinitGBA(struct mSDLRenderer* renderer);
27#endif
28#ifdef M_CORE_GB
29static bool mSDLGLInitGB(struct mSDLRenderer* renderer);
30static void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user);
31static void mSDLGLDeinitGB(struct mSDLRenderer* renderer);
32#endif
33
34#ifdef M_CORE_GBA
35void mSDLGLCreate(struct mSDLRenderer* renderer) {
36 renderer->init = mSDLGLInitGBA;
37 renderer->deinit = mSDLGLDeinitGBA;
38 renderer->runloop = mSDLGLRunloopGBA;
39}
40
41bool mSDLGLInitGBA(struct mSDLRenderer* renderer) {
42 mSDLGLCommonInit(renderer);
43
44 renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
45 renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
46
47 GBAGLContextCreate(&renderer->gl);
48 renderer->gl.d.user = renderer;
49 renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
50 renderer->gl.d.filter = renderer->filter;
51 renderer->gl.d.swap = mSDLGLCommonSwap;
52 renderer->gl.d.init(&renderer->gl.d, 0);
53
54 _doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
55 return true;
56}
57
58void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user) {
59 struct GBAThread* context = user;
60 SDL_Event event;
61 struct VideoBackend* v = &renderer->gl.d;
62
63 while (context->state < THREAD_EXITING) {
64 while (SDL_PollEvent(&event)) {
65 GBASDLHandleEvent(context, &renderer->player, &event);
66#if SDL_VERSION_ATLEAST(2, 0, 0)
67 // Event handling can change the size of the screen
68 if (renderer->player.windowUpdated) {
69 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
70 _doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
71 renderer->player.windowUpdated = 0;
72 }
73#endif
74 }
75
76 if (GBASyncWaitFrameStart(&context->sync)) {
77 v->postFrame(v, renderer->d.outputBuffer);
78 }
79 GBASyncWaitFrameEnd(&context->sync);
80 v->drawFrame(v);
81 v->swap(v);
82 }
83}
84
85void mSDLGLDeinitGBA(struct mSDLRenderer* renderer) {
86 if (renderer->gl.d.deinit) {
87 renderer->gl.d.deinit(&renderer->gl.d);
88 }
89 free(renderer->d.outputBuffer);
90#if SDL_VERSION_ATLEAST(2, 0, 0)
91 SDL_GL_DeleteContext(renderer->glCtx);
92#endif
93}
94#endif
95
96#ifdef M_CORE_GB
97void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
98 renderer->init = mSDLGLInitGB;
99 renderer->deinit = mSDLGLDeinitGB;
100 renderer->runloop = mSDLGLRunloopGB;
101}
102
103bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
104 mSDLGLCommonInit(renderer);
105
106 // TODO: Pass texture size along
107 renderer->gb.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
108 renderer->gb.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
109
110 GBAGLContextCreate(&renderer->gl);
111 renderer->gl.d.user = renderer;
112 renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
113 renderer->gl.d.filter = renderer->filter;
114 renderer->gl.d.swap = mSDLGLCommonSwap;
115 renderer->gl.d.init(&renderer->gl.d, 0);
116
117 _doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
118 return true;
119}
120
121void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) {
122 struct GB* gb = user;
123 SDL_Event event;
124 struct VideoBackend* v = &renderer->gl.d;
125 int activeKeys = 0;
126 gb->keySource = &activeKeys;
127
128 while (true) {
129 int64_t frameCounter = gb->video.frameCounter;
130 while (gb->video.frameCounter == frameCounter) {
131 LR35902Tick(gb->cpu);
132 }
133 while (SDL_PollEvent(&event)) {
134 // TODO: Refactor out
135 if (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) {
136 int key;
137#if !defined(BUILD_PANDORA) && SDL_VERSION_ATLEAST(2, 0, 0)
138 key = GBAInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.scancode);
139#else
140 key = GBAInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.sym);
141#endif
142 if (key != GBA_KEY_NONE) {
143 if (event.type == SDL_KEYDOWN) {
144 activeKeys |= 1 << key;
145 } else {
146 activeKeys &= ~(1 << key);
147 }
148 }
149 }
150 if (event.type == SDL_QUIT) {
151 return;
152 }
153
154#if SDL_VERSION_ATLEAST(2, 0, 0)
155 // Event handling can change the size of the screen
156 if (renderer->player.windowUpdated) {
157 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
158 _doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
159 renderer->player.windowUpdated = 0;
160 }
161#endif
162 }
163
164 v->postFrame(v, renderer->gb.outputBuffer);
165 v->drawFrame(v);
166 v->swap(v);
167 }
168}
169
170void mSDLGLDeinitGB(struct mSDLRenderer* renderer) {
171 if (renderer->gl.d.deinit) {
172 renderer->gl.d.deinit(&renderer->gl.d);
173 }
174 free(renderer->gb.outputBuffer);
175#if SDL_VERSION_ATLEAST(2, 0, 0)
176 SDL_GL_DeleteContext(renderer->glCtx);
177#endif
178}
179#endif