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 int activeKeys = 0;
115 gb->keySource = &activeKeys;
116
117 while (true) {
118 int64_t frameCounter = gb->video.frameCounter;
119 while (gb->video.frameCounter == frameCounter) {
120 LR35902Tick(gb->cpu);
121 }
122 while (SDL_PollEvent(&event)) {
123 // TODO: Refactor out
124 if (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) {
125 int key;
126#if !defined(BUILD_PANDORA) && SDL_VERSION_ATLEAST(2, 0, 0)
127 key = GBAInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.scancode);
128#else
129 key = GBAInputMapKey(renderer->player.bindings, SDL_BINDING_KEY, event.key.keysym.sym);
130#endif
131 if (key != GBA_KEY_NONE) {
132 if (event.type == SDL_KEYDOWN) {
133 activeKeys |= 1 << key;
134 } else {
135 activeKeys &= ~(1 << key);
136 }
137 }
138 }
139 if (event.type == SDL_QUIT) {
140 return;
141 }
142
143#if SDL_VERSION_ATLEAST(2, 0, 0)
144 // Event handling can change the size of the screen
145 if (renderer->player.windowUpdated) {
146 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
147 _doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
148 renderer->player.windowUpdated = 0;
149 }
150#endif
151 }
152
153 v->postFrame(v, renderer->gb.outputBuffer);
154 v->drawFrame(v);
155 v->swap(v);
156 }
157}
158#endif
159
160void mSDLGLDeinit(struct mSDLRenderer* renderer) {
161 if (renderer->gl.d.deinit) {
162 renderer->gl.d.deinit(&renderer->gl.d);
163 }
164 free(renderer->d.outputBuffer);
165#if SDL_VERSION_ATLEAST(2, 0, 0)
166 SDL_GL_DeleteContext(renderer->glCtx);
167#endif
168}