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
115 while (true) {
116 int64_t frameCounter = gb->video.frameCounter;
117 while (gb->video.frameCounter == frameCounter) {
118 LR35902Tick(gb->cpu);
119 }
120 while (SDL_PollEvent(&event)) {
121#if SDL_VERSION_ATLEAST(2, 0, 0)
122 // Event handling can change the size of the screen
123 if (renderer->player.windowUpdated) {
124 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
125 _doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
126 renderer->player.windowUpdated = 0;
127 }
128#endif
129 }
130
131 v->postFrame(v, renderer->gb.outputBuffer);
132 v->drawFrame(v);
133 v->swap(v);
134 }
135}
136#endif
137
138void mSDLGLDeinit(struct mSDLRenderer* renderer) {
139 if (renderer->gl.d.deinit) {
140 renderer->gl.d.deinit(&renderer->gl.d);
141 }
142 free(renderer->d.outputBuffer);
143#if SDL_VERSION_ATLEAST(2, 0, 0)
144 SDL_GL_DeleteContext(renderer->glCtx);
145#endif
146}