add triplebuffering support
[libpicofe.git] / gl.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <EGL/egl.h>
5 #include <GLES/gl.h>
6 #include "gl_platform.h"
7 #include "gl.h"
8
9 static EGLDisplay edpy;
10 static EGLSurface esfc;
11 static EGLContext ectxt;
12
13 /* for external flips */
14 void *gl_es_display;
15 void *gl_es_surface;
16
17 static int gl_have_error(const char *name)
18 {
19         GLenum e = glGetError();
20         if (e != GL_NO_ERROR) {
21                 fprintf(stderr, "GL error: %s %x\n", name, e);
22                 return 1;
23         }
24         return 0;
25 }
26
27 static int gles_have_error(const char *name)
28 {
29         EGLint e = eglGetError();
30         if (e != EGL_SUCCESS) {
31                 fprintf(stderr, "%s %x\n", name, e);
32                 return 1;
33         }
34         return 0;
35 }
36
37 int gl_init(void *display, void *window, int *quirks)
38 {
39         EGLConfig ecfg = NULL;
40         GLuint texture_name = 0;
41         void *tmp_texture_mem = NULL;
42         EGLint num_config;
43         int retval = -1;
44         int ret;
45         EGLint attr[] =
46         {
47                 EGL_NONE
48         };
49
50         ret = gl_platform_init(&display, &window, quirks);
51         if (ret != 0) {
52                 fprintf(stderr, "gl_platform_init failed with %d\n", ret);
53                 goto out;
54         }
55
56         tmp_texture_mem = calloc(1, 1024 * 512 * 2);
57         if (tmp_texture_mem == NULL) {
58                 fprintf(stderr, "OOM\n");
59                 goto out;
60         }
61
62         edpy = eglGetDisplay((EGLNativeDisplayType)display);
63         if (edpy == EGL_NO_DISPLAY) {
64                 fprintf(stderr, "Failed to get EGL display\n");
65                 goto out;
66         }
67
68         if (!eglInitialize(edpy, NULL, NULL)) {
69                 fprintf(stderr, "Failed to initialize EGL\n");
70                 goto out;
71         }
72
73         if (!eglChooseConfig(edpy, attr, &ecfg, 1, &num_config)) {
74                 fprintf(stderr, "Failed to choose config (%x)\n", eglGetError());
75                 goto out;
76         }
77
78         if (ecfg == NULL || num_config == 0) {
79                 fprintf(stderr, "No EGL configs available\n");
80                 goto out;
81         }
82
83         esfc = eglCreateWindowSurface(edpy, ecfg,
84                 (EGLNativeWindowType)window, NULL);
85         if (esfc == EGL_NO_SURFACE) {
86                 fprintf(stderr, "Unable to create EGL surface (%x)\n",
87                         eglGetError());
88                 goto out;
89         }
90
91         ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, NULL);
92         if (ectxt == EGL_NO_CONTEXT) {
93                 fprintf(stderr, "Unable to create EGL context (%x)\n",
94                         eglGetError());
95                 goto out;
96         }
97
98         eglMakeCurrent(edpy, esfc, esfc, ectxt);
99
100         glEnable(GL_TEXTURE_2D);
101
102         glGenTextures(1, &texture_name);
103
104         glBindTexture(GL_TEXTURE_2D, texture_name);
105
106         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 512, 0, GL_RGB,
107                 GL_UNSIGNED_SHORT_5_6_5, tmp_texture_mem);
108         if (gl_have_error("glTexImage2D"))
109                 goto out;
110
111         // no mipmaps
112         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
113         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
114
115         //glViewport(0, 0, 512, 512);
116         glLoadIdentity();
117         glFrontFace(GL_CW);
118         glEnable(GL_CULL_FACE);
119
120         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
121         glEnableClientState(GL_VERTEX_ARRAY);
122
123         if (gl_have_error("init"))
124                 goto out;
125
126         gl_es_display = (void *)edpy;
127         gl_es_surface = (void *)esfc;
128         retval = 0;
129 out:
130         free(tmp_texture_mem);
131         return retval;
132 }
133
134 static float vertices[] = {
135         -1.0f,  1.0f,  0.0f, // 0    0  1
136          1.0f,  1.0f,  0.0f, // 1  ^
137         -1.0f, -1.0f,  0.0f, // 2  | 2  3
138          1.0f, -1.0f,  0.0f, // 3  +-->
139 };
140
141 static float texture[] = {
142         0.0f, 0.0f, // we flip this:
143         1.0f, 0.0f, // v^
144         0.0f, 1.0f, //  |  u
145         1.0f, 1.0f, //  +-->
146 };
147
148 int gl_flip(const void *fb, int w, int h)
149 {
150         static int old_w, old_h;
151
152         if (fb != NULL) {
153                 if (w != old_w || h != old_h) {
154                         float f_w = (float)w / 1024.0f;
155                         float f_h = (float)h / 512.0f;
156                         texture[1*2 + 0] = f_w;
157                         texture[2*2 + 1] = f_h;
158                         texture[3*2 + 0] = f_w;
159                         texture[3*2 + 1] = f_h;
160                         old_w = w;
161                         old_h = h;
162                 }
163
164                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
165                         GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb);
166                 if (gl_have_error("glTexSubImage2D"))
167                         return -1;
168         }
169
170         glVertexPointer(3, GL_FLOAT, 0, vertices);
171         glTexCoordPointer(2, GL_FLOAT, 0, texture);
172         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
173
174         if (gl_have_error("glDrawArrays"))
175                 return -1;
176
177         eglSwapBuffers(edpy, esfc);
178         if (gles_have_error("eglSwapBuffers"))
179                 return -1;
180
181         return 0;
182 }
183
184 void gl_finish(void)
185 {
186         eglMakeCurrent(edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
187         eglDestroyContext(edpy, ectxt);
188         ectxt = EGL_NO_CONTEXT;
189         eglDestroySurface(edpy, esfc);
190         esfc = EGL_NO_SURFACE;
191         eglTerminate(edpy);
192         edpy = EGL_NO_DISPLAY;
193
194         gl_es_display = (void *)edpy;
195         gl_es_surface = (void *)esfc;
196
197         gl_platform_finish();
198 }