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