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)
18 module opengles1
is pkgconfig
("glesv1_cm", "egl")
26 EGLDisplay mnit_display;
27 EGLSurface mnit_surface;
28 EGLContext mnit_context;
29 EGLConfig mnit_config;
34 struct mnit_opengles_Texture {
37 /* offsets on source texture */
38 float src_xo, src_yo, src_xi, src_yi;
40 /* destination width and height */
43 /* may vary depending on scaling */
44 int center_x, center_y;
50 struct mnit_opengles_DrawableTexture {
51 struct mnit_opengles_Texture super;
57 GLenum mnit_opengles_error_code;
59 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha );
63 #define LOGW(...) ((void)fprintf(stderr, "# warn: %s (%i)\n", __VA_ARGS__))
65 #define LOGI(...) ((void)fprintf(stderr, "# info: %s (%i)\n", __VA_ARGS__))
67 #define LOGI(...) (void)0
70 extern NativeWindowType mnit_window;
71 extern EGLNativeDisplayType mnit_native_display;
73 GLfloat mnit_opengles_vertices[6][3] =
80 GLfloat mnit_opengles_texture[6][2] =
90 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
92 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
93 int format = has_alpha? GL_RGBA: GL_RGB;
96 image->height = height;
97 image->center_x = width/2;
98 image->center_y = height/2;
100 image->blended = has_alpha;
107 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
108 LOGW("error loading image after malloc", mnit_opengles_error_code);
111 glGenTextures(1, &image->texture);
113 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
114 LOGW("error loading image after glGenTextures", mnit_opengles_error_code);
117 glBindTexture(GL_TEXTURE_2D, image->texture);
119 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
120 LOGW("error loading image glBindTexture", mnit_opengles_error_code);
123 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
124 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
126 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
127 LOGW("error loading image after glTexImage2D", mnit_opengles_error_code);
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
132 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
133 LOGW("error loading image after gtTexParameter", mnit_opengles_error_code);
141 # Uses 3d hardware optimization
142 class Opengles1Display
145 redef type I
: Opengles1Image
148 fun midway_init
( format
: Int ) do end
149 fun extern_init
: Bool is extern import midway_init
`{
150 /* initialize OpenGL ES and EGL */
151 const EGLint attribs[] = {
152 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
158 EGLint w, h, dummy, format;
164 EGLDisplay display = eglGetDisplay(mnit_native_display);
165 if ( display == EGL_NO_DISPLAY) {
166 LOGW("Unable to eglGetDisplay", 0);
170 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
171 LOGW("Unable to eglInitialize", 0);
175 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
176 LOGW("Unable to eglChooseConfig", 0);
180 if ( numConfigs == 0 ) {
181 LOGW("No configs available for egl", 0);
185 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
186 LOGW("Unable to eglGetConfigAttrib", 0);
190 /* Used by Android to set buffer geometry */
191 Opengles1Display_midway_init(recv, format);
193 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
194 context = eglCreateContext(display, config, NULL, NULL);
196 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
197 LOGW("Unable to eglMakeCurrent", 0);
201 eglQuerySurface(display, surface, EGL_WIDTH, &w);
202 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
204 mnit_display = display;
205 mnit_context = context;
206 mnit_surface = surface;
207 mnit_config = config;
212 LOGI("surface", (int)surface);
213 LOGI("display", (int)display);
217 glViewport(0, 0, mnit_width, mnit_height);
218 glMatrixMode(GL_PROJECTION);
220 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
221 glMatrixMode(GL_MODELVIEW);
223 glFrontFace( GL_CW );
228 fun close
is extern `{
229 if ( mnit_display != EGL_NO_DISPLAY) {
230 eglMakeCurrent( mnit_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
231 if ( mnit_context != EGL_NO_CONTEXT) {
232 eglDestroyContext( mnit_display, mnit_context );
234 if ( mnit_surface != EGL_NO_SURFACE) {
235 eglDestroySurface( mnit_display, mnit_surface );
237 eglTerminate( mnit_display);
239 mnit_display = EGL_NO_DISPLAY;
240 mnit_context = EGL_NO_CONTEXT;
241 mnit_surface = EGL_NO_SURFACE;
244 redef fun begin
is extern `{
245 glClear(GL_COLOR_BUFFER_BIT);
249 redef fun width
: Int is extern `{
252 redef fun height
: Int is extern `{
256 redef fun finish
is extern `{
257 eglSwapBuffers( mnit_display, mnit_surface );
260 redef fun set_viewport
( x
, y
, w
, h
) is extern `{
262 glViewport(0,0, mnit_width, mnit_height );
263 glMatrixMode(GL_PROJECTION);
265 glOrthof(x, x+w, y+h, y, 0.0f, 1.0f);
266 mnit_zoom = ((float)w)/mnit_width;
267 glMatrixMode(GL_MODELVIEW);
268 glFrontFace( GL_CW );
271 redef fun blit
( image
, x
, y
) is extern `{
272 GLfloat texture_coord[4][2] =
274 {image->src_xo, image->src_yi},
275 {image->src_xi, image->src_yi},
276 {image->src_xo, image->src_yo},
277 {image->src_xi, image->src_yo}
282 glBindTexture(GL_TEXTURE_2D, image->texture);
284 glEnableClientState(GL_VERTEX_ARRAY);
285 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
286 glTranslatef( x, y, 0.0f );
287 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
289 if ( image->blended ) {
291 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
294 glEnable(GL_TEXTURE_2D);
295 glDisable(GL_DEPTH_TEST);
297 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
298 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
300 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
302 glDisableClientState(GL_VERTEX_ARRAY);
303 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
304 if ( image->blended ) glDisable(GL_BLEND);
305 glDisable(GL_TEXTURE_2D);
307 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
308 LOGW("error drawing", mnit_opengles_error_code);
312 redef fun blit_centered
( img
, x
, y
)
319 redef fun blit_rotated
( image
, x
, y
, angle
) is extern `{
320 GLfloat texture_coord[4][2] =
322 {image->src_xo, image->src_yi},
323 {image->src_xi, image->src_yi},
324 {image->src_xo, image->src_yo},
325 {image->src_xi, image->src_yo}
330 glBindTexture(GL_TEXTURE_2D, image->texture);
332 glEnableClientState(GL_VERTEX_ARRAY);
333 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
334 glTranslatef( x, y, 0.0f );
335 glRotatef( angle*180.0f/3.14156f, 0, 0, 1.0f );
336 glTranslatef( image->width*image->scale/-2, image->height*image->scale/-2, 0.0f );
337 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
338 if ( image->blended ) {
340 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
342 glEnable(GL_TEXTURE_2D);
343 glDisable(GL_DEPTH_TEST);
345 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
346 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
348 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
350 glDisableClientState(GL_VERTEX_ARRAY);
351 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
352 if ( image->blended ) glDisable(GL_BLEND);
353 glDisable(GL_TEXTURE_2D);
355 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
356 LOGW("error drawing", mnit_opengles_error_code);
360 # a = top left, b = bottom left, c = bottom right, d = top right
361 redef fun blit_stretched
( image
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
) is extern `{
362 GLfloat texture_coord[4][2] =
364 {image->src_xo, image->src_yi},
365 {image->src_xi, image->src_yi},
366 {image->src_xo, image->src_yo},
367 {image->src_xi, image->src_yo}
370 GLfloat mnit_opengles_vertices_stretched[6][3] =
380 glBindTexture(GL_TEXTURE_2D, image->texture);
382 glEnableClientState(GL_VERTEX_ARRAY);
383 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
385 if ( image->blended ) {
387 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
390 glEnable(GL_TEXTURE_2D);
391 glDisable(GL_DEPTH_TEST);
393 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
394 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
396 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
398 glDisableClientState(GL_VERTEX_ARRAY);
399 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
400 if ( image->blended ) glDisable(GL_BLEND);
401 glDisable(GL_TEXTURE_2D);
403 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
404 LOGW("error drawing", mnit_opengles_error_code);
408 redef fun clear
( r
, g
, b
: Float ) is extern `{
409 glClearColor( r, g, b, 1.0 );
410 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
413 fun clear_alpha
( r
, g
, b
, a
: Float ) is extern `{
414 glClearColor( r, g, b, a );
415 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
418 # Set the current color applied to all drawing
420 # require: r, g, b, a in [0.0 .. 1.0]
421 fun color
(r
, g
, b
, a
: Float) `{ glColor4f(r, g, b, a); `}
423 # Reset the current color to opaque white
424 fun reset_color `{ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); `}
427 extern class Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
430 redef fun destroy is extern `{ free( recv ); `}
432 redef fun width
: Int is extern `{ return recv->width; `}
433 redef fun height: Int is extern `{ return recv->height; `}
435 fun center_x
: Int `{ return recv->center_x; `}
436 fun center_y: Int `{ return recv->center_y; `}
438 redef fun scale
=( v
: Float ) is extern `{
440 recv->center_x = v*recv->width/2;
441 recv->center_y = v*recv->height/2;
443 redef fun scale
: Float is extern `{ return recv->scale; `}
445 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
446 redef fun blended
: Bool is extern `{ return recv->blended; `}
448 # inherits scale and blend from source
449 redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
450 struct mnit_opengles_Texture
* image
=
451 malloc
( sizeof
( struct mnit_opengles_Texture
) );
453 image-
>texture
= recv-
>texture
;
456 image-
>center_x
= recv-
>scale
*w
/2;
457 image-
>center_y
= recv-
>scale
*h
/2;
458 image-
>scale
= recv-
>scale
;
459 image-
>blended
= recv-
>blended
;
461 image-
>src_xo
= ((float
)x
)/recv-
>width
;
462 image-
>src_yo
= ((float
)y
)/recv-
>height
;
463 image-
>src_xi
= ((float
)x
+w
)/recv-
>width
;
464 image-
>src_yi
= ((float
)y
+h
)/recv-
>height
;
466 return Opengles1Image_as_Image( image
);