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;
33 struct mnit_opengles_Texture {
36 /* offsets on source texture */
37 float src_xo, src_yo, src_xi, src_yi;
39 /* destination width and height */
42 /* may vary depending on scaling */
43 int center_x, center_y;
49 struct mnit_opengles_DrawableTexture {
50 struct mnit_opengles_Texture super;
56 GLenum mnit_opengles_error_code;
58 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha );
62 #define LOGW(...) ((void)fprintf(stderr, "# warn: %s (%i)\n", __VA_ARGS__))
64 #define LOGI(...) ((void)fprintf(stderr, "# info: %s (%i)\n", __VA_ARGS__))
66 #define LOGI(...) (void)0
69 extern NativeWindowType mnit_window;
70 extern EGLNativeDisplayType mnit_native_display;
72 GLfloat mnit_opengles_vertices[6][3] =
79 GLfloat mnit_opengles_texture[6][2] =
89 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
91 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
92 int format = has_alpha? GL_RGBA: GL_RGB;
95 image->height = height;
96 image->center_x = width/2;
97 image->center_y = height/2;
99 image->blended = has_alpha;
106 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
107 LOGW("error loading image after malloc", mnit_opengles_error_code);
110 glGenTextures(1, &image->texture);
112 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
113 LOGW("error loading image after glGenTextures", mnit_opengles_error_code);
116 glBindTexture(GL_TEXTURE_2D, image->texture);
118 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
119 LOGW("error loading image glBindTexture", mnit_opengles_error_code);
122 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
123 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
125 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
126 LOGW("error loading image after glTexImage2D", mnit_opengles_error_code);
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
131 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
132 LOGW("error loading image after gtTexParameter", mnit_opengles_error_code);
140 # Uses 3d hardware optimization
141 class Opengles1Display
144 redef type I
: Opengles1Image
147 fun midway_init
( format
: Int ) do end
148 fun extern_init
: Bool is extern import midway_init
`{
149 /* initialize OpenGL ES and EGL */
150 const EGLint attribs[] = {
151 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
157 EGLint w, h, dummy, format;
163 EGLDisplay display = eglGetDisplay(mnit_native_display);
164 if ( display == EGL_NO_DISPLAY) {
165 LOGW("Unable to eglGetDisplay", 0);
169 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
170 LOGW("Unable to eglInitialize", 0);
174 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
175 LOGW("Unable to eglChooseConfig", 0);
179 if ( numConfigs == 0 ) {
180 LOGW("No configs available for egl", 0);
184 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
185 LOGW("Unable to eglGetConfigAttrib", 0);
189 /* Used by Android to set buffer geometry */
190 Opengles1Display_midway_init(recv, format);
192 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
193 context = eglCreateContext(display, config, NULL, NULL);
195 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
196 LOGW("Unable to eglMakeCurrent", 0);
200 eglQuerySurface(display, surface, EGL_WIDTH, &w);
201 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
203 mnit_display = display;
204 mnit_context = context;
205 mnit_surface = surface;
206 mnit_config = config;
210 LOGI("surface", (int)surface);
211 LOGI("display", (int)display);
215 glViewport(0, 0, mnit_width, mnit_height);
216 glMatrixMode(GL_PROJECTION);
218 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
219 glMatrixMode(GL_MODELVIEW);
221 glFrontFace( GL_CW );
226 fun close
is extern `{
227 if ( mnit_display != EGL_NO_DISPLAY) {
228 eglMakeCurrent( mnit_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
229 if ( mnit_context != EGL_NO_CONTEXT) {
230 eglDestroyContext( mnit_display, mnit_context );
232 if ( mnit_surface != EGL_NO_SURFACE) {
233 eglDestroySurface( mnit_display, mnit_surface );
235 eglTerminate( mnit_display);
237 mnit_display = EGL_NO_DISPLAY;
238 mnit_context = EGL_NO_CONTEXT;
239 mnit_surface = EGL_NO_SURFACE;
242 redef fun begin
is extern `{
243 glClear(GL_COLOR_BUFFER_BIT);
247 redef fun width
: Int is extern `{
250 redef fun height
: Int is extern `{
254 redef fun finish
is extern `{
255 eglSwapBuffers( mnit_display, mnit_surface );
258 redef fun set_viewport
( x
, y
, w
, h
) is extern `{
260 glViewport(0,0, mnit_width, mnit_height );
261 glMatrixMode(GL_PROJECTION);
263 glOrthof(x, x+w, y+h, y, 0.0f, 1.0f);
264 glMatrixMode(GL_MODELVIEW);
265 glFrontFace( GL_CW );
268 redef fun blit
(image
, x
, y
) do native_blit
(image
, x
.to_f
, y
.to_f
)
270 private fun native_blit
(image
: Opengles1Image, x
, y
: Float) `{
271 GLfloat texture_coord[4][2] =
273 {image->src_xo, image->src_yi},
274 {image->src_xi, image->src_yi},
275 {image->src_xo, image->src_yo},
276 {image->src_xi, image->src_yo}
281 glBindTexture(GL_TEXTURE_2D, image->texture);
283 glEnableClientState(GL_VERTEX_ARRAY);
284 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
285 glTranslatef( x, y, 0.0f );
286 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
288 if ( image->blended ) {
290 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
293 glEnable(GL_TEXTURE_2D);
294 glDisable(GL_DEPTH_TEST);
296 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
297 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
299 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
301 glDisableClientState(GL_VERTEX_ARRAY);
302 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
303 if ( image->blended ) glDisable(GL_BLEND);
304 glDisable(GL_TEXTURE_2D);
306 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
307 LOGW("error drawing", mnit_opengles_error_code);
311 redef fun blit_centered
(img
, x
, y
)
313 x
= x
.sub
(img
.center_x
)
314 y
= y
.sub
(img
.center_y
)
318 redef fun blit_rotated
(image
, x
, y
, angle
) do native_blit_rotated
(image
, x
.to_f
, y
.to_f
, angle
)
320 private fun native_blit_rotated
(image
: Opengles1Image, x
, y
, angle
: Float) `{
321 GLfloat texture_coord[4][2] =
323 {image->src_xo, image->src_yi},
324 {image->src_xi, image->src_yi},
325 {image->src_xo, image->src_yo},
326 {image->src_xi, image->src_yo}
331 glBindTexture(GL_TEXTURE_2D, image->texture);
333 glEnableClientState(GL_VERTEX_ARRAY);
334 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
335 glTranslatef( x, y, 0.0f );
336 glRotatef( angle*180.0f/3.14156f, 0, 0, 1.0f );
337 glTranslatef( image->width*image->scale/-2, image->height*image->scale/-2, 0.0f );
338 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
339 if ( image->blended ) {
341 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
343 glEnable(GL_TEXTURE_2D);
344 glDisable(GL_DEPTH_TEST);
346 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
347 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
349 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
351 glDisableClientState(GL_VERTEX_ARRAY);
352 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
353 if ( image->blended ) glDisable(GL_BLEND);
354 glDisable(GL_TEXTURE_2D);
356 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
357 LOGW("error drawing", mnit_opengles_error_code);
361 # a = top left, b = bottom left, c = bottom right, d = top right
362 redef fun blit_stretched
(image
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
)
364 native_blit_stretched
(image
,
365 ax
.to_f
, ay
.to_f
, bx
.to_f
, by
.to_f
,
366 cx
.to_f
, cy
.to_f
, dx
.to_f
, dy
.to_f
)
369 private fun native_blit_stretched
(image
: I
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
: Float) `{
370 GLfloat texture_coord[4][2] =
372 {image->src_xo, image->src_yi},
373 {image->src_xi, image->src_yi},
374 {image->src_xo, image->src_yo},
375 {image->src_xi, image->src_yo}
378 GLfloat mnit_opengles_vertices_stretched[6][3] =
388 glBindTexture(GL_TEXTURE_2D, image->texture);
390 glEnableClientState(GL_VERTEX_ARRAY);
391 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
393 if ( image->blended ) {
395 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
398 glEnable(GL_TEXTURE_2D);
399 glDisable(GL_DEPTH_TEST);
401 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
402 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
404 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
406 glDisableClientState(GL_VERTEX_ARRAY);
407 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
408 if ( image->blended ) glDisable(GL_BLEND);
409 glDisable(GL_TEXTURE_2D);
411 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
412 LOGW("error drawing", mnit_opengles_error_code);
416 redef fun clear
( r
, g
, b
: Float ) is extern `{
417 glClearColor( r, g, b, 1.0 );
418 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
421 fun clear_alpha
( r
, g
, b
, a
: Float ) is extern `{
422 glClearColor( r, g, b, a );
423 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
426 # Set the current color applied to all drawing
428 # require: r, g, b, a in [0.0 .. 1.0]
429 fun color
(r
, g
, b
, a
: Float) `{ glColor4f(r, g, b, a); `}
431 # Reset the current color to opaque white
432 fun reset_color `{ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); `}
435 extern class Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
438 redef fun destroy is extern `{ free( recv ); `}
440 redef fun width
: Int is extern `{ return recv->width; `}
441 redef fun height: Int is extern `{ return recv->height; `}
443 fun center_x
: Int `{ return recv->center_x; `}
444 fun center_y: Int `{ return recv->center_y; `}
446 redef fun scale
=( v
: Float ) is extern `{
448 recv->center_x = v*recv->width/2;
449 recv->center_y = v*recv->height/2;
451 redef fun scale
: Float is extern `{ return recv->scale; `}
453 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
454 redef fun blended
: Bool is extern `{ return recv->blended; `}
456 # inherits scale and blend from source
457 redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
458 struct mnit_opengles_Texture
* image
=
459 malloc
( sizeof
( struct mnit_opengles_Texture
) );
461 image-
>texture
= recv-
>texture
;
464 image-
>center_x
= recv-
>scale
*w
/2;
465 image-
>center_y
= recv-
>scale
*h
/2;
466 image-
>scale
= recv-
>scale
;
467 image-
>blended
= recv-
>blended
;
469 image-
>src_xo
= ((float
)x
)/recv-
>width
;
470 image-
>src_yo
= ((float
)y
)/recv-
>height
;
471 image-
>src_xi
= ((float
)x
+w
)/recv-
>width
;
472 image-
>src_yi
= ((float
)y
+h
)/recv-
>height
;
474 return Opengles1Image_as_Image( image
);