metrics/rta: save the list of live things in files
[nit.git] / lib / mnit / opengles1.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2011-2013 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # OpenGL ES1 general support (most of it)
18 module opengles1
19
20 import display
21
22 in "C header" `{
23 #include <EGL/egl.h>
24 #include <GLES/gl.h>
25 #define GL_GLEXT_PROTOTYPES 1
26 #include <GLES/glext.h>
27 #include <errno.h>
28
29 #define LOGW(...) ((void)fprintf(stderr, "# warn: %s", __VA_ARGS__))
30 #ifdef DEBUG
31 #define LOGI(...) ((void)fprintf(stderr, "# info: %s", __VA_ARGS__))
32 #else
33 #define LOGI(...) (void)0
34 #endif
35
36 EGLDisplay mnit_display;
37 EGLSurface mnit_surface;
38 EGLContext mnit_context;
39 EGLConfig mnit_config;
40 int32_t mnit_width;
41 int32_t mnit_height;
42 float mnit_zoom;
43
44 struct mnit_opengles_Texture {
45 GLuint texture;
46
47 /* offsets on source texture */
48 float src_xo, src_yo, src_xi, src_yi;
49
50 /* destination width and height */
51 int width, height;
52
53 /* may vary depending on scaling */
54 int center_x, center_y;
55
56 float scale;
57 int blended;
58 };
59
60 struct mnit_opengles_DrawableTexture {
61 struct mnit_opengles_Texture super;
62 GLuint fbo;
63 GLuint depth;
64 GLuint color;
65 };
66
67 GLenum mnit_opengles_error_code;
68
69 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha );
70 `}
71
72 in "C" `{
73 extern NativeWindowType mnit_window;
74 extern EGLNativeDisplayType mnit_native_display;
75
76 GLfloat mnit_opengles_vertices[6][3] =
77 {
78 {0.0f, 1.0f, 0.0f},
79 {1.0f, 1.0f, 0.0f},
80 {0.0f, 0.0f, 0.0f},
81 {1.0f, 0.0f, 0.0f},
82 };
83 GLfloat mnit_opengles_texture[6][2] =
84 {
85 {0.0f, 0.0f},
86 {0.0f, 1.0f},
87 {1.0f, 1.0f},
88 {0.0f, 0.0f},
89 {1.0f, 1.0f},
90 {1.0f, 0.0f}
91 };
92
93 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
94 {
95 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
96 int format = has_alpha? GL_RGBA: GL_RGB;
97
98 image->width = width;
99 image->height = height;
100 image->center_x = width/2;
101 image->center_y = height/2;
102 image->scale = 1.0f;
103 image->blended = has_alpha;
104
105 image->src_xo = 0;
106 image->src_yo = 0;
107 image->src_xi = 1.0;
108 image->src_yi = 1.0;
109
110
111 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
112 LOGW ("a error loading image: %i\n", mnit_opengles_error_code);
113 printf( "%i\n", mnit_opengles_error_code );
114 }
115 glGenTextures(1, &image->texture);
116
117 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
118 LOGW ("b error loading image: %i\n", mnit_opengles_error_code);
119 printf( "%i\n", mnit_opengles_error_code );
120 }
121 glBindTexture(GL_TEXTURE_2D, image->texture);
122
123 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
124 LOGW ("c error loading image: %i\n", mnit_opengles_error_code);
125 printf( "%i\n", mnit_opengles_error_code );
126 }
127 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
128 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
129
130 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
131 LOGW ("d error loading image: %i\n", mnit_opengles_error_code);
132 printf( "%i\n", mnit_opengles_error_code );
133 }
134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
135
136 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
137 LOGW ("e error loading image: %i\n", mnit_opengles_error_code);
138 printf( "%i\n", mnit_opengles_error_code );
139 }
140
141 return image;
142 }
143 `}
144
145 # OpenGL ES1 display
146 # Uses 3d hardware optimization
147 class Opengles1Display
148 super Display
149
150 redef type I: Opengles1Image
151
152 init do extern_init
153 fun midway_init( format: Int ) do end
154 fun extern_init: Bool is extern import midway_init `{
155 /* initialize OpenGL ES and EGL */
156 const EGLint attribs[] = {
157 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
158 EGL_BLUE_SIZE, 8,
159 EGL_GREEN_SIZE, 8,
160 EGL_RED_SIZE, 8,
161 EGL_NONE
162 };
163 EGLint w, h, dummy, format;
164 EGLint numConfigs;
165 EGLConfig config;
166 EGLSurface surface;
167 EGLContext context;
168
169 EGLDisplay display = eglGetDisplay(mnit_native_display);
170 if ( display == EGL_NO_DISPLAY) {
171 LOGW("Unable to eglGetDisplay");
172 return -1;
173 }
174
175 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
176 LOGW("Unable to eglInitialize");
177 return -1;
178 }
179
180 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
181 LOGW("Unable to eglChooseConfig");
182 return -1;
183 }
184
185 if ( numConfigs == 0 ) {
186 LOGW("No configs available for egl");
187 return -1;
188 }
189
190 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
191 LOGW("Unable to eglGetConfigAttrib");
192 return -1;
193 }
194
195 /* Used by Android to set buffer geometry */
196 Opengles1Display_midway_init(recv, format);
197
198 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
199 context = eglCreateContext(display, config, NULL, NULL);
200
201 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
202 LOGW("Unable to eglMakeCurrent");
203 return -1;
204 }
205
206 eglQuerySurface(display, surface, EGL_WIDTH, &w);
207 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
208
209 mnit_display = display;
210 mnit_context = context;
211 mnit_surface = surface;
212 mnit_config = config;
213 mnit_width = w;
214 mnit_height = h;
215 mnit_zoom = 1.0f;
216
217 LOGI( "surface: %i, display: %i, w %i, h %i", (int)surface, (int)display, w, h );
218
219 glViewport(0, 0, mnit_width, mnit_height);
220 glMatrixMode(GL_PROJECTION);
221 glLoadIdentity();
222 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
223 glMatrixMode(GL_MODELVIEW);
224
225 glFrontFace( GL_CW );
226
227 return 0;
228 `}
229
230 fun close is extern `{
231 if ( mnit_display != EGL_NO_DISPLAY) {
232 eglMakeCurrent( mnit_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
233 if ( mnit_context != EGL_NO_CONTEXT) {
234 eglDestroyContext( mnit_display, mnit_context );
235 }
236 if ( mnit_surface != EGL_NO_SURFACE) {
237 eglDestroySurface( mnit_display, mnit_surface );
238 }
239 eglTerminate( mnit_display);
240 }
241 mnit_display = EGL_NO_DISPLAY;
242 mnit_context = EGL_NO_CONTEXT;
243 mnit_surface = EGL_NO_SURFACE;
244 `}
245
246 redef fun begin is extern `{
247 glClear(GL_COLOR_BUFFER_BIT);
248 glLoadIdentity();
249 `}
250
251 redef fun width: Int is extern `{
252 return mnit_width;
253 `}
254 redef fun height: Int is extern `{
255 return mnit_height;
256 `}
257
258 redef fun finish is extern `{
259 eglSwapBuffers( mnit_display, mnit_surface );
260 `}
261
262 fun set_as_target is extern `{
263 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
264 `}
265
266 redef fun set_viewport( x, y, w, h ) is extern `{
267 glLoadIdentity();
268 glViewport(0,0, mnit_width, mnit_height );
269 glMatrixMode(GL_PROJECTION);
270 glLoadIdentity();
271 glOrthof(x, x+w, y+h, y, 0.0f, 1.0f);
272 mnit_zoom = ((float)w)/mnit_width;
273 glMatrixMode(GL_MODELVIEW);
274 glFrontFace( GL_CW );
275 `}
276
277 redef fun blit( image, x, y ) is extern `{
278 GLfloat texture_coord[4][2] =
279 {
280 {image->src_xo, image->src_yi},
281 {image->src_xi, image->src_yi},
282 {image->src_xo, image->src_yo},
283 {image->src_xi, image->src_yo}
284 };
285
286 glLoadIdentity();
287
288 glBindTexture(GL_TEXTURE_2D, image->texture);
289
290 glEnableClientState(GL_VERTEX_ARRAY);
291 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
292 glTranslatef( x, y, 0.0f );
293 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
294
295 if ( image->blended ) {
296 glEnable(GL_BLEND);
297 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
298 }
299
300 glEnable(GL_TEXTURE_2D);
301 glDisable(GL_DEPTH_TEST);
302
303 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
304 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
305
306 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
307
308 glDisableClientState(GL_VERTEX_ARRAY);
309 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
310 if ( image->blended ) glDisable(GL_BLEND);
311 glDisable(GL_TEXTURE_2D);
312
313 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
314 LOGW ("error drawing: %i", mnit_opengles_error_code);
315 }
316 `}
317
318 redef fun blit_centered( img, x, y )
319 do
320 x = x - img.center_x
321 y = y - img.center_y
322 blit( img, x, y )
323 end
324
325 redef fun blit_rotated( image, x, y, angle ) is extern `{
326 GLfloat texture_coord[4][2] =
327 {
328 {image->src_xo, image->src_yi},
329 {image->src_xi, image->src_yi},
330 {image->src_xo, image->src_yo},
331 {image->src_xi, image->src_yo}
332 };
333
334 glLoadIdentity();
335
336 glBindTexture(GL_TEXTURE_2D, image->texture);
337
338 glEnableClientState(GL_VERTEX_ARRAY);
339 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
340 glTranslatef( x, y, 0.0f );
341 glRotatef( angle*180.0f/3.14156f, 0, 0, 1.0f );
342 glTranslatef( image->width*image->scale/-2, image->height*image->scale/-2, 0.0f );
343 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
344 if ( image->blended ) {
345 glEnable(GL_BLEND);
346 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
347 }
348 glEnable(GL_TEXTURE_2D);
349 glDisable(GL_DEPTH_TEST);
350
351 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
352 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
353
354 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
355
356 glDisableClientState(GL_VERTEX_ARRAY);
357 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
358 if ( image->blended ) glDisable(GL_BLEND);
359 glDisable(GL_TEXTURE_2D);
360
361 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
362 LOGW ("error drawing: %i", mnit_opengles_error_code);
363 }
364 `}
365
366 # a = top left, b = bottom left, c = bottom right, d = top right
367 redef fun blit_stretched( image, ax, ay, bx, by, cx, cy, dx, dy ) is extern `{
368 GLfloat texture_coord[4][2] =
369 {
370 {image->src_xo, image->src_yi},
371 {image->src_xi, image->src_yi},
372 {image->src_xo, image->src_yo},
373 {image->src_xi, image->src_yo}
374 };
375
376 GLfloat mnit_opengles_vertices_stretched[6][3] =
377 {
378 {bx, by, 0.0f},
379 {cx, cy, 0.0f},
380 {ax, ay, 0.0f},
381 {dx, dy, 0.0f},
382 };
383
384 glLoadIdentity();
385
386 glBindTexture(GL_TEXTURE_2D, image->texture);
387
388 glEnableClientState(GL_VERTEX_ARRAY);
389 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
390
391 if ( image->blended ) {
392 glEnable(GL_BLEND);
393 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
394 }
395
396 glEnable(GL_TEXTURE_2D);
397 glDisable(GL_DEPTH_TEST);
398
399 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
400 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
401
402 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
403
404 glDisableClientState(GL_VERTEX_ARRAY);
405 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
406 if ( image->blended ) glDisable(GL_BLEND);
407 glDisable(GL_TEXTURE_2D);
408
409 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
410 LOGW ("error drawing: %i", mnit_opengles_error_code);
411 }
412 `}
413
414 redef fun clear( r, g, b: Float ) is extern `{
415 glClearColor( r, g, b, 1.0 );
416 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
417 `}
418
419 fun clear_alpha( r, g, b, a: Float ) is extern `{
420 glClearColor( r, g, b, a );
421 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
422 `}
423 end
424
425 extern Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
426 super Image
427
428 redef fun destroy is extern `{ free( recv ); `}
429
430 redef fun width: Int is extern `{ return recv->width; `}
431 redef fun height: Int is extern `{ return recv->height; `}
432
433 fun center_x: Int `{ return recv->center_x; `}
434 fun center_y: Int `{ return recv->center_y; `}
435
436 redef fun scale=( v: Float ) is extern `{
437 recv->scale = v;
438 recv->center_x = v*recv->width/2;
439 recv->center_y = v*recv->height/2;
440 `}
441 redef fun scale: Float is extern `{ return recv->scale; `}
442
443 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
444 redef fun blended: Bool is extern `{ return recv->blended; `}
445
446 # inherits scale and blend from source
447 redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
448 struct mnit_opengles_Texture* image =
449 malloc( sizeof( struct mnit_opengles_Texture ) );
450
451 image->texture = recv->texture;
452 image->width = w;
453 image->height = h;
454 image->center_x = recv->scale*w/2;
455 image->center_y = recv->scale*h/2;
456 image->scale = recv->scale;
457 image->blended = recv->blended;
458
459 image->src_xo = ((float)x)/recv->width;
460 image->src_yo = ((float)y)/recv->height;
461 image->src_xi = ((float)x+w)/recv->width;
462 image->src_yi = ((float)y+h)/recv->height;
463
464 return Opengles1Image_as_Image( image );
465 `}
466 end
467
468 # FIXME this class is broken
469 extern Opengles1DrawableImage in "C" `{struct mnit_opengles_DrawableTexture*`}
470 super DrawableImage
471 new ( w, h: Int ) is extern `{
472 struct mnit_opengles_DrawableTexture *image =
473 malloc( sizeof(struct mnit_opengles_DrawableTexture) );
474
475 /* texture */
476 glGenTextures(1, &image->super.texture);
477 glBindTexture(GL_TEXTURE_2D, image->super.texture);
478 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
481 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
483 /* glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4c */
484 glBindTexture(GL_TEXTURE_2D, 0);
485
486 /* fbo */
487 glGenFramebuffersOES( 1, &image->fbo );
488 glBindFramebufferOES( GL_FRAMEBUFFER_OES, image->fbo );
489 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
490 GL_COLOR_ATTACHMENT0_OES,
491 GL_TEXTURE_2D,
492 image->super.texture,
493 0 );
494
495 /* depth */
496 glGenRenderbuffersOES(1, &image->depth);
497 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->depth);
498 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES,
499 w, h);
500 glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
501 glFramebufferRenderbufferOES( GL_FRAMEBUFFER_OES,
502 GL_DEPTH_ATTACHMENT_OES,
503 GL_RENDERBUFFER_OES,
504 image->depth );
505
506 /* tex framebuffer */
507 glGenRenderbuffersOES(1, &image->color);
508 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->color);
509 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, w, h);
510 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, image->color );
511
512 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) != GL_FRAMEBUFFER_COMPLETE_OES )
513 {
514 LOGW( "framebuffer not set" );
515 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES )
516 LOGW( "framebuffer not set a" );
517 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES )
518 LOGW( "framebuffer not set b" );
519 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES )
520 LOGW( "framebuffer not set c" );
521 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES )
522 LOGW( "framebuffer not set d" );
523 }
524
525 image->super.width = w;
526 image->super.height = h;
527 image->super.center_x = w/2;
528 image->super.center_y = h/2;
529 image->super.scale = 1.0f;
530 image->super.blended = 0;
531
532 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");
533
534 return image;
535 `}
536
537 fun set_as_target is extern `{
538 LOGI( "sat %i", recv->fbo );
539 glBindFramebufferOES(GL_FRAMEBUFFER_OES, recv->fbo);
540 if (glGetError() != GL_NO_ERROR) LOGW( "gl error 0");
541 /*glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES,&recv->fbo);
542 if (glGetError() != GL_NO_ERROR) LOGW( "gl error a");*/
543 glViewport(0, 0, recv->super.width, recv->super.height);
544
545 glMatrixMode(GL_PROJECTION);
546 glLoadIdentity();
547 glOrthof(0.0f, recv->super.width, recv->super.height, 0.0f, 0.0f, 1.0f);
548 glMatrixMode(GL_MODELVIEW);
549 glFrontFace( GL_CW );
550
551 glClearColor( 0.0f, 1.0f, 1.0f, 1.0f );
552 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
553 `}
554
555 fun unset_as_target is extern `{
556 glFlush();
557 /*glBindTexture(GL_TEXTURE_2D, recv->super.texture);
558 glGenerateMipmapOES(GL_TEXTURE_2D);
559 glBindTexture(GL_TEXTURE_2D, 0);*/
560 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
561 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");
562 `}
563 end
564