1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 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 # Interface between rendering APIs (OpenGL, OpenGL ES, etc.) and the native windowing system.
19 # Most services of this module are a direct wrapper of the underlying
20 # C library. If a method or class is not documented in Nit, refer to
21 # the official documentation by the Khronos Group at:
22 # http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/
25 ldflags
("-lEGL")@android
34 extern class EGLNativeDisplayType `{ EGLNativeDisplayType `}
35 new from_x11(handle: Pointer) `{ return (EGLNativeDisplayType)handle; `}
38 extern class EGLDisplay `{ EGLDisplay `}
39 new current `{ return eglGetCurrentDisplay(); `}
40 new(handle
: Pointer) `{ return eglGetDisplay(handle); `}
42 fun is_valid: Bool `{ return self != EGL_NO_DISPLAY; `}
44 fun initialize
: Bool `{
45 return eglInitialize(self, NULL, NULL);
48 fun major_version
: Int `{
50 eglInitialize(self, &val, NULL);
53 fun minor_version
: Int `{
55 eglInitialize(self, NULL, &val);
60 # Returns all configs supported by the hardware
61 #fun get_configs: nullable Array[EGLConfig] import Array[EGLConfig].with_native `{
63 # Returns some configs compatible with the specified `attributes`
64 fun choose_configs
(attribs
: Array[Int]): nullable Array[EGLConfig] import Array[Int].length
, Array[Int].[], Array[EGLConfig], Array[EGLConfig].add
, Array[EGLConfig].as nullable, report_egl_error
`{
67 int n_attribs = Array_of_Int_length(attribs);
69 int *c_attribs = malloc(sizeof(int)*n_attribs);
70 for (i = 0; i < n_attribs; i ++) {
71 c_attribs[i] = Array_of_Int__index(attribs, i);
74 // get number of configs
75 EGLBoolean r = eglChooseConfig(self, c_attribs, NULL, 0, &n_configs);
78 EGLDisplay_report_egl_error(self, "failed to get number of available configs.");
79 return null_Array_of_EGLConfig();
80 } else if (n_configs == 0) {
81 EGLDisplay_report_egl_error(self, "no config available.");
82 return null_Array_of_EGLConfig();
85 configs = (EGLConfig*)malloc(sizeof(EGLConfig)*n_configs);
87 r = eglChooseConfig(self, c_attribs, configs, n_configs, &n_configs);
90 EGLDisplay_report_egl_error(self, "failed to load config.");
91 return null_Array_of_EGLConfig();
93 Array_of_EGLConfig array = new_Array_of_EGLConfig();
94 for (i=0; i < n_configs; i++)
95 Array_of_EGLConfig_add(array, configs[i]);
97 return Array_of_EGLConfig_as_nullable(array);
101 private fun report_egl_error
(cmsg
: CString)
104 print
"libEGL error: {msg}"
107 # Can be used directly, but it is preferable to use a `EGLConfigAttribs`
108 fun config_attrib
(config
: EGLConfig, attribute
: Int): Int `{
110 EGLBoolean r = eglGetConfigAttrib(self, config, attribute, &val);
117 fun terminate
: Bool `{
118 return eglTerminate(self) == EGL_TRUE;
121 fun create_window_surface
(config
: EGLConfig, native_window
: Pointer, attribs
: Array[Int]): EGLSurface `{
122 EGLSurface surface = eglCreateWindowSurface(self, config, (EGLNativeWindowType)native_window, NULL);
126 # TODO add share_context
127 fun create_context
(config
: EGLConfig): EGLContext `{
128 EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE}; // TODO move out!
129 EGLContext context = eglCreateContext(self, config, EGL_NO_CONTEXT, context_attribs);
133 fun make_current
(draw
, read
: EGLSurface, context
: EGLContext): Bool `{
134 return eglMakeCurrent(self, draw, read, context);
137 # Can be used directly, but it is preferable to use a `EGLSurfaceAttribs`
138 fun query_surface
(surface
: EGLSurface, attribute
: Int): Int `{
140 EGLBoolean r = eglQuerySurface(self, surface, attribute, &val);
147 fun destroy_context
(context
: EGLContext): Bool `{
148 return eglDestroyContext(self, context);
151 fun destroy_surface
(surface
: EGLSurface): Bool `{
152 return eglDestroySurface(self, surface);
155 fun error
: EGLError `{ return eglGetError(); `}
157 # Utility method for easier debugging
158 fun assert_no_egl_error
160 var error = self.error
161 if not error.is_success then
162 print "EGL error: {error}"
167 private fun query_string(name: Int): String import CString.to_s `{
168 return CString_to_s((char
*)eglQueryString
(self, name
));
171 fun vendor: String do return query_string(0x3053)
173 fun version: String do return query_string(0x3054)
175 fun extensions: Array[String] do return query_string(0x3055).trim.split_with(" ")
177 fun client_apis: Array[String] do return query_string(0x308D).split_with(" ")
179 fun swap_buffers(surface: EGLSurface) `{ eglSwapBuffers(self, surface); `}
182 extern class EGLConfig `{ EGLConfig `}
183 fun attribs(display: EGLDisplay): EGLConfigAttribs do
184 return new EGLConfigAttribs(display, self)
188 extern class EGLSurface `{ EGLSurface `}
189 new current_draw
`{ return eglGetCurrentSurface(EGL_DRAW); `}
190 new current_read `{ return eglGetCurrentSurface(EGL_READ); `}
191 new none
`{ return EGL_NO_SURFACE; `}
193 fun is_ok: Bool `{ return self != EGL_NO_SURFACE; `}
195 fun attribs
(display
: EGLDisplay): EGLSurfaceAttribs do
196 return new EGLSurfaceAttribs(display
, self)
200 extern class EGLContext `{ EGLContext `}
201 new current `{ return eglGetCurrentContext(); `}
202 new none
`{ return EGL_NO_CONTEXT; `}
204 fun is_ok: Bool `{ return self != EGL_NO_CONTEXT; `}
207 # Attributes of a config for a given EGL display
208 class EGLConfigAttribs
209 var display
: EGLDisplay
210 var config
: EGLConfig
212 fun buffer_size
: Int do return display
.config_attrib
(config
, 0x3020)
213 fun alpha_size
: Int do return display
.config_attrib
(config
, 0x3021)
214 fun blue_size
: Int do return display
.config_attrib
(config
, 0x3022)
215 fun green_size
: Int do return display
.config_attrib
(config
, 0x3023)
216 fun red_size
: Int do return display
.config_attrib
(config
, 0x3024)
217 fun depth_size
: Int do return display
.config_attrib
(config
, 0x3025)
218 fun stencil_size
: Int do return display
.config_attrib
(config
, 0x3026)
219 fun samples
: Int do return display
.config_attrib
(config
, 0x3031)
220 fun sample_buffers
: Int do return display
.config_attrib
(config
, 0x3032)
222 fun native_visual_id
: Int do return display
.config_attrib
(config
, 0x302E)
223 fun native_visual_type
: Int do return display
.config_attrib
(config
, 0x302F)
225 fun caveat
: EGLConfigCaveat do
226 return new EGLConfigCaveat.from_i
(display
.config_attrib
(config
, 0x3027))
229 fun conformant
: EGLConformant do
230 return new EGLConformant.from_i
(display
.config_attrib
(config
, 0x3042))
234 extern class EGLConfigCaveat `{ EGLint `}
235 new from_i(val: Int) `{ return (EGLint)val; `}
236 fun to_i
: Int `{ return self; `}
238 new none `{ return EGL_NONE; `}
239 fun is_none
: Bool `{ return self == EGL_NONE; `}
241 new dont_care `{ return EGL_DONT_CARE; `}
242 fun is_dont_care
: Bool `{ return self == EGL_DONT_CARE; `}
244 new slow `{ return EGL_SLOW_CONFIG; `}
245 fun is_slow
: Bool `{ return self == EGL_SLOW_CONFIG; `}
247 # Obselete since EGL 1.3, use EGL_CONFORMANT instead
248 new non_conformant `{ return EGL_NON_CONFORMANT_CONFIG; `}
249 fun is_non_conformant
: Bool `{ return self == EGL_NON_CONFORMANT_CONFIG; `}
253 if is_none then return "EGL_NONE"
254 if is_dont_care then return "EGL_DONT_CARE"
255 if is_slow then return "EGL_SLOW_CONFIG"
256 if is_non_conformant then return "EGL_NON_CONFORMANT"
257 return "Unknown or invalid value"
261 extern class EGLConformant `{ EGLint `}
262 new `{ return (EGLint)0; `}
263 new from_i(val: Int) `{ return (EGLint)val; `}
264 fun to_i
: Int `{ return self; `}
266 fun opengl: Bool `{ return self & EGL_OPENGL_BIT; `}
267 fun with_opengl
: EGLConformant `{ return self | EGL_OPENGL_BIT; `}
269 fun opengl_es: Bool `{ return self & EGL_OPENGL_ES_BIT; `}
270 fun with_opengl_es
: EGLConformant `{ return self | EGL_OPENGL_ES_BIT; `}
272 fun opengl_es2: Bool `{ return self & EGL_OPENGL_ES2_BIT; `}
273 fun with_opengl_es2
: EGLConformant `{ return self | EGL_OPENGL_ES2_BIT; `}
275 fun openvg: Bool `{ return self & EGL_OPENVG_BIT; `}
276 fun with_openvg
: EGLConformant `{ return self | EGL_OPENVG_BIT; `}
278 fun to_a: Array[String]
280 var features = new Array[String]
281 if opengl then features.add("OpenGL")
282 if opengl_es then features.add("OpenGL ES")
283 if opengl_es2 then features.add("OpenGL ES2")
284 if openvg then features.add("OpenVG")
288 redef fun to_s do return to_a.join(", ")
291 # Attributes of a surface for a given EGL display
292 class EGLSurfaceAttribs
293 var display: EGLDisplay
294 var surface: EGLSurface
296 fun height: Int do return display.query_surface(surface, 0x3056)
297 fun width: Int do return display.query_surface(surface, 0x3057)
298 fun largest_pbuffer: Int do return display.query_surface(surface, 0x3058)
299 fun texture_format: Int do return display.query_surface(surface, 0x3080)
300 fun texture_target: Int do return display.query_surface(surface, 0x3081)
301 fun mipmap_texture: Int do return display.query_surface(surface, 0x3082)
302 fun mipmap_level: Int do return display.query_surface(surface, 0x3083)
303 fun render_buffer: Int do return display.query_surface(surface, 0x3086)
304 fun vg_colorspace: Int do return display.query_surface(surface, 0x3087)
305 fun vg_alpha_format: Int do return display.query_surface(surface, 0x3088)
306 fun horizontal_resolution: Int do return display.query_surface(surface, 0x3090)
307 fun vertical_resolution: Int do return display.query_surface(surface, 0x3091)
308 fun pixel_aspect_ratio: Int do return display.query_surface(surface, 0x3092)
309 fun swap_behavior: Int do return display.query_surface(surface, 0x3093)
310 fun multisample_resolve: Int do return display.query_surface(surface, 0x3099)
313 extern class EGLError `{ EGLint `}
314 fun is_success
: Bool `{ return self == EGL_SUCCESS; `}
316 fun is_not_initialized: Bool `{ return self == EGL_NOT_INITIALIZED; `}
317 fun is_bad_access
: Bool `{ return self == EGL_BAD_ACCESS; `}
318 fun is_bad_alloc: Bool `{ return self == EGL_BAD_ALLOC; `}
319 fun is_bad_attribute
: Bool `{ return self == EGL_BAD_ATTRIBUTE; `}
320 fun is_bad_config: Bool `{ return self == EGL_BAD_CONFIG; `}
321 fun is_bad_context
: Bool `{ return self == EGL_BAD_CONTEXT; `}
322 fun is_bad_current_surface: Bool `{ return self == EGL_BAD_CURRENT_SURFACE; `}
323 fun is_bad_display
: Bool `{ return self == EGL_BAD_DISPLAY; `}
324 fun is_bad_match: Bool `{ return self == EGL_BAD_MATCH; `}
325 fun is_bad_native_pixmap
: Bool `{ return self == EGL_BAD_NATIVE_PIXMAP; `}
326 fun is_bad_native_window: Bool `{ return self == EGL_BAD_NATIVE_WINDOW; `}
327 fun is_bad_parameter
: Bool `{ return self == EGL_BAD_PARAMETER; `}
328 fun is_bad_surface: Bool `{ return self == EGL_BAD_SURFACE; `}
329 fun is_context_lost
: Bool `{ return self == EGL_CONTEXT_LOST; `}
333 if is_not_initialized then return "Not initialized"
334 if is_bad_access then return "Bad access"
335 if is_bad_alloc then return "Bad allocation"
336 if is_bad_attribute then return "Bad attribute"
337 if is_bad_config then return "Bad configuration"
338 if is_bad_context then return "Bad context"
339 if is_bad_current_surface then return "Bad current surface"
340 if is_bad_display then return "Bad display"
341 if is_bad_match then return "Bad match"
342 if is_bad_native_pixmap then return "Bad native pixmap"
343 if is_bad_native_window then return "Bad native window"
344 if is_bad_parameter then return "Bad parameter"
345 if is_bad_surface then return "Bad surface"
346 if is_context_lost then return "Context lost"
347 return "Unknown error" # this is not good
351 extern class EGLContextAttribute `{ EGLint `}
352 new buffer_size
`{ return EGL_BUFFER_SIZE; `}
353 new alpha_size `{ return EGL_ALPHA_SIZE; `}
354 new blue_size
`{ return EGL_BLUE_SIZE; `}
355 new green_size `{ return EGL_GREEN_SIZE; `}
356 new red_size
`{ return EGL_RED_SIZE; `}
357 new depth_size `{ return EGL_DEPTH_SIZE; `}
358 new stencil_size
`{ return EGL_STENCIL_SIZE; `}
359 new config_caveat `{ return EGL_CONFIG_CAVEAT; `}
360 new config_id
`{ return EGL_CONFIG_ID; `}
361 new level `{ return EGL_LEVEL; `}
362 new max_pbuffer_height
`{ return EGL_MAX_PBUFFER_HEIGHT; `}
363 new max_pbuffer_pixels `{ return EGL_MAX_PBUFFER_PIXELS; `}
364 new max_pbuffer_width
`{ return EGL_MAX_PBUFFER_WIDTH; `}
365 new native_renderable `{ return EGL_NATIVE_RENDERABLE; `}
366 new native_visual_id
`{ return EGL_NATIVE_VISUAL_ID; `}
367 new native_visual_type `{ return EGL_NATIVE_VISUAL_TYPE; `}
368 new samples
`{ return EGL_SAMPLES; `}
369 new sample_buffers `{ return EGL_SAMPLE_BUFFERS; `}
370 new surface_type
`{ return EGL_SURFACE_TYPE; `}
371 new transparent_type `{ return EGL_TRANSPARENT_TYPE; `}
372 new transparent_blue_value
`{ return EGL_TRANSPARENT_BLUE_VALUE; `}
373 new transparent_green_value `{ return EGL_TRANSPARENT_GREEN_VALUE; `}
374 new transparent_red_value
`{ return EGL_TRANSPARENT_RED_VALUE; `}
375 new bind_to_texture_rgb `{ return EGL_BIND_TO_TEXTURE_RGB; `}
376 new bind_to_texture_rgba
`{ return EGL_BIND_TO_TEXTURE_RGBA; `}
377 new min_swap_interval `{ return EGL_MIN_SWAP_INTERVAL; `}
378 new max_swap_interval
`{ return EGL_MAX_SWAP_INTERVAL; `}
379 new limunance_size `{ return EGL_LUMINANCE_SIZE; `}
380 new alpha_mask_size
`{ return EGL_ALPHA_MASK_SIZE; `}
381 new color_buffer_type `{ return EGL_COLOR_BUFFER_TYPE; `}
382 new renderable_type
`{ return EGL_RENDERABLE_TYPE; `}
383 new match_native_pixmap `{ return EGL_MATCH_NATIVE_PIXMAP; `}
384 new conformant
`{ return EGL_CONFORMANT; `}
386 # Attrib list terminator
387 new none `{ return EGL_NONE; `}
390 # Utility class to choose an EGLConfig
391 class EGLConfigChooser
392 var array
= new Array[Int]
394 protected var inserted_attribs
= new Array[Int]
396 protected fun insert_attrib_key
(key
: Int)
398 assert not inserted_attribs
.has
(key
) else
399 print
"Duplicate attrib passed to EGLConfigChooser"
404 protected fun insert_attrib_with_val
(key
, val
: Int)
406 insert_attrib_key key
411 insert_attrib_key
0x3038
415 fun surface_type
=(flag
: Int) do insert_attrib_with_val
(0x3033, flag
)
416 fun surface_type_egl
do surface_type
= 4
418 # Set which client rendering APIs are supported
419 fun renderable_type
=(flag
: Int) do insert_attrib_with_val
(0x3040, flag
)
421 # Set EGL as the only supported rendering API
422 fun renderable_type_egl
do renderable_type
= 4
424 fun blue_size
=(size
: Int) do insert_attrib_with_val
(0x3022, size
)
425 fun green_size
=(size
: Int) do insert_attrib_with_val
(0x3023, size
)
426 fun red_size
=(size
: Int) do insert_attrib_with_val
(0x3024, size
)
428 fun buffer_size
=(size
: Int) do insert_attrib_with_val
(0x3020, size
)
429 fun alpha_size
=(size
: Int) do insert_attrib_with_val
(0x3021, size
)
430 fun depth_size
=(size
: Int) do insert_attrib_with_val
(0x3025, size
)
431 fun stencil_size
=(size
: Int) do insert_attrib_with_val
(0x3026, size
)
432 fun samples
=(count
: Int) do insert_attrib_with_val
(0x3031, count
)
433 fun sample_buffers
=(size
: Int) do insert_attrib_with_val
(0x3032, size
)
435 fun caveat
=(caveat
: EGLConfigCaveat) do insert_attrib_with_val
(0x3050, caveat
.to_i
)
437 fun conformant
=(conformant
: EGLConformant) do insert_attrib_with_val
(0x3042, conformant
.to_i
)
439 fun choose
(display
: EGLDisplay): nullable Array[EGLConfig]
441 assert closed
else print
"EGLConfigChooser not closed."
442 return display
.choose_configs
(array
)
446 fun egl_bind_opengl_api
: Bool `{ return eglBindAPI(EGL_OPENGL_API); `}
447 fun egl_bind_opengl_es_api: Bool `{ return eglBindAPI(EGL_OPENGL_ES_API); `}
448 fun egl_bind_openvg_api
: Bool `{ return eglBindAPI(EGL_OPENVG_API); `}
450 # Handle to the default display to use with EGL
451 fun egl_default_display: Pointer `{ return EGL_DEFAULT_DISPLAY; `}