src/platform/sdl/gles2-sdl.c (view raw)
1/* Copyright (c) 2013-2016 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#ifdef BUILD_RASPI
10#include "rpi-common.h"
11#endif
12
13#include <mgba/core/core.h>
14#include <mgba/core/thread.h>
15
16#ifdef __linux__
17#include <malloc.h>
18#endif
19
20static bool mSDLGLES2Init(struct mSDLRenderer* renderer);
21static void mSDLGLES2Runloop(struct mSDLRenderer* renderer, void* user);
22static void mSDLGLES2Deinit(struct mSDLRenderer* renderer);
23
24void mSDLGLES2Create(struct mSDLRenderer* renderer) {
25 renderer->init = mSDLGLES2Init;
26 renderer->deinit = mSDLGLES2Deinit;
27 renderer->runloop = mSDLGLES2Runloop;
28}
29
30bool mSDLGLES2Init(struct mSDLRenderer* renderer) {
31#ifdef BUILD_RASPI
32 mRPIGLCommonInit(renderer);
33#else
34 mSDLGLCommonInit(renderer);
35#endif
36
37 size_t size = renderer->width * renderer->height * BYTES_PER_PIXEL;
38#ifdef _WIN32
39 renderer->outputBuffer = _aligned_malloc(size, 16);
40#elif defined(__linux__)
41 renderer->outputBuffer = memalign(16, size);
42#else
43 posix_memalign((void**) &renderer->outputBuffer, 16, size);
44#endif
45 memset(renderer->outputBuffer, 0, size);
46 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, renderer->width);
47
48 mGLES2ContextCreate(&renderer->gl2);
49 renderer->gl2.d.user = renderer;
50 renderer->gl2.d.lockAspectRatio = renderer->lockAspectRatio;
51 renderer->gl2.d.lockIntegerScaling = renderer->lockIntegerScaling;
52 renderer->gl2.d.filter = renderer->filter;
53#ifdef BUILD_RASPI
54 renderer->gl2.d.swap = mRPIGLCommonSwap;
55#else
56 renderer->gl2.d.swap = mSDLGLCommonSwap;
57#endif
58 renderer->gl2.d.init(&renderer->gl2.d, 0);
59 renderer->gl2.d.setDimensions(&renderer->gl2.d, renderer->width, renderer->height);
60
61 mSDLGLDoViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl2.d);
62 return true;
63}
64
65void mSDLGLES2Runloop(struct mSDLRenderer* renderer, void* user) {
66 struct mCoreThread* context = user;
67 SDL_Event event;
68 struct VideoBackend* v = &renderer->gl2.d;
69
70 while (mCoreThreadIsActive(context)) {
71 while (SDL_PollEvent(&event)) {
72 mSDLHandleEvent(context, &renderer->player, &event);
73 // Event handling can change the size of the screen
74 if (renderer->player.windowUpdated) {
75#if SDL_VERSION_ATLEAST(2, 0, 0)
76 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
77#else
78 renderer->viewportWidth = renderer->player.newWidth;
79 renderer->viewportHeight = renderer->player.newHeight;
80 mSDLGLCommonInit(renderer);
81#endif
82 mSDLGLDoViewport(renderer->viewportWidth, renderer->viewportHeight, v);
83 renderer->player.windowUpdated = 0;
84 }
85 }
86
87 if (mCoreSyncWaitFrameStart(&context->impl->sync)) {
88 v->postFrame(v, renderer->outputBuffer);
89 }
90 mCoreSyncWaitFrameEnd(&context->impl->sync);
91 v->drawFrame(v);
92 v->swap(v);
93 }
94}
95
96void mSDLGLES2Deinit(struct mSDLRenderer* renderer) {
97 if (renderer->gl2.d.deinit) {
98 renderer->gl2.d.deinit(&renderer->gl2.d);
99 }
100#ifdef BUILD_RASPI
101 eglMakeCurrent(renderer->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
102 eglDestroySurface(renderer->eglDisplay, renderer->eglSurface);
103 eglDestroyContext(renderer->eglDisplay, renderer->eglContext);
104 eglTerminate(renderer->eglDisplay);
105 bcm_host_deinit();
106#elif SDL_VERSION_ATLEAST(2, 0, 0)
107 SDL_GL_DeleteContext(renderer->glCtx);
108#endif
109 free(renderer->outputBuffer);
110}