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 renderer->audio.psg = &context->gba->audio.psg;
69
70 while (context->state < THREAD_EXITING) {
71 while (SDL_PollEvent(&event)) {
72 mSDLHandleEventGBA(context, &renderer->player, &event);
73#if SDL_VERSION_ATLEAST(2, 0, 0)
74 // Event handling can change the size of the screen
75 if (renderer->player.windowUpdated) {
76 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
77 _doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
78 renderer->player.windowUpdated = 0;
79 }
80#endif
81 }
82
83 if (mCoreSyncWaitFrameStart(&context->sync)) {
84 v->postFrame(v, renderer->d.outputBuffer);
85 }
86 mCoreSyncWaitFrameEnd(&context->sync);
87 v->drawFrame(v);
88 v->swap(v);
89 }
90
91 renderer->audio.psg = 0;
92}
93
94void mSDLGLDeinitGBA(struct mSDLRenderer* renderer) {
95 if (renderer->gl.d.deinit) {
96 renderer->gl.d.deinit(&renderer->gl.d);
97 }
98 free(renderer->d.outputBuffer);
99#if SDL_VERSION_ATLEAST(2, 0, 0)
100 SDL_GL_DeleteContext(renderer->glCtx);
101#endif
102}
103#endif
104
105#ifdef M_CORE_GB
106void mSDLGLCreateGB(struct mSDLRenderer* renderer) {
107 renderer->init = mSDLGLInitGB;
108 renderer->deinit = mSDLGLDeinitGB;
109 renderer->runloop = mSDLGLRunloopGB;
110}
111
112bool mSDLGLInitGB(struct mSDLRenderer* renderer) {
113 mSDLGLCommonInit(renderer);
114
115 // TODO: Pass texture size along
116 renderer->outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
117 memset(renderer->outputBuffer, 0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
118 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer + GB_GBA_CENTER, VIDEO_HORIZONTAL_PIXELS);
119
120 GBAGLContextCreate(&renderer->gl);
121 renderer->gl.d.user = renderer;
122 renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
123 renderer->gl.d.filter = renderer->filter;
124 renderer->gl.d.swap = mSDLGLCommonSwap;
125 renderer->gl.d.init(&renderer->gl.d, 0);
126
127 _doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
128 return true;
129}
130
131void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) {
132 struct mCoreThread* context = user;
133 SDL_Event event;
134 struct VideoBackend* v = &renderer->gl.d;
135 renderer->audio.psg = &((struct GB*) renderer->core->board)->audio;
136
137 while (context->state < THREAD_EXITING) {
138 while (SDL_PollEvent(&event)) {
139 mSDLHandleEvent(context, &renderer->player, &event);
140#if SDL_VERSION_ATLEAST(2, 0, 0)
141 // Event handling can change the size of the screen
142 if (renderer->player.windowUpdated) {
143 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
144 _doViewport(renderer->viewportWidth, renderer->viewportHeight, v);
145 renderer->player.windowUpdated = 0;
146 }
147#endif
148 }
149
150 if (mCoreSyncWaitFrameStart(&context->sync)) {
151 v->postFrame(v, renderer->outputBuffer);
152 }
153 mCoreSyncWaitFrameEnd(&context->sync);
154 v->drawFrame(v);
155 v->swap(v);
156 }
157 renderer->audio.psg = 0;
158}
159
160void mSDLGLDeinitGB(struct mSDLRenderer* renderer) {
161 if (renderer->gl.d.deinit) {
162 renderer->gl.d.deinit(&renderer->gl.d);
163 }
164 free(renderer->outputBuffer);
165#if SDL_VERSION_ATLEAST(2, 0, 0)
166 SDL_GL_DeleteContext(renderer->glCtx);
167#endif
168}
169#endif