1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2011-2013 Alexis Laferrière <alexis.laf@xymus.net>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # OpenGL ES1 general support (most of it)
25 #define GL_GLEXT_PROTOTYPES 1
26 #include <GLES/glext.h>
29 #define LOGW(...) ((void)fprintf(stderr, "# warn: %s", __VA_ARGS__))
31 #define LOGI(...) ((void)fprintf(stderr, "# info: %s", __VA_ARGS__))
33 #define LOGI(...) (void)0
36 EGLDisplay mnit_display;
37 EGLSurface mnit_surface;
38 EGLContext mnit_context;
39 EGLConfig mnit_config;
44 struct mnit_opengles_Texture {
47 /* offsets on source texture */
48 float src_xo, src_yo, src_xi, src_yi;
50 /* destination width and height */
53 /* may vary depending on scaling */
54 int center_x, center_y;
60 struct mnit_opengles_DrawableTexture {
61 struct mnit_opengles_Texture super;
67 GLenum mnit_opengles_error_code;
69 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha );
73 extern NativeWindowType mnit_window;
74 extern EGLNativeDisplayType mnit_native_display;
76 GLfloat mnit_opengles_vertices[6][3] =
85 GLfloat mnit_opengles_texture[6][2] =
95 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
97 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
98 int format = has_alpha? GL_RGBA: GL_RGB;
100 image->width = width;
101 image->height = height;
102 image->center_x = width/2;
103 image->center_y = height/2;
105 image->blended = has_alpha;
113 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
114 LOGW ("a error loading image: %i\n", mnit_opengles_error_code);
115 printf( "%i\n", mnit_opengles_error_code );
117 glGenTextures(1, &image->texture);
119 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
120 LOGW ("b error loading image: %i\n", mnit_opengles_error_code);
121 printf( "%i\n", mnit_opengles_error_code );
123 glBindTexture(GL_TEXTURE_2D, image->texture);
125 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
126 LOGW ("c error loading image: %i\n", mnit_opengles_error_code);
127 printf( "%i\n", mnit_opengles_error_code );
129 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
130 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
132 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
133 LOGW ("d error loading image: %i\n", mnit_opengles_error_code);
134 printf( "%i\n", mnit_opengles_error_code );
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
138 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
139 LOGW ("e error loading image: %i\n", mnit_opengles_error_code);
140 printf( "%i\n", mnit_opengles_error_code );
148 # Uses 3d hardware optimization
149 class Opengles1Display
152 redef type I
: Opengles1Image
155 fun midway_init
( format
: Int ) do end
156 fun extern_init
: Bool is extern import midway_init
`{
157 /* initialize OpenGL ES and EGL */
158 const EGLint attribs[] = {
159 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
165 EGLint w, h, dummy, format;
171 EGLDisplay display = eglGetDisplay(mnit_native_display);
172 if ( display == EGL_NO_DISPLAY) {
173 LOGW("Unable to eglGetDisplay");
177 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
178 LOGW("Unable to eglInitialize");
182 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
183 LOGW("Unable to eglChooseConfig");
187 if ( numConfigs == 0 ) {
188 LOGW("No configs available for egl");
192 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
193 LOGW("Unable to eglGetConfigAttrib");
197 /* Used by Android to set buffer geometry */
198 Opengles1Display_midway_init(recv, format);
200 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
201 context = eglCreateContext(display, config, NULL, NULL);
203 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
204 LOGW("Unable to eglMakeCurrent");
208 eglQuerySurface(display, surface, EGL_WIDTH, &w);
209 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
211 mnit_display = display;
212 mnit_context = context;
213 mnit_surface = surface;
214 mnit_config = config;
219 LOGI( "surface: %i, display: %i, w %i, h %i", (int)surface, (int)display, w, h );
221 glViewport(0, 0, mnit_width, mnit_height);
222 glMatrixMode(GL_PROJECTION);
224 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
225 glMatrixMode(GL_MODELVIEW);
227 glFrontFace( GL_CW );
232 fun close
is extern `{
233 if ( mnit_display != EGL_NO_DISPLAY) {
234 eglMakeCurrent( mnit_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
235 if ( mnit_context != EGL_NO_CONTEXT) {
236 eglDestroyContext( mnit_display, mnit_context );
238 if ( mnit_surface != EGL_NO_SURFACE) {
239 eglDestroySurface( mnit_display, mnit_surface );
241 eglTerminate( mnit_display);
243 mnit_display = EGL_NO_DISPLAY;
244 mnit_context = EGL_NO_CONTEXT;
245 mnit_surface = EGL_NO_SURFACE;
248 redef fun begin
is extern `{
249 glClear(GL_COLOR_BUFFER_BIT);
253 redef fun width
: Int is extern `{
256 redef fun height
: Int is extern `{
260 redef fun finish
is extern `{
261 eglSwapBuffers( mnit_display, mnit_surface );
264 fun set_as_target
is extern `{
265 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
268 redef fun set_viewport
( x
, y
, w
, h
) is extern `{
270 glViewport(0,0, mnit_width, mnit_height );
271 glMatrixMode(GL_PROJECTION);
273 glOrthof(x, x+w, y+h, y, 0.0f, 1.0f);
274 mnit_zoom = ((float)w)/mnit_width;
275 glMatrixMode(GL_MODELVIEW);
276 glFrontFace( GL_CW );
279 redef fun blit
( image
, x
, y
) is extern `{
280 GLfloat texture_coord[6][2] =
282 {image->src_xo, image->src_yo},
283 {image->src_xo, image->src_yi},
284 {image->src_xi, image->src_yi},
285 {image->src_xo, image->src_yo},
286 {image->src_xi, image->src_yi},
287 {image->src_xi, image->src_yo}
292 glBindTexture(GL_TEXTURE_2D, image->texture);
294 glEnableClientState(GL_VERTEX_ARRAY);
295 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
296 glTranslatef( x, y, 0.0f );
297 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
299 if ( image->blended ) {
301 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
304 glEnable(GL_TEXTURE_2D);
305 glDisable(GL_DEPTH_TEST);
307 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
308 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord ); /* mnit_opengles_texture); */
310 glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
312 glDisableClientState(GL_VERTEX_ARRAY);
313 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
314 if ( image->blended ) glDisable(GL_BLEND);
315 glDisable(GL_TEXTURE_2D);
317 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
318 LOGW ("error drawing: %i", mnit_opengles_error_code);
322 redef fun blit_centered
( img
, x
, y
)
329 redef fun blit_rotated
( image
, x
, y
, angle
) is extern `{
330 GLfloat texture_coord[6][2] =
332 {image->src_xo, image->src_yo},
333 {image->src_xo, image->src_yi},
334 {image->src_xi, image->src_yi},
335 {image->src_xo, image->src_yo},
336 {image->src_xi, image->src_yi},
337 {image->src_xi, image->src_yo}
342 glBindTexture(GL_TEXTURE_2D, image->texture);
344 glEnableClientState(GL_VERTEX_ARRAY);
345 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
346 glTranslatef( x, y, 0.0f );
347 glRotatef( angle*180.0f/3.14156f, 0, 0, 1.0f );
348 glTranslatef( image->width*image->scale/-2, image->height*image->scale/-2, 0.0f );
349 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
350 if ( image->blended ) {
352 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
354 glEnable(GL_TEXTURE_2D);
355 glDisable(GL_DEPTH_TEST);
357 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
358 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
360 glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
362 glDisableClientState(GL_VERTEX_ARRAY);
363 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
364 if ( image->blended ) glDisable(GL_BLEND);
365 glDisable(GL_TEXTURE_2D);
367 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
368 LOGW ("error drawing: %i", mnit_opengles_error_code);
372 # a = top left, b = bottom left, c = bottom right, d = top right
373 redef fun blit_stretched
( image
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
) is extern `{
374 GLfloat texture_coord[4][2] =
376 {image->src_xo, image->src_yi},
377 {image->src_xi, image->src_yi},
378 {image->src_xo, image->src_yo},
379 {image->src_xi, image->src_yo}
382 GLfloat mnit_opengles_vertices_stretched[6][3] =
392 glBindTexture(GL_TEXTURE_2D, image->texture);
394 glEnableClientState(GL_VERTEX_ARRAY);
395 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
397 if ( image->blended ) {
399 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
402 glEnable(GL_TEXTURE_2D);
403 glDisable(GL_DEPTH_TEST);
405 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
406 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
408 glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
410 glDisableClientState(GL_VERTEX_ARRAY);
411 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
412 if ( image->blended ) glDisable(GL_BLEND);
413 glDisable(GL_TEXTURE_2D);
415 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
416 LOGW ("error drawing: %i", mnit_opengles_error_code);
420 redef fun clear
( r
, g
, b
: Float ) is extern `{
421 glClearColor( r, g, b, 1.0 );
422 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
425 fun clear_alpha
( r
, g
, b
, a
: Float ) is extern `{
426 glClearColor( r, g, b, a );
427 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
431 extern Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
434 redef fun destroy is extern `{ free( recv ); `}
436 redef fun width
: Int is extern `{ return recv->width; `}
437 redef fun height: Int is extern `{ return recv->height; `}
439 fun center_x
: Int `{ return recv->center_x; `}
440 fun center_y: Int `{ return recv->center_y; `}
442 redef fun scale
=( v
: Float ) is extern `{
444 recv->center_x = v*recv->width/2;
445 recv->center_y = v*recv->height/2;
447 redef fun scale
: Float is extern `{ return recv->scale; `}
449 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
450 redef fun blended
: Bool is extern `{ return recv->blended; `}
452 # inherits scale and blend from source
453 redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
454 struct mnit_opengles_Texture
* image
=
455 malloc
( sizeof
( struct mnit_opengles_Texture
) );
457 image-
>texture
= recv-
>texture
;
460 image-
>center_x
= recv-
>scale
*w
/2;
461 image-
>center_y
= recv-
>scale
*h
/2;
462 image-
>scale
= recv-
>scale
;
463 image-
>blended
= recv-
>blended
;
465 image-
>src_xo
= ((float
)x
)/recv-
>width
;
466 image-
>src_yo
= ((float
)y
)/recv-
>height
;
467 image-
>src_xi
= ((float
)w
+w
)/recv-
>width
;
468 image-
>src_yi
= ((float
)x
+h
)/recv-
>height
;
470 return Opengles1Image_as_Image( image
);
474 # FIXME this class is broken
475 extern Opengles1DrawableImage in "C" `{struct mnit_opengles_DrawableTexture*`}
477 new ( w
, h
: Int ) is extern `{
478 struct mnit_opengles_DrawableTexture *image =
479 malloc( sizeof(struct mnit_opengles_DrawableTexture) );
482 glGenTextures(1, &image->super.texture);
483 glBindTexture(GL_TEXTURE_2D, image->super.texture);
484 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
485 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
486 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
487 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
489 /* glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4c */
490 glBindTexture(GL_TEXTURE_2D, 0);
493 glGenFramebuffersOES( 1, &image->fbo );
494 glBindFramebufferOES( GL_FRAMEBUFFER_OES, image->fbo );
495 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
496 GL_COLOR_ATTACHMENT0_OES,
498 image->super.texture,
502 glGenRenderbuffersOES(1, &image->depth);
503 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->depth);
504 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES,
506 glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
507 glFramebufferRenderbufferOES( GL_FRAMEBUFFER_OES,
508 GL_DEPTH_ATTACHMENT_OES,
512 /* tex framebuffer */
513 glGenRenderbuffersOES(1, &image->color);
514 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->color);
515 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, w, h);
516 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, image->color );
518 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) != GL_FRAMEBUFFER_COMPLETE_OES )
520 LOGW( "framebuffer not set" );
521 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES )
522 LOGW( "framebuffer not set a" );
523 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES )
524 LOGW( "framebuffer not set b" );
525 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES )
526 LOGW( "framebuffer not set c" );
527 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES )
528 LOGW( "framebuffer not set d" );
531 image->super.width = w;
532 image->super.height = h;
533 image->super.center_x = w/2;
534 image->super.center_y = h/2;
535 image->super.scale = 1.0f;
536 image->super.blended = 0;
538 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");
543 fun set_as_target
is extern `{
544 LOGI( "sat %i", recv->fbo );
545 glBindFramebufferOES(GL_FRAMEBUFFER_OES, recv->fbo);
546 if (glGetError() != GL_NO_ERROR) LOGW( "gl error 0");
547 /*glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES,&recv->fbo);
548 if (glGetError() != GL_NO_ERROR) LOGW( "gl error a");*/
549 glViewport(0, 0, recv->super.width, recv->super.height);
551 glMatrixMode(GL_PROJECTION);
553 glOrthof(0.0f, recv->super.width, recv->super.height, 0.0f, 0.0f, 1.0f);
554 glMatrixMode(GL_MODELVIEW);
555 glFrontFace( GL_CW );
557 glClearColor( 0.0f, 1.0f, 1.0f, 1.0f );
558 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
561 fun unset_as_target
is extern `{
563 /*glBindTexture(GL_TEXTURE_2D, recv->super.texture);
564 glGenerateMipmapOES(GL_TEXTURE_2D);
565 glBindTexture(GL_TEXTURE_2D, 0);*/
566 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
567 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");