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 extern NativeWindowType mnit_window;
63 extern EGLNativeDisplayType mnit_native_display;
65 GLfloat mnit_opengles_vertices[6][3] =
72 GLfloat mnit_opengles_texture[6][2] =
82 struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha )
84 struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture));
85 int format = has_alpha? GL_RGBA: GL_RGB;
88 image->height = height;
89 image->center_x = width/2;
90 image->center_y = height/2;
92 image->blended = has_alpha;
99 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
100 PRINT_ERROR("error loading image after malloc: %i", mnit_opengles_error_code);
103 glGenTextures(1, &image->texture);
105 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
106 PRINT_ERROR("error loading image after glGenTextures: %i", mnit_opengles_error_code);
109 glBindTexture(GL_TEXTURE_2D, image->texture);
111 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
112 PRINT_ERROR("error loading image glBindTexture: %i", mnit_opengles_error_code);
115 glTexImage2D( GL_TEXTURE_2D, 0, format, width, height,
116 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels);
118 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
119 PRINT_ERROR("error loading image after glTexImage2D: %i", mnit_opengles_error_code);
122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
124 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
125 PRINT_ERROR("error loading image after gtTexParameter: %i", mnit_opengles_error_code);
133 # Uses 3d hardware optimization
134 class Opengles1Display
137 redef type I
: Opengles1Image
140 fun midway_init
( format
: Int ) do end
141 fun extern_init
: Bool is extern import midway_init
`{
142 /* initialize OpenGL ES and EGL */
143 const EGLint attribs[] = {
144 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
150 EGLint w, h, dummy, format;
156 EGLDisplay display = eglGetDisplay(mnit_native_display);
157 if ( display == EGL_NO_DISPLAY) {
158 PRINT_ERROR("Unable to eglGetDisplay");
162 if ( eglInitialize(display, 0, 0) == EGL_FALSE) {
163 PRINT_ERROR("Unable to eglInitialize");
167 if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) {
168 PRINT_ERROR("Unable to eglChooseConfig");
172 if ( numConfigs == 0 ) {
173 PRINT_ERROR("No configs available for egl");
177 if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) {
178 PRINT_ERROR("Unable to eglGetConfigAttrib");
182 /* Used by Android to set buffer geometry */
183 Opengles1Display_midway_init(recv, format);
185 surface = eglCreateWindowSurface(display, config, mnit_window, NULL);
186 context = eglCreateContext(display, config, NULL, NULL);
188 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
189 PRINT_ERROR("Unable to eglMakeCurrent");
193 eglQuerySurface(display, surface, EGL_WIDTH, &w);
194 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
196 mnit_display = display;
197 mnit_context = context;
198 mnit_surface = surface;
199 mnit_config = config;
203 glViewport(0, 0, mnit_width, mnit_height);
204 glMatrixMode(GL_PROJECTION);
206 glOrthof(0.0f, w, h, 0.0f, 0.0f, 1.0f);
207 glMatrixMode(GL_MODELVIEW);
209 glFrontFace( GL_CW );
214 fun close
is extern `{
215 if ( mnit_display != EGL_NO_DISPLAY) {
216 eglMakeCurrent( mnit_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
217 if ( mnit_context != EGL_NO_CONTEXT) {
218 eglDestroyContext( mnit_display, mnit_context );
220 if ( mnit_surface != EGL_NO_SURFACE) {
221 eglDestroySurface( mnit_display, mnit_surface );
223 eglTerminate( mnit_display);
225 mnit_display = EGL_NO_DISPLAY;
226 mnit_context = EGL_NO_CONTEXT;
227 mnit_surface = EGL_NO_SURFACE;
230 redef fun begin
is extern `{
231 glClear(GL_COLOR_BUFFER_BIT);
235 redef fun width
: Int is extern `{
238 redef fun height
: Int is extern `{
242 redef fun finish
is extern `{
243 eglSwapBuffers( mnit_display, mnit_surface );
246 redef fun set_viewport
( x
, y
, w
, h
) is extern `{
248 glViewport(0,0, mnit_width, mnit_height );
249 glMatrixMode(GL_PROJECTION);
251 glOrthof(x, x+w, y+h, y, 0.0f, 1.0f);
252 glMatrixMode(GL_MODELVIEW);
253 glFrontFace( GL_CW );
256 redef fun blit
(image
, x
, y
) do native_blit
(image
, x
.to_f
, y
.to_f
)
258 private fun native_blit
(image
: Opengles1Image, x
, y
: Float) `{
259 GLfloat texture_coord[4][2] =
261 {image->src_xo, image->src_yi},
262 {image->src_xi, image->src_yi},
263 {image->src_xo, image->src_yo},
264 {image->src_xi, image->src_yo}
269 glBindTexture(GL_TEXTURE_2D, image->texture);
271 glEnableClientState(GL_VERTEX_ARRAY);
272 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
273 glTranslatef( x, y, 0.0f );
274 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
276 if ( image->blended ) {
278 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
281 glEnable(GL_TEXTURE_2D);
282 glDisable(GL_DEPTH_TEST);
284 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
285 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
287 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
289 glDisableClientState(GL_VERTEX_ARRAY);
290 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
291 if ( image->blended ) glDisable(GL_BLEND);
292 glDisable(GL_TEXTURE_2D);
294 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
295 PRINT_ERROR("error drawing: %i", mnit_opengles_error_code);
299 redef fun blit_centered
(img
, x
, y
)
301 x
= x
.sub
(img
.center_x
)
302 y
= y
.sub
(img
.center_y
)
306 redef fun blit_rotated
(image
, x
, y
, angle
) do native_blit_rotated
(image
, x
.to_f
, y
.to_f
, angle
)
308 private fun native_blit_rotated
(image
: Opengles1Image, x
, y
, angle
: Float) `{
309 GLfloat texture_coord[4][2] =
311 {image->src_xo, image->src_yi},
312 {image->src_xi, image->src_yi},
313 {image->src_xo, image->src_yo},
314 {image->src_xi, image->src_yo}
319 glBindTexture(GL_TEXTURE_2D, image->texture);
321 glEnableClientState(GL_VERTEX_ARRAY);
322 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
323 glTranslatef( x, y, 0.0f );
324 glRotatef( angle*180.0f/3.14156f, 0, 0, 1.0f );
325 glTranslatef( image->width*image->scale/-2, image->height*image->scale/-2, 0.0f );
326 glScalef( image->width*image->scale, image->height*image->scale, 1.0f );
327 if ( image->blended ) {
329 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
331 glEnable(GL_TEXTURE_2D);
332 glDisable(GL_DEPTH_TEST);
334 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices);
335 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
337 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
339 glDisableClientState(GL_VERTEX_ARRAY);
340 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
341 if ( image->blended ) glDisable(GL_BLEND);
342 glDisable(GL_TEXTURE_2D);
344 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
345 PRINT_ERROR("error drawing: %i", mnit_opengles_error_code);
349 # a = top left, b = bottom left, c = bottom right, d = top right
350 redef fun blit_stretched
(image
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
)
352 native_blit_stretched
(image
,
353 ax
.to_f
, ay
.to_f
, bx
.to_f
, by
.to_f
,
354 cx
.to_f
, cy
.to_f
, dx
.to_f
, dy
.to_f
)
357 private fun native_blit_stretched
(image
: I
, ax
, ay
, bx
, by
, cx
, cy
, dx
, dy
: Float) `{
358 GLfloat texture_coord[4][2] =
360 {image->src_xo, image->src_yi},
361 {image->src_xi, image->src_yi},
362 {image->src_xo, image->src_yo},
363 {image->src_xi, image->src_yo}
366 GLfloat mnit_opengles_vertices_stretched[6][3] =
376 glBindTexture(GL_TEXTURE_2D, image->texture);
378 glEnableClientState(GL_VERTEX_ARRAY);
379 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
381 if ( image->blended ) {
383 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
386 glEnable(GL_TEXTURE_2D);
387 glDisable(GL_DEPTH_TEST);
389 glVertexPointer(3, GL_FLOAT, 0, mnit_opengles_vertices_stretched);
390 glTexCoordPointer(2, GL_FLOAT, 0, texture_coord );
392 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
394 glDisableClientState(GL_VERTEX_ARRAY);
395 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
396 if ( image->blended ) glDisable(GL_BLEND);
397 glDisable(GL_TEXTURE_2D);
399 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
400 PRINT_ERROR("error drawing: %i", mnit_opengles_error_code);
404 redef fun clear
( r
, g
, b
: Float ) is extern `{
405 glClearColor( r, g, b, 1.0 );
406 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
409 fun clear_alpha
( r
, g
, b
, a
: Float ) is extern `{
410 glClearColor( r, g, b, a );
411 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
414 # Set the current color applied to all drawing
416 # require: r, g, b, a in [0.0 .. 1.0]
417 fun color
(r
, g
, b
, a
: Float) `{ glColor4f(r, g, b, a); `}
419 # Reset the current color to opaque white
420 fun reset_color `{ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); `}
423 extern class Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
426 redef fun destroy is extern `{ free( recv ); `}
428 redef fun width
: Int is extern `{ return recv->width; `}
429 redef fun height: Int is extern `{ return recv->height; `}
431 fun center_x
: Int `{ return recv->center_x; `}
432 fun center_y: Int `{ return recv->center_y; `}
434 redef fun scale
=( v
: Float ) is extern `{
436 recv->center_x = v*recv->width/2;
437 recv->center_y = v*recv->height/2;
439 redef fun scale
: Float is extern `{ return recv->scale; `}
441 redef fun blended=( v: Bool ) is extern `{ recv->blended = v; `}
442 redef fun blended
: Bool is extern `{ return recv->blended; `}
444 # inherits scale and blend from source
445 redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
446 struct mnit_opengles_Texture
* image
=
447 malloc
( sizeof
( struct mnit_opengles_Texture
) );
449 image-
>texture
= recv-
>texture
;
452 image-
>center_x
= recv-
>scale
*w
/2;
453 image-
>center_y
= recv-
>scale
*h
/2;
454 image-
>scale
= recv-
>scale
;
455 image-
>blended
= recv-
>blended
;
457 image-
>src_xo
= ((float
)x
)/recv-
>width
;
458 image-
>src_yo
= ((float
)y
)/recv-
>height
;
459 image-
>src_xi
= ((float
)x
+w
)/recv-
>width
;
460 image-
>src_yi
= ((float
)y
+h
)/recv-
>height
;
462 return Opengles1Image_as_Image( image
);