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 size_t size = renderer->width * renderer->height * BYTES_PER_PIXEL;
32#ifdef _WIN32
33 renderer->outputBuffer = _aligned_malloc(size, 16);
34#elif defined(__linux__)
35 renderer->outputBuffer = memalign(16, size);
36#else
37 posix_memalign((void**) &renderer->outputBuffer, 16, size);
38#endif
39 memset(renderer->outputBuffer, 0, size);
40 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, renderer->width);
41
42 mGLES2ContextCreate(&renderer->gl2);
43 renderer->gl2.d.user = renderer;
44 renderer->gl2.d.lockAspectRatio = renderer->lockAspectRatio;
45 renderer->gl2.d.lockIntegerScaling = renderer->lockIntegerScaling;
46 renderer->gl2.d.filter = renderer->filter;
47#ifdef BUILD_RASPI
48 renderer->gl2.d.swap = mRPIGLCommonSwap;
49#else
50 renderer->gl2.d.swap = mSDLGLCommonSwap;
51#endif
52 renderer->gl2.d.init(&renderer->gl2.d, 0);
53 renderer->gl2.d.setDimensions(&renderer->gl2.d, renderer->width, renderer->height);
54
55 mSDLGLDoViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl2.d);
56 return true;
57}
58
59void mSDLGLES2Runloop(struct mSDLRenderer* renderer, void* user) {
60 struct mCoreThread* context = user;
61 SDL_Event event;
62 struct VideoBackend* v = &renderer->gl2.d;
63
64 while (mCoreThreadIsActive(context)) {
65 while (SDL_PollEvent(&event)) {
66 mSDLHandleEvent(context, &renderer->player, &event);
67 // Event handling can change the size of the screen
68 if (renderer->player.windowUpdated) {
69#if SDL_VERSION_ATLEAST(2, 0, 0)
70 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
71#else
72 renderer->viewportWidth = renderer->player.newWidth;
73 renderer->viewportHeight = renderer->player.newHeight;
74 mSDLGLCommonInit(renderer);
75#endif
76 mSDLGLDoViewport(renderer->viewportWidth, renderer->viewportHeight, v);
77 renderer->player.windowUpdated = 0;
78 }
79 }
80
81 if (mCoreSyncWaitFrameStart(&context->impl->sync)) {
82 v->postFrame(v, renderer->outputBuffer);
83 }
84 mCoreSyncWaitFrameEnd(&context->impl->sync);
85 v->drawFrame(v);
86 v->swap(v);
87 }
88}
89
90void mSDLGLES2Deinit(struct mSDLRenderer* renderer) {
91 if (renderer->gl2.d.deinit) {
92 renderer->gl2.d.deinit(&renderer->gl2.d);
93 }
94#ifdef BUILD_RASPI
95 eglMakeCurrent(renderer->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
96 eglDestroySurface(renderer->eglDisplay, renderer->eglSurface);
97 eglDestroyContext(renderer->eglDisplay, renderer->eglContext);
98 eglTerminate(renderer->eglDisplay);
99 bcm_host_deinit();
100#elif SDL_VERSION_ATLEAST(2, 0, 0)
101 SDL_GL_DeleteContext(renderer->glCtx);
102#endif
103 free(renderer->outputBuffer);
104}