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