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] =
83 GLfloat mnit_opengles_texture[6][2] =
93 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
95 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
96 int format = has_alpha? GL_RGBA: GL_RGB;
99 image->height = height;
100 image->center_x = width/2;
101 image->center_y = height/2;
103 image->blended = has_alpha;
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 );
115 glGenTextures(1, &image->texture);
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 );
121 glBindTexture(GL_TEXTURE_2D, image->texture);
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 );
127 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
128 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
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 );
134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
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 );
146 # Uses 3d hardware optimization
147 class Opengles1Display
150 redef type I
: Opengles1Image
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,
163 EGLint w, h, dummy, format;
169 EGLDisplay display = eglGetDisplay(mnit_native_display);
170 if ( display == EGL_NO_DISPLAY) {
171 LOGW("Unable to eglGetDisplay");
175 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
176 LOGW("Unable to eglInitialize");
180 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
181 LOGW("Unable to eglChooseConfig");
185 if ( numConfigs == 0 ) {
186 LOGW("No configs available for egl");
190 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
191 LOGW("Unable to eglGetConfigAttrib");
195 /* Used by Android to set buffer geometry */
196 Opengles1Display_midway_init(recv, format);
198 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
199 context = eglCreateContext(display, config, NULL, NULL);
201 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
202 LOGW("Unable to eglMakeCurrent");
206 eglQuerySurface(display, surface, EGL_WIDTH, &w);
207 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
209 mnit_display = display;
210 mnit_context = context;
211 mnit_surface = surface;
212 mnit_config = config;
217 LOGI( "surface: %i, display: %i, w %i, h %i", (int)surface, (int)display, w, h );
219 glViewport(0, 0, mnit_width, mnit_height);
220 glMatrixMode(GL_PROJECTION);
222 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
223 glMatrixMode(GL_MODELVIEW);
225 glFrontFace( GL_CW );
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 );
236 if ( mnit_surface != EGL_NO_SURFACE) {
237 eglDestroySurface( mnit_display, mnit_surface );
239 eglTerminate( mnit_display);
241 mnit_display = EGL_NO_DISPLAY;
242 mnit_context = EGL_NO_CONTEXT;
243 mnit_surface = EGL_NO_SURFACE;
246 redef fun begin
is extern `{
247 glClear(GL_COLOR_BUFFER_BIT);
251 redef fun width
: Int is extern `{
254 redef fun height
: Int is extern `{
258 redef fun finish
is extern `{
259 eglSwapBuffers( mnit_display, mnit_surface );
262 fun set_as_target
is extern `{
263 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
266 redef fun set_viewport
( x
, y
, w
, h
) is extern `{
268 glViewport(0,0, mnit_width, mnit_height );
269 glMatrixMode(GL_PROJECTION);
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 );
277 redef fun blit
( image
, x
, y
) is extern `{
278 GLfloat texture_coord[4][2] =
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}
288 glBindTexture(GL_TEXTURE_2D, image->texture);
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 );
295 if ( image->blended ) {
297 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
300 glEnable(GL_TEXTURE_2D);
301 glDisable(GL_DEPTH_TEST);
303 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
304 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
306 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
308 glDisableClientState(GL_VERTEX_ARRAY);
309 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
310 if ( image->blended ) glDisable(GL_BLEND);
311 glDisable(GL_TEXTURE_2D);
313 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
314 LOGW ("error drawing: %i", mnit_opengles_error_code);
318 redef fun blit_centered
( img
, x
, y
)
325 redef fun blit_rotated
( image
, x
, y
, angle
) is extern `{
326 GLfloat texture_coord[4][2] =
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}
336 glBindTexture(GL_TEXTURE_2D, image->texture);
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 ) {
346 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
348 glEnable(GL_TEXTURE_2D);
349 glDisable(GL_DEPTH_TEST);
351 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
352 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
354 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
356 glDisableClientState(GL_VERTEX_ARRAY);
357 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
358 if ( image->blended ) glDisable(GL_BLEND);
359 glDisable(GL_TEXTURE_2D);
361 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
362 LOGW ("error drawing: %i", mnit_opengles_error_code);
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] =
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}
376 GLfloat mnit_opengles_vertices_stretched[6][3] =
386 glBindTexture(GL_TEXTURE_2D, image->texture);
388 glEnableClientState(GL_VERTEX_ARRAY);
389 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
391 if ( image->blended ) {
393 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
396 glEnable(GL_TEXTURE_2D);
397 glDisable(GL_DEPTH_TEST);
399 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
400 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
402 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
404 glDisableClientState(GL_VERTEX_ARRAY);
405 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
406 if ( image->blended ) glDisable(GL_BLEND);
407 glDisable(GL_TEXTURE_2D);
409 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
410 LOGW ("error drawing: %i", mnit_opengles_error_code);
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);
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);
425 extern Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
428 redef fun destroy is extern `{ free( recv ); `}
430 redef fun width
: Int is extern `{ return recv->width; `}
431 redef fun height: Int is extern `{ return recv->height; `}
433 fun center_x
: Int `{ return recv->center_x; `}
434 fun center_y: Int `{ return recv->center_y; `}
436 redef fun scale
=( v
: Float ) is extern `{
438 recv->center_x = v*recv->width/2;
439 recv->center_y = v*recv->height/2;
441 redef fun scale
: Float is extern `{ return recv->scale; `}
443 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
444 redef fun blended
: Bool is extern `{ return recv->blended; `}
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
) );
451 image-
>texture
= recv-
>texture
;
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
;
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
;
464 return Opengles1Image_as_Image( image
);
468 # FIXME this class is broken
469 extern Opengles1DrawableImage in "C" `{struct mnit_opengles_DrawableTexture*`}
471 new ( w
, h
: Int ) is extern `{
472 struct mnit_opengles_DrawableTexture *image =
473 malloc( sizeof(struct mnit_opengles_DrawableTexture) );
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);
487 glGenFramebuffersOES( 1, &image->fbo );
488 glBindFramebufferOES( GL_FRAMEBUFFER_OES, image->fbo );
489 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
490 GL_COLOR_ATTACHMENT0_OES,
492 image->super.texture,
496 glGenRenderbuffersOES(1, &image->depth);
497 glBindRenderbufferOES(GL_RENDERBUFFER_OES, image->depth);
498 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES,
500 glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
501 glFramebufferRenderbufferOES( GL_FRAMEBUFFER_OES,
502 GL_DEPTH_ATTACHMENT_OES,
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 );
512 if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) != GL_FRAMEBUFFER_COMPLETE_OES )
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" );
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;
532 if (glGetError() != GL_NO_ERROR) LOGW( "gl error");
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);
545 glMatrixMode(GL_PROJECTION);
547 glOrthof(0.0f, recv->super.width, recv->super.height, 0.0f, 0.0f, 1.0f);
548 glMatrixMode(GL_MODELVIEW);
549 glFrontFace( GL_CW );
551 glClearColor( 0.0f, 1.0f, 1.0f, 1.0f );
552 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
555 fun unset_as_target
is extern `{
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");