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;
71 GLenum mnit_opengles_error_code;
73 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha );
77 extern NativeWindowType mnit_window;
78 extern EGLNativeDisplayType mnit_native_display;
80 GLfloat mnit_opengles_vertices[6][3] =
89 GLfloat mnit_opengles_texture[6][2] =
99 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
101 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
102 int format = has_alpha? GL_RGBA: GL_RGB;
104 image->width = width;
105 image->height = height;
106 image->center_x = width/2;
107 image->center_y = height/2;
109 image->blended = has_alpha;
117 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
118 LOGW ("a error loading image: %i\n", mnit_opengles_error_code);
119 printf( "%i\n", mnit_opengles_error_code );
121 glGenTextures(1, &image->texture);
123 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
124 LOGW ("b error loading image: %i\n", mnit_opengles_error_code);
125 printf( "%i\n", mnit_opengles_error_code );
127 glBindTexture(GL_TEXTURE_2D, image->texture);
129 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
130 LOGW ("c error loading image: %i\n", mnit_opengles_error_code);
131 printf( "%i\n", mnit_opengles_error_code );
133 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
134 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
136 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
137 LOGW ("d error loading image: %i\n", mnit_opengles_error_code);
138 printf( "%i\n", mnit_opengles_error_code );
140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
142 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
143 LOGW ("e error loading image: %i\n", mnit_opengles_error_code);
144 printf( "%i\n", mnit_opengles_error_code );
152 # Uses 3d hardware optimization
153 class Opengles1Display
156 redef type I
: Opengles1Image
159 fun midway_init
( format
: Int ) do end
160 fun extern_init
: Bool is extern import midway_init
`{
161 /* initialize OpenGL ES and EGL */
162 const EGLint attribs[] = {
163 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
169 EGLint w, h, dummy, format;
175 EGLDisplay display = eglGetDisplay(mnit_native_display);
176 if ( display == EGL_NO_DISPLAY) {
177 LOGW("Unable to eglGetDisplay");
181 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
182 LOGW("Unable to eglInitialize");
186 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
187 LOGW("Unable to eglChooseConfig");
191 if ( numConfigs == 0 ) {
192 LOGW("No configs available for egl");
196 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
197 LOGW("Unable to eglGetConfigAttrib");
201 /* Used by Android to set buffer geometry */
202 Opengles1Display_midway_init(recv, format);
204 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
205 context = eglCreateContext(display, config, NULL, NULL);
207 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
208 LOGW("Unable to eglMakeCurrent");
212 eglQuerySurface(display, surface, EGL_WIDTH, &w);
213 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
215 mnit_display = display;
216 mnit_context = context;
217 mnit_surface = surface;
218 mnit_config = config;
223 LOGI( "surface: %i, display: %i, w %i, h %i", (int)surface, (int)display, w, h );
225 glViewport(0, 0, mnit_width, mnit_height);
226 glMatrixMode(GL_PROJECTION);
228 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
229 glMatrixMode(GL_MODELVIEW);
231 glFrontFace( GL_CW );
236 fun close
is extern `{
237 if ( mnit_display != EGL_NO_DISPLAY) {
238 eglMakeCurrent( mnit_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
239 if ( mnit_context != EGL_NO_CONTEXT) {
240 eglDestroyContext( mnit_display, mnit_context );
242 if ( mnit_surface != EGL_NO_SURFACE) {
243 eglDestroySurface( mnit_display, mnit_surface );
245 eglTerminate( mnit_display);
247 mnit_display = EGL_NO_DISPLAY;
248 mnit_context = EGL_NO_CONTEXT;
249 mnit_surface = EGL_NO_SURFACE;
252 redef fun begin
is extern `{
253 glClear(GL_COLOR_BUFFER_BIT);
257 redef fun width
: Int is extern `{
260 redef fun height
: Int is extern `{
264 redef fun finish
is extern `{
265 eglSwapBuffers( mnit_display, mnit_surface );
268 fun set_as_target
is extern `{
269 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
272 redef fun set_viewport
( x
, y
, w
, h
) is extern `{
274 glViewport(0,0, mnit_width, mnit_height );
275 glMatrixMode(GL_PROJECTION);
277 glOrthof(x, x+w, y+h, y, 0.0f, 1.0f);
278 /*glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);*/
279 mnit_zoom = ((float)w)/mnit_width;
280 glMatrixMode(GL_MODELVIEW);
281 glFrontFace( GL_CW );
284 redef fun blit
( image
, x
, y
) is extern `{
285 GLfloat texture_coord[6][2] =
287 {image->src_xo, image->src_yo},
288 {image->src_xo, image->src_yi},
289 {image->src_xi, image->src_yi},
290 {image->src_xo, image->src_yo},
291 {image->src_xi, image->src_yi},
292 {image->src_xi, image->src_yo}
297 glBindTexture(GL_TEXTURE_2D, image->texture);
299 glEnableClientState(GL_VERTEX_ARRAY);
300 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
301 glTranslatef( x, y, 0.0f );
302 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
304 if ( image->blended ) {
306 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
309 glEnable(GL_TEXTURE_2D);
310 glDisable(GL_DEPTH_TEST);
312 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
313 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord ); /* mnit_opengles_texture); */
315 glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
317 glDisableClientState(GL_VERTEX_ARRAY);
318 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
319 if ( image->blended ) glDisable(GL_BLEND);
320 glDisable(GL_TEXTURE_2D);
322 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
323 LOGW ("error drawing: %i", mnit_opengles_error_code);
327 redef fun blit_centered
( img
, x
, y
)
334 redef fun blit_rotated
( image
, x
, y
, angle
) is extern `{
335 GLfloat texture_coord[6][2] =
337 {image->src_xo, image->src_yo},
338 {image->src_xo, image->src_yi},
339 {image->src_xi, image->src_yi},
340 {image->src_xo, image->src_yo},
341 {image->src_xi, image->src_yi},
342 {image->src_xi, image->src_yo}
347 glBindTexture(GL_TEXTURE_2D, image->texture);
349 glEnableClientState(GL_VERTEX_ARRAY);
350 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
351 glTranslatef( x, y, 0.0f );
352 glRotatef( angle*180.0f/3.14156f, 0, 0, 1.0f );
353 glTranslatef( image->width*image->scale/-2, image->height*image->scale/-2, 0.0f );
354 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
355 if ( image->blended ) {
357 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
359 glEnable(GL_TEXTURE_2D);
360 glDisable(GL_DEPTH_TEST);
362 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
363 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
365 glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
367 glDisableClientState(GL_VERTEX_ARRAY);
368 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
369 if ( image->blended ) glDisable(GL_BLEND);
370 glDisable(GL_TEXTURE_2D);
372 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
373 LOGW ("error drawing: %i", mnit_opengles_error_code);
376 # fun clear( r, g, b: Int ) is extern `{
377 # glClear(GL_COLOR_BUFFER_BIT);
380 # a = top left, b = bottom left, c = bottom right, d = top right
381 redef fun blit_stretched
( image
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
) is extern `{
382 GLfloat texture_coord[6][2] =
384 {image->src_xo, image->src_yo},
385 {image->src_xo, image->src_yi},
386 {image->src_xi, image->src_yi},
387 {image->src_xo, image->src_yo},
388 {image->src_xi, image->src_yi},
389 {image->src_xi, image->src_yo}
392 GLfloat mnit_opengles_vertices_stretched[6][3] =
404 glBindTexture(GL_TEXTURE_2D, image->texture);
406 glEnableClientState(GL_VERTEX_ARRAY);
407 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
409 if ( image->blended ) {
411 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
414 glEnable(GL_TEXTURE_2D);
415 glDisable(GL_DEPTH_TEST);
417 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
418 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
420 glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
422 glDisableClientState(GL_VERTEX_ARRAY);
423 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
424 if ( image->blended ) glDisable(GL_BLEND);
425 glDisable(GL_TEXTURE_2D);
427 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
428 LOGW ("error drawing: %i", mnit_opengles_error_code);
432 redef fun clear
( r
, g
, b
: Float ) is extern `{
433 glClearColor( r, g, b, 1.0 );
434 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
437 fun clear_alpha
( r
, g
, b
, a
: Float ) is extern `{
438 glClearColor( r, g, b, a );
439 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
443 extern Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
446 redef fun destroy is extern `{ free( recv ); `}
448 redef fun width
: Int is extern `{ return recv->width; `}
449 redef fun height: Int is extern `{ return recv->height; `}
451 fun center_x
: Int `{ return recv->center_x; `}
452 fun center_y: Int `{ return recv->center_y; `}
454 redef fun scale
=( v
: Float ) is extern `{
456 recv->center_x = v*recv->width/2;
457 recv->center_y = v*recv->height/2;
459 redef fun scale
: Float is extern `{ return recv->scale; `}
461 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
462 redef fun blended
: Bool is extern `{ return recv->blended; `}
464 # inherits scale and blend from source
465 redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
466 struct mnit_opengles_Texture
* image
=
467 malloc
( sizeof
( struct mnit_opengles_Texture
) );
469 image-
>texture
= recv-
>texture
;
472 image-
>center_x
= recv-
>scale
*w
/2;
473 image-
>center_y
= recv-
>scale
*h
/2;
474 image-
>scale
= recv-
>scale
;
475 image-
>blended
= recv-
>blended
;
477 image-
>src_xo
= ((float
)x
)/recv-
>width
;
478 image-
>src_yo
= ((float
)y
)/recv-
>height
;
479 image-
>src_xi
= ((float
)w
+w
)/recv-
>width
;
480 image-
>src_yi
= ((float
)x
+h
)/recv-
>height
;
482 return Opengles1Image_as_Image( image
);
487 extern Opengles1DrawableImage in "C" `{struct mnit_opengles_DrawableTexture*`}
489 new ( w
, h
: Int ) is extern `{
490 struct mnit_opengles_DrawableTexture *image =
491 malloc( sizeof(struct mnit_opengles_DrawableTexture) );
494 const EGLint attribs[] = {
497 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
498 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
502 image->surface = eglCreatePbufferSurface( andronit.display,
506 LOGW( "eglCreatePbuffer error" );
510 image->center_x = w/2;
511 image->center_y = h/2;
512 eglMakeCurrent( andronit.display,
519 glGenTextures(1, &image->super.texture);
520 glBindTexture(GL_TEXTURE_2D, image->super.texture);
521 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
522 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
523 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
524 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
525 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
526 /* glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4c */
527 glBindTexture(GL_TEXTURE_2D, 0);
530 glGenFramebuffersOES( 1, &image->fbo );
531 glBindFramebufferOES( GL_FRAMEBUFFER_OES, image->fbo );
532 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
533 GL_COLOR_ATTACHMENT0_OES,
535 image->super.texture,
539 glGenRenderbuffersOES(1, &image->depth);
540 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->depth);
541 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES,
543 glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
544 glFramebufferRenderbufferOES( GL_FRAMEBUFFER_OES,
545 GL_DEPTH_ATTACHMENT_OES,
549 /* tex framebuffer */
550 glGenRenderbuffersOES(1, &image->color);
551 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->color);
552 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, w, h);
553 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, image->color );
555 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) != GL_FRAMEBUFFER_COMPLETE_OES )
557 LOGW( "framebuffer not set" );
558 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES )
559 LOGW( "framebuffer not set a" );
560 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES )
561 LOGW( "framebuffer not set b" );
562 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES )
563 LOGW( "framebuffer not set c" );
564 else if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES )
565 LOGW( "framebuffer not set d" );
568 image->super.width = w;
569 image->super.height = h;
570 image->super.center_x = w/2;
571 image->super.center_y = h/2;
572 image->super.scale = 1.0f;
573 image->super.blended = 0;
577 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");
582 # fun image: I is extern `{
583 # struct mnit_opengles_Texture *image;
584 # const uint_least32_t *pixels;
585 # pixels = malloc( sizeof(uint_least32_t)*recv->width*recv->height );
586 # glReadPixels( 0, 0, recv->width, recv->height,
587 # GL_RGBA, GL_UNSIGNED_BYTE, pixels );
588 # image = mnit_opengles_load_image( pixels, recv->width, recv->height );
591 fun set_as_target
is extern `{
592 LOGI( "sat %i", recv->fbo );
593 glBindFramebufferOES(GL_FRAMEBUFFER_OES, recv->fbo);
594 /*glBindRenderbufferOES(GL_FRAMEBUFFER_OES, recv->color);*/
595 if (glGetError() != GL_NO_ERROR) LOGW( "gl error 0");
596 /*glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES,&recv->fbo);
597 //if (glGetError() != GL_NO_ERROR) LOGW( "gl error a");*/
598 glViewport(0, 0, recv->super.width, recv->super.height);
600 glMatrixMode(GL_PROJECTION);
602 glOrthof(0.0f, recv->super.width, recv->super.height, 0.0f, 0.0f, 1.0f);
603 glMatrixMode(GL_MODELVIEW);
604 glFrontFace( GL_CW );
606 glClearColor( 0.0f, 1.0f, 1.0f, 1.0f );
607 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
610 fun unset_as_target
is extern `{
612 /*glBindTexture(GL_TEXTURE_2D, recv->super.texture);
613 glGenerateMipmapOES(GL_TEXTURE_2D);
614 glBindTexture(GL_TEXTURE_2D, 0);*/
615 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
616 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");