9 #include "gl_platform.h"
12 static EGLDisplay edpy = EGL_NO_DISPLAY;
13 static EGLSurface esfc = EGL_NO_SURFACE;
14 static EGLContext ectxt = EGL_NO_CONTEXT;
16 static GLuint texture_name;
18 /* for external flips */
22 static int tex_w, tex_h;
24 static int flip_old_w, flip_old_h;
26 static int gl_have_error(const char *name)
28 GLenum e = glGetError();
29 if (e != GL_NO_ERROR) {
30 fprintf(stderr, "GL error: %s %x\n", name, e);
36 static int gles_have_error(const char *name)
38 EGLint e = eglGetError();
39 if (e != EGL_SUCCESS) {
40 fprintf(stderr, "%s %x\n", name, e);
46 int gl_init(void *display, int *quirks)
51 ret = gl_platform_init(&display, quirks);
53 fprintf(stderr, "gl_platform_init failed with %d\n", ret);
57 edpy = eglGetDisplay((EGLNativeDisplayType)display);
58 if (edpy == EGL_NO_DISPLAY) {
59 fprintf(stderr, "Failed to get EGL display\n");
63 if (!eglInitialize(edpy, NULL, NULL)) {
64 fprintf(stderr, "Failed to initialize EGL\n");
70 if (retval && edpy != EGL_NO_DISPLAY)
75 int gl_create(void *window, int *quirks, int w, int h)
77 EGLConfig ecfg = NULL;
81 EGLint config_attr[] =
86 ret = gl_platform_create(&window, quirks);
88 fprintf(stderr, "gl_platform_init failed with %d\n", ret);
92 flip_old_w = flip_old_h = 0;
93 for (tex_w = 1; tex_w < w; tex_w *= 2)
95 for (tex_h = 1; tex_h < h; tex_h *= 2)
97 tex_mem = realloc(tex_mem, tex_w * tex_h * 2);
98 if (tex_mem == NULL) {
99 fprintf(stderr, "OOM\n");
102 memset(tex_mem, 0, tex_w * tex_h * 2);
104 if (!eglChooseConfig(edpy, config_attr, &ecfg, 1, &num_config)) {
105 fprintf(stderr, "Failed to choose config (%x)\n", eglGetError());
109 if (ecfg == NULL || num_config == 0) {
110 fprintf(stderr, "No EGL configs available\n");
114 esfc = eglCreateWindowSurface(edpy, ecfg,
115 (EGLNativeWindowType)window, NULL);
116 if (esfc == EGL_NO_SURFACE) {
117 fprintf(stderr, "Unable to create EGL surface (%x)\n",
122 ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, NULL);
123 if (ectxt == EGL_NO_CONTEXT) {
124 fprintf(stderr, "Unable to create EGL context (%x)\n",
126 // on mesa, some distros disable ES1.x but compat GL still works
127 ret = eglBindAPI(EGL_OPENGL_API);
129 fprintf(stderr, "eglBindAPI: %x\n", eglGetError());
132 ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, NULL);
133 if (ectxt == EGL_NO_CONTEXT) {
134 fprintf(stderr, "giving up on EGL context (%x)\n",
140 ret = eglMakeCurrent(edpy, esfc, esfc, ectxt);
142 fprintf(stderr, "eglMakeCurrent: %x\n", eglGetError());
146 ret = *quirks & GL_QUIRK_VSYNC_ON ? 1 : 0;
147 eglSwapInterval(edpy, ret);
149 // 1.x (fixed-function) only
150 glEnable(GL_TEXTURE_2D);
153 assert(!texture_name);
155 glGenTextures(1, &texture_name);
156 if (gl_have_error("glGenTextures"))
159 glBindTexture(GL_TEXTURE_2D, texture_name);
160 if (gl_have_error("glBindTexture"))
163 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h, 0, GL_RGB,
164 GL_UNSIGNED_SHORT_5_6_5, tex_mem);
165 if (gl_have_error("glTexImage2D"))
169 ret = *quirks & GL_QUIRK_SCALING_NEAREST ? GL_NEAREST : GL_LINEAR;
170 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ret);
171 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ret);
173 //glViewport(0, 0, 512, 512);
176 glEnable(GL_CULL_FACE);
178 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
179 glEnableClientState(GL_VERTEX_ARRAY);
181 if (gl_have_error("init"))
184 gl_es_display = (void *)edpy;
185 gl_es_surface = (void *)esfc;
188 if (retval && edpy != EGL_NO_DISPLAY)
193 void gl_announce(void)
195 printf("GL_RENDERER: %s\n", (char *)glGetString(GL_RENDERER));
196 printf("GL_VERSION: %s\n", (char *)glGetString(GL_VERSION));
199 static const float default_vertices[] = {
200 -1.0f, 1.0f, 0.0f, // 0 0 1
201 1.0f, 1.0f, 0.0f, // 1 ^
202 -1.0f, -1.0f, 0.0f, // 2 | 2 3
203 1.0f, -1.0f, 0.0f, // 3 +-->
206 static float texture[] = {
207 0.0f, 0.0f, // we flip this:
213 int gl_flip_v(const void *fb, int w, int h, const float *vertices)
215 gl_have_error("pre-flip unknown");
217 glBindTexture(GL_TEXTURE_2D, texture_name);
218 if (gl_have_error("glBindTexture"))
222 if (w != flip_old_w || h != flip_old_h) {
223 float f_w = (float)w / tex_w;
224 float f_h = (float)h / tex_h;
225 texture[1*2 + 0] = f_w;
226 texture[2*2 + 1] = f_h;
227 texture[3*2 + 0] = f_w;
228 texture[3*2 + 1] = f_h;
233 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
234 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb);
235 if (gl_have_error("glTexSubImage2D")) {
236 fprintf(stderr, " %dx%d t: %dx%d %p\n", w, h, tex_w, tex_h, fb);
241 glVertexPointer(3, GL_FLOAT, 0, vertices ? vertices : default_vertices);
242 glTexCoordPointer(2, GL_FLOAT, 0, texture);
243 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
244 if (gl_have_error("glDrawArrays"))
247 eglSwapBuffers(edpy, esfc);
248 if (gles_have_error("eglSwapBuffers"))
254 int gl_flip(const void *fb, int w, int h)
256 return gl_flip_v(fb, w, h, NULL);
259 // to be used once after exiting menu, etc
262 glClearColor(0, 0, 0, 0);
263 glClear(GL_COLOR_BUFFER_BIT);
264 eglSwapBuffers(edpy, esfc);
265 glClear(GL_COLOR_BUFFER_BIT);
266 eglSwapBuffers(edpy, esfc);
267 glClear(GL_COLOR_BUFFER_BIT);
268 gl_have_error("glClear");
271 void gl_destroy(void)
273 if (edpy == EGL_NO_DISPLAY)
274 return; // nothing to do
276 // sometimes there is an error... from somewhere?
277 //gl_have_error("finish");
282 glDeleteTextures(1, &texture_name);
283 gl_have_error("glDeleteTextures");
287 eglMakeCurrent(edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
288 if (ectxt != EGL_NO_CONTEXT) {
289 eglDestroyContext(edpy, ectxt);
290 ectxt = EGL_NO_CONTEXT;
292 if (esfc != EGL_NO_SURFACE) {
293 eglDestroySurface(edpy, esfc);
294 esfc = EGL_NO_SURFACE;
297 gl_es_surface = (void *)esfc;
299 if (tex_mem) free(tex_mem);
302 gl_platform_destroy();
305 void gl_shutdown(void)
307 if (edpy != EGL_NO_DISPLAY) {
309 edpy = EGL_NO_DISPLAY;
312 gl_es_display = (void *)edpy;
314 gl_platform_shutdown();