src/egl-main.c (view raw)
1#include "debugger.h"
2#include "gba-thread.h"
3#include "gba.h"
4#include "renderers/video-glsl.h"
5#include "sdl-events.h"
6
7#include <SDL.h>
8#include <GLES2/gl2.h>
9#include <EGL/egl.h>
10
11#include <bcm_host.h>
12
13#include <fcntl.h>
14#include <errno.h>
15#include <signal.h>
16#include <sys/time.h>
17#include <unistd.h>
18
19struct GBAVideoEGLRenderer {
20 struct GBAVideoGLSLRenderer d;
21
22 EGLDisplay display;
23 EGLSurface surface;
24 EGLContext context;
25};
26
27static int _GBAEGLInit(struct GBAVideoEGLRenderer* renderer);
28static void _GBAEGLDeinit(struct GBAVideoEGLRenderer* renderer);
29static void _GBAEGLRunloop(struct GBAThread* context, struct GBAVideoEGLRenderer* renderer);
30
31int main(int argc, char** argv) {
32 const char* fname = "test.rom";
33 if (argc > 1) {
34 fname = argv[1];
35 }
36 int fd = open(fname, O_RDONLY);
37 if (fd < 0) {
38 return 1;
39 }
40
41 struct GBAThread context;
42 struct GBAVideoEGLRenderer renderer;
43
44 if (!_GBAEGLInit(&renderer)) {
45 return 1;
46 }
47 GBAVideoGLSLRendererCreate(&renderer.d);
48
49 context.fd = fd;
50 context.renderer = &renderer.d.d;
51 GBAThreadStart(&context);
52
53 _GBAEGLRunloop(&context, &renderer);
54
55 GBAThreadJoin(&context);
56 close(fd);
57
58 _GBAEGLDeinit(&renderer);
59
60 return 0;
61}
62
63static int _GBAEGLInit(struct GBAVideoEGLRenderer* renderer) {
64 if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
65 return 0;
66 }
67
68 GBASDLInitEvents();
69 bcm_host_init();
70 renderer->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
71 int major, minor;
72 if (EGL_FALSE == eglInitialize(renderer->display, &major, &minor)) {
73 printf("Failed to initialize EGL");
74 return 0;
75 }
76
77 if (EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) {
78 printf("Failed to get GLES API");
79 return 0;
80 }
81
82 const EGLint requestConfig[] = {
83 EGL_RED_SIZE, 8,
84 EGL_GREEN_SIZE, 8,
85 EGL_BLUE_SIZE, 8,
86 EGL_ALPHA_SIZE, 8,
87 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
88 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
89 EGL_NONE
90 };
91
92 EGLConfig config;
93 EGLint numConfigs;
94
95 if (EGL_FALSE == eglChooseConfig(renderer->display, requestConfig, &config, 1, &numConfigs)) {
96 printf("Failed to choose EGL config\n");
97 return 0;
98 }
99
100 const EGLint contextAttributes[] = {
101 EGL_CONTEXT_CLIENT_VERSION, 2,
102 EGL_NONE
103 };
104
105 renderer->context = eglCreateContext(renderer->display, config, EGL_NO_CONTEXT, contextAttributes);
106
107 DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0);
108 DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
109
110 VC_RECT_T destRect = {
111 .x = 0,
112 .y = 0,
113 .width = 240,
114 .height = 160
115 };
116
117 VC_RECT_T srcRect = {
118 .x = 0,
119 .y = 0,
120 .width = 240,
121 .height = 160
122 };
123
124 DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update, display, 0, &destRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, DISPMANX_NO_ROTATE);
125 vc_dispmanx_update_submit_sync(update);
126
127 EGL_DISPMANX_WINDOW_T window = {
128 .element = element,
129 .width = 240,
130 .height = 160
131 };
132
133 renderer->surface = eglCreateWindowSurface(renderer->display, config, &window, 0);
134 return EGL_TRUE == eglMakeCurrent(renderer->display, renderer->surface, renderer->surface, renderer->context);
135}
136
137static void _GBAEGLRunloop(struct GBAThread* context, struct GBAVideoEGLRenderer* renderer) {
138 SDL_Event event;
139
140 while (context->started && context->debugger->state != DEBUGGER_EXITING) {
141 GBAVideoGLSLRendererProcessEvents(&renderer->d);
142 pthread_mutex_lock(&renderer->d.mutex);
143 if (renderer->d.d.framesPending) {
144 renderer->d.d.framesPending = 0;
145 pthread_mutex_unlock(&renderer->d.mutex);
146
147 eglSwapBuffers(renderer->display, renderer->surface);
148
149 while (SDL_PollEvent(&event)) {
150 GBASDLHandleEvent(context, &event);
151 }
152 pthread_mutex_lock(&renderer->d.mutex);
153 pthread_cond_broadcast(&renderer->d.downCond);
154 } else {
155 pthread_cond_broadcast(&renderer->d.downCond);
156 pthread_cond_wait(&renderer->d.upCond, &renderer->d.mutex);
157 }
158 pthread_mutex_unlock(&renderer->d.mutex);
159 }
160}
161
162static void _GBAEGLDeinit(struct GBAVideoEGLRenderer* renderer) {
163 eglMakeCurrent(renderer->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
164 eglDestroySurface(renderer->display, renderer->surface);
165 eglDestroyContext(renderer->display, renderer->context);
166 eglTerminate(renderer->display);
167
168 GBASDLDeinitEvents();
169 SDL_Quit();
170
171 bcm_host_deinit();
172}