src/platform/sdl/egl-sdl.c (view raw)
1#include "main.h"
2
3static const char* _vertexShader =
4 "attribute vec4 position;\n"
5 "varying vec2 texCoord;\n"
6
7 "void main() {\n"
8 " gl_Position = position;\n"
9 " texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.46875, -0.3125);\n"
10 "}";
11
12static const char* _fragmentShader =
13 "varying vec2 texCoord;\n"
14 "uniform sampler2D tex;\n"
15
16 "void main() {\n"
17 " vec4 color = texture2D(tex, texCoord);\n"
18 " color.a = 1.;\n"
19 " gl_FragColor = color;"
20 "}";
21
22static const GLfloat _vertices[] = {
23 -1.f, -1.f,
24 -1.f, 1.f,
25 1.f, 1.f,
26 1.f, -1.f,
27};
28
29bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
30 bcm_host_init();
31 renderer->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
32 int major, minor;
33 if (EGL_FALSE == eglInitialize(renderer->display, &major, &minor)) {
34 printf("Failed to initialize EGL");
35 return false;
36 }
37
38 if (EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) {
39 printf("Failed to get GLES API");
40 return false;
41 }
42
43 const EGLint requestConfig[] = {
44 EGL_RED_SIZE, 5,
45 EGL_GREEN_SIZE, 5,
46 EGL_BLUE_SIZE, 5,
47 EGL_ALPHA_SIZE, 1,
48 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
49 EGL_NONE
50 };
51
52 EGLConfig config;
53 EGLint numConfigs;
54
55 if (EGL_FALSE == eglChooseConfig(renderer->display, requestConfig, &config, 1, &numConfigs)) {
56 printf("Failed to choose EGL config\n");
57 return false;
58 }
59
60 const EGLint contextAttributes[] = {
61 EGL_CONTEXT_CLIENT_VERSION, 2,
62 EGL_NONE
63 };
64
65 int dispWidth = 240, dispHeight = 160, adjWidth;
66 renderer->context = eglCreateContext(renderer->display, config, EGL_NO_CONTEXT, contextAttributes);
67 graphics_get_display_size(0, &dispWidth, &dispHeight);
68 adjWidth = dispHeight / 2 * 3;
69
70 DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0);
71 DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
72
73 VC_RECT_T destRect = {
74 .x = (dispWidth - adjWidth) / 2,
75 .y = 0,
76 .width = adjWidth,
77 .height = dispHeight
78 };
79
80 VC_RECT_T srcRect = {
81 .x = 0,
82 .y = 0,
83 .width = 240 << 16,
84 .height = 160 << 16
85 };
86
87 DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update, display, 0, &destRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, 0);
88 vc_dispmanx_update_submit_sync(update);
89
90 renderer->window.element = element;
91 renderer->window.width = dispWidth;
92 renderer->window.height = dispHeight;
93
94 renderer->surface = eglCreateWindowSurface(renderer->display, config, &renderer->window, 0);
95 if (EGL_FALSE == eglMakeCurrent(renderer->display, renderer->surface, renderer->surface, renderer->context)) {
96 return false;
97 }
98
99 renderer->d.outputBuffer = memalign(16, 256 * 256 * 4);
100 renderer->d.outputBufferStride = 256;
101 glGenTextures(1, &renderer->tex);
102 glBindTexture(GL_TEXTURE_2D, renderer->tex);
103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
107 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
108 renderer->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
109 renderer->vertexShader = glCreateShader(GL_VERTEX_SHADER);
110 renderer->program = glCreateProgram();
111
112 glShaderSource(renderer->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
113 glShaderSource(renderer->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
114 glAttachShader(renderer->program, renderer->vertexShader);
115 glAttachShader(renderer->program, renderer->fragmentShader);
116 char log[1024];
117 glCompileShader(renderer->fragmentShader);
118 glCompileShader(renderer->vertexShader);
119 glGetShaderInfoLog(renderer->fragmentShader, 1024, 0, log);
120 glGetShaderInfoLog(renderer->vertexShader, 1024, 0, log);
121 glLinkProgram(renderer->program);
122 glGetProgramInfoLog(renderer->program, 1024, 0, log);
123 printf("%s\n", log);
124 renderer->texLocation = glGetUniformLocation(renderer->program, "tex");
125 renderer->positionLocation = glGetAttribLocation(renderer->program, "position");
126 glClearColor(1.f, 0.f, 0.f, 1.f);
127}
128
129void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
130 SDL_Event event;
131
132 while (context->state < THREAD_EXITING) {
133 while (SDL_PollEvent(&event)) {
134 GBASDLHandleEvent(context, &renderer->events, &event);
135 }
136
137 if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
138 glViewport(0, 0, 240, 160);
139 glClear(GL_COLOR_BUFFER_BIT);
140 glUseProgram(renderer->program);
141 glUniform1i(renderer->texLocation, 0);
142 glActiveTexture(GL_TEXTURE0);
143 glBindTexture(GL_TEXTURE_2D, renderer->tex);
144 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer);
145 glVertexAttribPointer(renderer->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
146 glEnableVertexAttribArray(renderer->positionLocation);
147 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
148 glUseProgram(0);
149 eglSwapBuffers(renderer->display, renderer->surface);
150 }
151 GBASyncWaitFrameEnd(&context->sync);
152 }
153}
154
155void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
156 eglMakeCurrent(renderer->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
157 eglDestroySurface(renderer->display, renderer->surface);
158 eglDestroyContext(renderer->display, renderer->context);
159 eglTerminate(renderer->display);
160 bcm_host_deinit();
161}