1 /*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19 #include <dlfcn.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <hardware/gralloc.h>
25 #include <system/window.h>
26
27 #include <EGL/egl.h>
28 #include <EGL/eglext.h>
29
30 #include <cutils/log.h>
31 #include <cutils/atomic.h>
32 #include <cutils/compiler.h>
33 #include <cutils/properties.h>
34 #include <cutils/memory.h>
35
36 #include <utils/KeyedVector.h>
37 #include <utils/SortedVector.h>
38 #include <utils/String8.h>
39 #include <utils/Trace.h>
40
41 #include "../egl_impl.h"
42 #include "../glestrace.h"
43 #include "../hooks.h"
44
45 #include "egl_display.h"
46 #include "egl_object.h"
47 #include "egl_tls.h"
48 #include "egldefs.h"
49
50 using namespace android;
51
52 // This extension has not been ratified yet, so can't be shipped.
53 // Implementation is incomplete and untested.
54 #define ENABLE_EGL_KHR_GL_COLORSPACE 0
55
56 // ----------------------------------------------------------------------------
57
58 namespace android {
59
60 struct extention_map_t {
61 const char* name;
62 __eglMustCastToProperFunctionPointerType address;
63 };
64
65 /*
66 * This is the list of EGL extensions exposed to applications.
67 *
68 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
69 * wrapper and are always available.
70 *
71 * The rest (gExtensionString) depend on support in the EGL driver, and are
72 * only available if the driver supports them. However, some of these must be
73 * supported because they are used by the Android system itself; these are
74 * listd as mandatory below and are required by the CDD. The system *assumes*
75 * the mandatory extensions are present and may not function properly if some
76 * are missing.
77 *
78 * NOTE: Both strings MUST have a single space as the last character.
79 */
80 extern char const * const gBuiltinExtensionString =
81 "EGL_KHR_get_all_proc_addresses "
82 "EGL_ANDROID_presentation_time "
83 "EGL_KHR_swap_buffers_with_damage "
84 ;
85 extern char const * const gExtensionString =
86 "EGL_KHR_image " // mandatory
87 "EGL_KHR_image_base " // mandatory
88 "EGL_KHR_image_pixmap "
89 "EGL_KHR_lock_surface "
90 #if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
91 "EGL_KHR_gl_colorspace "
92 #endif
93 "EGL_KHR_gl_texture_2D_image "
94 "EGL_KHR_gl_texture_3D_image "
95 "EGL_KHR_gl_texture_cubemap_image "
96 "EGL_KHR_gl_renderbuffer_image "
97 "EGL_KHR_reusable_sync "
98 "EGL_KHR_fence_sync "
99 "EGL_KHR_create_context "
100 "EGL_KHR_config_attribs "
101 "EGL_KHR_surfaceless_context "
102 "EGL_KHR_stream "
103 "EGL_KHR_stream_fifo "
104 "EGL_KHR_stream_producer_eglsurface "
105 "EGL_KHR_stream_consumer_gltexture "
106 "EGL_KHR_stream_cross_process_fd "
107 "EGL_EXT_create_context_robustness "
108 "EGL_NV_system_time "
109 "EGL_ANDROID_image_native_buffer " // mandatory
110 "EGL_KHR_wait_sync " // strongly recommended
111 "EGL_ANDROID_recordable " // mandatory
112 "EGL_KHR_partial_update " // strongly recommended
113 "EGL_EXT_buffer_age " // strongly recommended with partial_update
114 "EGL_KHR_create_context_no_error "
115 ;
116
117 // extensions not exposed to applications but used by the ANDROID system
118 // "EGL_ANDROID_blob_cache " // strongly recommended
119 // "EGL_IMG_hibernate_process " // optional
120 // "EGL_ANDROID_native_fence_sync " // strongly recommended
121 // "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
122 // "EGL_ANDROID_image_crop " // optional
123
124 /*
125 * EGL Extensions entry-points exposed to 3rd party applications
126 * (keep in sync with gExtensionString above)
127 *
128 */
129 static const extention_map_t sExtensionMap[] = {
130 // EGL_KHR_lock_surface
131 { "eglLockSurfaceKHR",
132 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
133 { "eglUnlockSurfaceKHR",
134 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
135
136 // EGL_KHR_image, EGL_KHR_image_base
137 { "eglCreateImageKHR",
138 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
139 { "eglDestroyImageKHR",
140 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
141
142 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
143 { "eglCreateSyncKHR",
144 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
145 { "eglDestroySyncKHR",
146 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
147 { "eglClientWaitSyncKHR",
148 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
149 { "eglSignalSyncKHR",
150 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
151 { "eglGetSyncAttribKHR",
152 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
153
154 // EGL_NV_system_time
155 { "eglGetSystemTimeFrequencyNV",
156 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
157 { "eglGetSystemTimeNV",
158 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
159
160 // EGL_KHR_wait_sync
161 { "eglWaitSyncKHR",
162 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
163
164 // EGL_ANDROID_presentation_time
165 { "eglPresentationTimeANDROID",
166 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
167
168 // EGL_KHR_swap_buffers_with_damage
169 { "eglSwapBuffersWithDamageKHR",
170 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
171
172 // EGL_KHR_partial_update
173 { "eglSetDamageRegionKHR",
174 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
175
176 { "eglCreateStreamKHR",
177 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
178 { "eglDestroyStreamKHR",
179 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
180 { "eglStreamAttribKHR",
181 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
182 { "eglQueryStreamKHR",
183 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
184 { "eglQueryStreamu64KHR",
185 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
186 { "eglQueryStreamTimeKHR",
187 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
188 { "eglCreateStreamProducerSurfaceKHR",
189 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
190 { "eglStreamConsumerGLTextureExternalKHR",
191 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
192 { "eglStreamConsumerAcquireKHR",
193 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
194 { "eglStreamConsumerReleaseKHR",
195 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
196 { "eglGetStreamFileDescriptorKHR",
197 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
198 { "eglCreateStreamFromFileDescriptorKHR",
199 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
200 };
201
202 /*
203 * These extensions entry-points should not be exposed to applications.
204 * They're used internally by the Android EGL layer.
205 */
206 #define FILTER_EXTENSIONS(procname) \
207 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
208 !strcmp((procname), "eglHibernateProcessIMG") || \
209 !strcmp((procname), "eglAwakenProcessIMG") || \
210 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
211
212
213
214 // accesses protected by sExtensionMapMutex
215 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
216 static int sGLExtentionSlot = 0;
217 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
218
findProcAddress(const char * name,const extention_map_t * map,size_t n)219 static void(*findProcAddress(const char* name,
220 const extention_map_t* map, size_t n))() {
221 for (uint32_t i=0 ; i<n ; i++) {
222 if (!strcmp(name, map[i].name)) {
223 return map[i].address;
224 }
225 }
226 return NULL;
227 }
228
229 // ----------------------------------------------------------------------------
230
231 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
232 extern EGLBoolean egl_init_drivers();
233 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
234 extern int getEGLDebugLevel();
235 extern void setEGLDebugLevel(int level);
236 extern gl_hooks_t gHooksTrace;
237
238 } // namespace android;
239
240
241 // ----------------------------------------------------------------------------
242
clearError()243 static inline void clearError() { egl_tls_t::clearError(); }
getContext()244 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
245
246 // ----------------------------------------------------------------------------
247
eglGetDisplay(EGLNativeDisplayType display)248 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
249 {
250 clearError();
251
252 uintptr_t index = reinterpret_cast<uintptr_t>(display);
253 if (index >= NUM_DISPLAYS) {
254 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
255 }
256
257 if (egl_init_drivers() == EGL_FALSE) {
258 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
259 }
260
261 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
262 return dpy;
263 }
264
265 // ----------------------------------------------------------------------------
266 // Initialization
267 // ----------------------------------------------------------------------------
268
eglInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)269 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
270 {
271 clearError();
272
273 egl_display_ptr dp = get_display(dpy);
274 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
275
276 EGLBoolean res = dp->initialize(major, minor);
277
278 return res;
279 }
280
eglTerminate(EGLDisplay dpy)281 EGLBoolean eglTerminate(EGLDisplay dpy)
282 {
283 // NOTE: don't unload the drivers b/c some APIs can be called
284 // after eglTerminate() has been called. eglTerminate() only
285 // terminates an EGLDisplay, not a EGL itself.
286
287 clearError();
288
289 egl_display_ptr dp = get_display(dpy);
290 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
291
292 EGLBoolean res = dp->terminate();
293
294 return res;
295 }
296
297 // ----------------------------------------------------------------------------
298 // configuration
299 // ----------------------------------------------------------------------------
300
eglGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)301 EGLBoolean eglGetConfigs( EGLDisplay dpy,
302 EGLConfig *configs,
303 EGLint config_size, EGLint *num_config)
304 {
305 clearError();
306
307 const egl_display_ptr dp = validate_display(dpy);
308 if (!dp) return EGL_FALSE;
309
310 if (num_config==0) {
311 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
312 }
313
314 EGLBoolean res = EGL_FALSE;
315 *num_config = 0;
316
317 egl_connection_t* const cnx = &gEGLImpl;
318 if (cnx->dso) {
319 res = cnx->egl.eglGetConfigs(
320 dp->disp.dpy, configs, config_size, num_config);
321 }
322
323 return res;
324 }
325
eglChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)326 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
327 EGLConfig *configs, EGLint config_size,
328 EGLint *num_config)
329 {
330 clearError();
331
332 const egl_display_ptr dp = validate_display(dpy);
333 if (!dp) return EGL_FALSE;
334
335 if (num_config==0) {
336 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
337 }
338
339 EGLBoolean res = EGL_FALSE;
340 *num_config = 0;
341
342 egl_connection_t* const cnx = &gEGLImpl;
343 if (cnx->dso) {
344 if (attrib_list) {
345 char value[PROPERTY_VALUE_MAX];
346 property_get("debug.egl.force_msaa", value, "false");
347
348 if (!strcmp(value, "true")) {
349 size_t attribCount = 0;
350 EGLint attrib = attrib_list[0];
351
352 // Only enable MSAA if the context is OpenGL ES 2.0 and
353 // if no caveat is requested
354 const EGLint *attribRendererable = NULL;
355 const EGLint *attribCaveat = NULL;
356
357 // Count the number of attributes and look for
358 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
359 while (attrib != EGL_NONE) {
360 attrib = attrib_list[attribCount];
361 switch (attrib) {
362 case EGL_RENDERABLE_TYPE:
363 attribRendererable = &attrib_list[attribCount];
364 break;
365 case EGL_CONFIG_CAVEAT:
366 attribCaveat = &attrib_list[attribCount];
367 break;
368 }
369 attribCount++;
370 }
371
372 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
373 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
374
375 // Insert 2 extra attributes to force-enable MSAA 4x
376 EGLint aaAttribs[attribCount + 4];
377 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
378 aaAttribs[1] = 1;
379 aaAttribs[2] = EGL_SAMPLES;
380 aaAttribs[3] = 4;
381
382 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
383
384 EGLint numConfigAA;
385 EGLBoolean resAA = cnx->egl.eglChooseConfig(
386 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
387
388 if (resAA == EGL_TRUE && numConfigAA > 0) {
389 ALOGD("Enabling MSAA 4x");
390 *num_config = numConfigAA;
391 return resAA;
392 }
393 }
394 }
395 }
396
397 res = cnx->egl.eglChooseConfig(
398 dp->disp.dpy, attrib_list, configs, config_size, num_config);
399 }
400 return res;
401 }
402
eglGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)403 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
404 EGLint attribute, EGLint *value)
405 {
406 clearError();
407
408 egl_connection_t* cnx = NULL;
409 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
410 if (!dp) return EGL_FALSE;
411
412 return cnx->egl.eglGetConfigAttrib(
413 dp->disp.dpy, config, attribute, value);
414 }
415
416 // ----------------------------------------------------------------------------
417 // surfaces
418 // ----------------------------------------------------------------------------
419
420 // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
421 // been added to the Khronos egl.h.
422 #define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
423 #define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
424 #define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
425
426 // Turn linear formats into corresponding sRGB formats when colorspace is
427 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
428 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
429 // the modification isn't possible, the original dataSpace is returned.
modifyBufferDataspace(android_dataspace dataSpace,EGLint colorspace)430 static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
431 EGLint colorspace) {
432 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
433 return HAL_DATASPACE_SRGB_LINEAR;
434 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
435 return HAL_DATASPACE_SRGB;
436 }
437 return dataSpace;
438 }
439
eglCreateWindowSurface(EGLDisplay dpy,EGLConfig config,NativeWindowType window,const EGLint * attrib_list)440 EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
441 NativeWindowType window,
442 const EGLint *attrib_list)
443 {
444 clearError();
445
446 egl_connection_t* cnx = NULL;
447 egl_display_ptr dp = validate_display_connection(dpy, cnx);
448 if (dp) {
449 EGLDisplay iDpy = dp->disp.dpy;
450
451 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
452 if (result != OK) {
453 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
454 "failed (%#x) (already connected to another API?)",
455 window, result);
456 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
457 }
458
459 // Set the native window's buffers format to match what this config requests.
460 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
461 // of our native format. So if sRGB gamma is requested, we have to
462 // modify the EGLconfig's format before setting the native window's
463 // format.
464
465 // by default, just pick RGBA_8888
466 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
467 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
468
469 EGLint a = 0;
470 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
471 if (a > 0) {
472 // alpha-channel requested, there's really only one suitable format
473 format = HAL_PIXEL_FORMAT_RGBA_8888;
474 } else {
475 EGLint r, g, b;
476 r = g = b = 0;
477 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
478 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
479 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
480 EGLint colorDepth = r + g + b;
481 if (colorDepth <= 16) {
482 format = HAL_PIXEL_FORMAT_RGB_565;
483 } else {
484 format = HAL_PIXEL_FORMAT_RGBX_8888;
485 }
486 }
487
488 // now select a corresponding sRGB format if needed
489 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
490 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
491 if (*attr == EGL_GL_COLORSPACE_KHR) {
492 if (ENABLE_EGL_KHR_GL_COLORSPACE) {
493 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
494 } else {
495 // Normally we'd pass through unhandled attributes to
496 // the driver. But in case the driver implements this
497 // extension but we're disabling it, we want to prevent
498 // it getting through -- support will be broken without
499 // our help.
500 ALOGE("sRGB window surfaces not supported");
501 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
502 }
503 }
504 }
505 }
506
507 if (format != 0) {
508 int err = native_window_set_buffers_format(window, format);
509 if (err != 0) {
510 ALOGE("error setting native window pixel format: %s (%d)",
511 strerror(-err), err);
512 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
513 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
514 }
515 }
516
517 if (dataSpace != 0) {
518 int err = native_window_set_buffers_data_space(window, dataSpace);
519 if (err != 0) {
520 ALOGE("error setting native window pixel dataSpace: %s (%d)",
521 strerror(-err), err);
522 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
523 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
524 }
525 }
526
527 // the EGL spec requires that a new EGLSurface default to swap interval
528 // 1, so explicitly set that on the window here.
529 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
530 anw->setSwapInterval(anw, 1);
531
532 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
533 iDpy, config, window, attrib_list);
534 if (surface != EGL_NO_SURFACE) {
535 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
536 surface, cnx);
537 return s;
538 }
539
540 // EGLSurface creation failed
541 native_window_set_buffers_format(window, 0);
542 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
543 }
544 return EGL_NO_SURFACE;
545 }
546
eglCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,NativePixmapType pixmap,const EGLint * attrib_list)547 EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
548 NativePixmapType pixmap,
549 const EGLint *attrib_list)
550 {
551 clearError();
552
553 egl_connection_t* cnx = NULL;
554 egl_display_ptr dp = validate_display_connection(dpy, cnx);
555 if (dp) {
556 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
557 dp->disp.dpy, config, pixmap, attrib_list);
558 if (surface != EGL_NO_SURFACE) {
559 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
560 surface, cnx);
561 return s;
562 }
563 }
564 return EGL_NO_SURFACE;
565 }
566
eglCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)567 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
568 const EGLint *attrib_list)
569 {
570 clearError();
571
572 egl_connection_t* cnx = NULL;
573 egl_display_ptr dp = validate_display_connection(dpy, cnx);
574 if (dp) {
575 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
576 dp->disp.dpy, config, attrib_list);
577 if (surface != EGL_NO_SURFACE) {
578 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
579 surface, cnx);
580 return s;
581 }
582 }
583 return EGL_NO_SURFACE;
584 }
585
eglDestroySurface(EGLDisplay dpy,EGLSurface surface)586 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
587 {
588 clearError();
589
590 const egl_display_ptr dp = validate_display(dpy);
591 if (!dp) return EGL_FALSE;
592
593 SurfaceRef _s(dp.get(), surface);
594 if (!_s.get())
595 return setError(EGL_BAD_SURFACE, EGL_FALSE);
596
597 egl_surface_t * const s = get_surface(surface);
598 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
599 if (result == EGL_TRUE) {
600 _s.terminate();
601 }
602 return result;
603 }
604
eglQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)605 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
606 EGLint attribute, EGLint *value)
607 {
608 clearError();
609
610 const egl_display_ptr dp = validate_display(dpy);
611 if (!dp) return EGL_FALSE;
612
613 SurfaceRef _s(dp.get(), surface);
614 if (!_s.get())
615 return setError(EGL_BAD_SURFACE, EGL_FALSE);
616
617 egl_surface_t const * const s = get_surface(surface);
618 return s->cnx->egl.eglQuerySurface(
619 dp->disp.dpy, s->surface, attribute, value);
620 }
621
eglBeginFrame(EGLDisplay dpy,EGLSurface surface)622 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
623 ATRACE_CALL();
624 clearError();
625
626 const egl_display_ptr dp = validate_display(dpy);
627 if (!dp) {
628 return;
629 }
630
631 SurfaceRef _s(dp.get(), surface);
632 if (!_s.get()) {
633 setError(EGL_BAD_SURFACE, EGL_FALSE);
634 return;
635 }
636 }
637
638 // ----------------------------------------------------------------------------
639 // Contexts
640 // ----------------------------------------------------------------------------
641
eglCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_list,const EGLint * attrib_list)642 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
643 EGLContext share_list, const EGLint *attrib_list)
644 {
645 clearError();
646
647 egl_connection_t* cnx = NULL;
648 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
649 if (dp) {
650 if (share_list != EGL_NO_CONTEXT) {
651 if (!ContextRef(dp.get(), share_list).get()) {
652 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
653 }
654 egl_context_t* const c = get_context(share_list);
655 share_list = c->context;
656 }
657 EGLContext context = cnx->egl.eglCreateContext(
658 dp->disp.dpy, config, share_list, attrib_list);
659 if (context != EGL_NO_CONTEXT) {
660 // figure out if it's a GLESv1 or GLESv2
661 int version = 0;
662 if (attrib_list) {
663 while (*attrib_list != EGL_NONE) {
664 GLint attr = *attrib_list++;
665 GLint value = *attrib_list++;
666 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
667 if (value == 1) {
668 version = egl_connection_t::GLESv1_INDEX;
669 } else if (value == 2 || value == 3) {
670 version = egl_connection_t::GLESv2_INDEX;
671 }
672 }
673 };
674 }
675 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
676 version);
677 #if EGL_TRACE
678 if (getEGLDebugLevel() > 0)
679 GLTrace_eglCreateContext(version, c);
680 #endif
681 return c;
682 }
683 }
684 return EGL_NO_CONTEXT;
685 }
686
eglDestroyContext(EGLDisplay dpy,EGLContext ctx)687 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
688 {
689 clearError();
690
691 const egl_display_ptr dp = validate_display(dpy);
692 if (!dp)
693 return EGL_FALSE;
694
695 ContextRef _c(dp.get(), ctx);
696 if (!_c.get())
697 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
698
699 egl_context_t * const c = get_context(ctx);
700 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
701 if (result == EGL_TRUE) {
702 _c.terminate();
703 }
704 return result;
705 }
706
eglMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)707 EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
708 EGLSurface read, EGLContext ctx)
709 {
710 clearError();
711
712 egl_display_ptr dp = validate_display(dpy);
713 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
714
715 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
716 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
717 // a valid but uninitialized display.
718 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
719 (draw != EGL_NO_SURFACE) ) {
720 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
721 }
722
723 // get a reference to the object passed in
724 ContextRef _c(dp.get(), ctx);
725 SurfaceRef _d(dp.get(), draw);
726 SurfaceRef _r(dp.get(), read);
727
728 // validate the context (if not EGL_NO_CONTEXT)
729 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
730 // EGL_NO_CONTEXT is valid
731 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
732 }
733
734 // these are the underlying implementation's object
735 EGLContext impl_ctx = EGL_NO_CONTEXT;
736 EGLSurface impl_draw = EGL_NO_SURFACE;
737 EGLSurface impl_read = EGL_NO_SURFACE;
738
739 // these are our objects structs passed in
740 egl_context_t * c = NULL;
741 egl_surface_t const * d = NULL;
742 egl_surface_t const * r = NULL;
743
744 // these are the current objects structs
745 egl_context_t * cur_c = get_context(getContext());
746
747 if (ctx != EGL_NO_CONTEXT) {
748 c = get_context(ctx);
749 impl_ctx = c->context;
750 } else {
751 // no context given, use the implementation of the current context
752 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
753 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
754 return setError(EGL_BAD_MATCH, EGL_FALSE);
755 }
756 if (cur_c == NULL) {
757 // no current context
758 // not an error, there is just no current context.
759 return EGL_TRUE;
760 }
761 }
762
763 // retrieve the underlying implementation's draw EGLSurface
764 if (draw != EGL_NO_SURFACE) {
765 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
766 d = get_surface(draw);
767 impl_draw = d->surface;
768 }
769
770 // retrieve the underlying implementation's read EGLSurface
771 if (read != EGL_NO_SURFACE) {
772 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
773 r = get_surface(read);
774 impl_read = r->surface;
775 }
776
777
778 EGLBoolean result = dp->makeCurrent(c, cur_c,
779 draw, read, ctx,
780 impl_draw, impl_read, impl_ctx);
781
782 if (result == EGL_TRUE) {
783 if (c) {
784 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
785 egl_tls_t::setContext(ctx);
786 #if EGL_TRACE
787 if (getEGLDebugLevel() > 0)
788 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
789 #endif
790 _c.acquire();
791 _r.acquire();
792 _d.acquire();
793 } else {
794 setGLHooksThreadSpecific(&gHooksNoContext);
795 egl_tls_t::setContext(EGL_NO_CONTEXT);
796 }
797 } else {
798 // this will ALOGE the error
799 egl_connection_t* const cnx = &gEGLImpl;
800 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
801 }
802 return result;
803 }
804
805
eglQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)806 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
807 EGLint attribute, EGLint *value)
808 {
809 clearError();
810
811 const egl_display_ptr dp = validate_display(dpy);
812 if (!dp) return EGL_FALSE;
813
814 ContextRef _c(dp.get(), ctx);
815 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
816
817 egl_context_t * const c = get_context(ctx);
818 return c->cnx->egl.eglQueryContext(
819 dp->disp.dpy, c->context, attribute, value);
820
821 }
822
eglGetCurrentContext(void)823 EGLContext eglGetCurrentContext(void)
824 {
825 // could be called before eglInitialize(), but we wouldn't have a context
826 // then, and this function would correctly return EGL_NO_CONTEXT.
827
828 clearError();
829
830 EGLContext ctx = getContext();
831 return ctx;
832 }
833
eglGetCurrentSurface(EGLint readdraw)834 EGLSurface eglGetCurrentSurface(EGLint readdraw)
835 {
836 // could be called before eglInitialize(), but we wouldn't have a context
837 // then, and this function would correctly return EGL_NO_SURFACE.
838
839 clearError();
840
841 EGLContext ctx = getContext();
842 if (ctx) {
843 egl_context_t const * const c = get_context(ctx);
844 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
845 switch (readdraw) {
846 case EGL_READ: return c->read;
847 case EGL_DRAW: return c->draw;
848 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
849 }
850 }
851 return EGL_NO_SURFACE;
852 }
853
eglGetCurrentDisplay(void)854 EGLDisplay eglGetCurrentDisplay(void)
855 {
856 // could be called before eglInitialize(), but we wouldn't have a context
857 // then, and this function would correctly return EGL_NO_DISPLAY.
858
859 clearError();
860
861 EGLContext ctx = getContext();
862 if (ctx) {
863 egl_context_t const * const c = get_context(ctx);
864 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
865 return c->dpy;
866 }
867 return EGL_NO_DISPLAY;
868 }
869
eglWaitGL(void)870 EGLBoolean eglWaitGL(void)
871 {
872 clearError();
873
874 egl_connection_t* const cnx = &gEGLImpl;
875 if (!cnx->dso)
876 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
877
878 return cnx->egl.eglWaitGL();
879 }
880
eglWaitNative(EGLint engine)881 EGLBoolean eglWaitNative(EGLint engine)
882 {
883 clearError();
884
885 egl_connection_t* const cnx = &gEGLImpl;
886 if (!cnx->dso)
887 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
888
889 return cnx->egl.eglWaitNative(engine);
890 }
891
eglGetError(void)892 EGLint eglGetError(void)
893 {
894 EGLint err = EGL_SUCCESS;
895 egl_connection_t* const cnx = &gEGLImpl;
896 if (cnx->dso) {
897 err = cnx->egl.eglGetError();
898 }
899 if (err == EGL_SUCCESS) {
900 err = egl_tls_t::getError();
901 }
902 return err;
903 }
904
findBuiltinWrapper(const char * procname)905 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
906 const char* procname) {
907 const egl_connection_t* cnx = &gEGLImpl;
908 void* proc = NULL;
909
910 proc = dlsym(cnx->libEgl, procname);
911 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
912
913 proc = dlsym(cnx->libGles2, procname);
914 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
915
916 proc = dlsym(cnx->libGles1, procname);
917 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
918
919 return NULL;
920 }
921
eglGetProcAddress(const char * procname)922 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
923 {
924 // eglGetProcAddress() could be the very first function called
925 // in which case we must make sure we've initialized ourselves, this
926 // happens the first time egl_get_display() is called.
927
928 clearError();
929
930 if (egl_init_drivers() == EGL_FALSE) {
931 setError(EGL_BAD_PARAMETER, NULL);
932 return NULL;
933 }
934
935 if (FILTER_EXTENSIONS(procname)) {
936 return NULL;
937 }
938
939 __eglMustCastToProperFunctionPointerType addr;
940 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
941 if (addr) return addr;
942
943 addr = findBuiltinWrapper(procname);
944 if (addr) return addr;
945
946 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
947 pthread_mutex_lock(&sExtensionMapMutex);
948
949 /*
950 * Since eglGetProcAddress() is not associated to anything, it needs
951 * to return a function pointer that "works" regardless of what
952 * the current context is.
953 *
954 * For this reason, we return a "forwarder", a small stub that takes
955 * care of calling the function associated with the context
956 * currently bound.
957 *
958 * We first look for extensions we've already resolved, if we're seeing
959 * this extension for the first time, we go through all our
960 * implementations and call eglGetProcAddress() and record the
961 * result in the appropriate implementation hooks and return the
962 * address of the forwarder corresponding to that hook set.
963 *
964 */
965
966 const String8 name(procname);
967 addr = sGLExtentionMap.valueFor(name);
968 const int slot = sGLExtentionSlot;
969
970 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
971 "no more slots for eglGetProcAddress(\"%s\")",
972 procname);
973
974 #if EGL_TRACE
975 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
976 #endif
977
978 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
979 bool found = false;
980
981 egl_connection_t* const cnx = &gEGLImpl;
982 if (cnx->dso && cnx->egl.eglGetProcAddress) {
983 // Extensions are independent of the bound context
984 addr =
985 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
986 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
987 #if EGL_TRACE
988 debugHooks->ext.extensions[slot] =
989 gHooksTrace.ext.extensions[slot] =
990 #endif
991 cnx->egl.eglGetProcAddress(procname);
992 if (addr) found = true;
993 }
994
995 if (found) {
996 addr = gExtensionForwarders[slot];
997 sGLExtentionMap.add(name, addr);
998 sGLExtentionSlot++;
999 }
1000 }
1001
1002 pthread_mutex_unlock(&sExtensionMapMutex);
1003 return addr;
1004 }
1005
1006 class FrameCompletionThread : public Thread {
1007 public:
1008
queueSync(EGLSyncKHR sync)1009 static void queueSync(EGLSyncKHR sync) {
1010 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1011 static bool running = false;
1012 if (!running) {
1013 thread->run("GPUFrameCompletion");
1014 running = true;
1015 }
1016 {
1017 Mutex::Autolock lock(thread->mMutex);
1018 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1019 thread->mFramesQueued).string());
1020 thread->mQueue.push_back(sync);
1021 thread->mCondition.signal();
1022 thread->mFramesQueued++;
1023 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1024 }
1025 }
1026
1027 private:
FrameCompletionThread()1028 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1029
threadLoop()1030 virtual bool threadLoop() {
1031 EGLSyncKHR sync;
1032 uint32_t frameNum;
1033 {
1034 Mutex::Autolock lock(mMutex);
1035 while (mQueue.isEmpty()) {
1036 mCondition.wait(mMutex);
1037 }
1038 sync = mQueue[0];
1039 frameNum = mFramesCompleted;
1040 }
1041 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1042 {
1043 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1044 frameNum).string());
1045 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1046 if (result == EGL_FALSE) {
1047 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1048 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1049 ALOGE("FrameCompletion: timeout waiting for fence");
1050 }
1051 eglDestroySyncKHR(dpy, sync);
1052 }
1053 {
1054 Mutex::Autolock lock(mMutex);
1055 mQueue.removeAt(0);
1056 mFramesCompleted++;
1057 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1058 }
1059 return true;
1060 }
1061
1062 uint32_t mFramesQueued;
1063 uint32_t mFramesCompleted;
1064 Vector<EGLSyncKHR> mQueue;
1065 Condition mCondition;
1066 Mutex mMutex;
1067 };
1068
eglSwapBuffersWithDamageKHR(EGLDisplay dpy,EGLSurface draw,EGLint * rects,EGLint n_rects)1069 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1070 EGLint *rects, EGLint n_rects)
1071 {
1072 ATRACE_CALL();
1073 clearError();
1074
1075 const egl_display_ptr dp = validate_display(dpy);
1076 if (!dp) return EGL_FALSE;
1077
1078 SurfaceRef _s(dp.get(), draw);
1079 if (!_s.get())
1080 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1081
1082 #if EGL_TRACE
1083 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
1084 if (getEGLDebugLevel() > 0) {
1085 if (trace_hooks == NULL) {
1086 if (GLTrace_start() < 0) {
1087 ALOGE("Disabling Tracer for OpenGL ES");
1088 setEGLDebugLevel(0);
1089 } else {
1090 // switch over to the trace version of hooks
1091 EGLContext ctx = egl_tls_t::getContext();
1092 egl_context_t * const c = get_context(ctx);
1093 if (c) {
1094 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1095 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
1096 }
1097 }
1098 }
1099
1100 GLTrace_eglSwapBuffers(dpy, draw);
1101 } else if (trace_hooks != NULL) {
1102 // tracing is now disabled, so switch back to the non trace version
1103 EGLContext ctx = egl_tls_t::getContext();
1104 egl_context_t * const c = get_context(ctx);
1105 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1106 GLTrace_stop();
1107 }
1108 #endif
1109
1110 egl_surface_t const * const s = get_surface(draw);
1111
1112 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1113 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1114 if (sync != EGL_NO_SYNC_KHR) {
1115 FrameCompletionThread::queueSync(sync);
1116 }
1117 }
1118
1119 if (CC_UNLIKELY(dp->finishOnSwap)) {
1120 uint32_t pixel;
1121 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1122 if (c) {
1123 // glReadPixels() ensures that the frame is complete
1124 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1125 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1126 }
1127 }
1128
1129 if (n_rects == 0) {
1130 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1131 }
1132
1133 Vector<android_native_rect_t> androidRects;
1134 for (int r = 0; r < n_rects; ++r) {
1135 int offset = r * 4;
1136 int x = rects[offset];
1137 int y = rects[offset + 1];
1138 int width = rects[offset + 2];
1139 int height = rects[offset + 3];
1140 android_native_rect_t androidRect;
1141 androidRect.left = x;
1142 androidRect.top = y + height;
1143 androidRect.right = x + width;
1144 androidRect.bottom = y;
1145 androidRects.push_back(androidRect);
1146 }
1147 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1148 androidRects.size());
1149
1150 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1151 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1152 rects, n_rects);
1153 } else {
1154 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1155 }
1156 }
1157
eglSwapBuffers(EGLDisplay dpy,EGLSurface surface)1158 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1159 {
1160 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1161 }
1162
eglCopyBuffers(EGLDisplay dpy,EGLSurface surface,NativePixmapType target)1163 EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1164 NativePixmapType target)
1165 {
1166 clearError();
1167
1168 const egl_display_ptr dp = validate_display(dpy);
1169 if (!dp) return EGL_FALSE;
1170
1171 SurfaceRef _s(dp.get(), surface);
1172 if (!_s.get())
1173 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1174
1175 egl_surface_t const * const s = get_surface(surface);
1176 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1177 }
1178
eglQueryString(EGLDisplay dpy,EGLint name)1179 const char* eglQueryString(EGLDisplay dpy, EGLint name)
1180 {
1181 clearError();
1182
1183 const egl_display_ptr dp = validate_display(dpy);
1184 if (!dp) return (const char *) NULL;
1185
1186 switch (name) {
1187 case EGL_VENDOR:
1188 return dp->getVendorString();
1189 case EGL_VERSION:
1190 return dp->getVersionString();
1191 case EGL_EXTENSIONS:
1192 return dp->getExtensionString();
1193 case EGL_CLIENT_APIS:
1194 return dp->getClientApiString();
1195 }
1196 return setError(EGL_BAD_PARAMETER, (const char *)0);
1197 }
1198
eglQueryStringImplementationANDROID(EGLDisplay dpy,EGLint name)1199 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1200 {
1201 clearError();
1202
1203 const egl_display_ptr dp = validate_display(dpy);
1204 if (!dp) return (const char *) NULL;
1205
1206 switch (name) {
1207 case EGL_VENDOR:
1208 return dp->disp.queryString.vendor;
1209 case EGL_VERSION:
1210 return dp->disp.queryString.version;
1211 case EGL_EXTENSIONS:
1212 return dp->disp.queryString.extensions;
1213 case EGL_CLIENT_APIS:
1214 return dp->disp.queryString.clientApi;
1215 }
1216 return setError(EGL_BAD_PARAMETER, (const char *)0);
1217 }
1218
1219 // ----------------------------------------------------------------------------
1220 // EGL 1.1
1221 // ----------------------------------------------------------------------------
1222
eglSurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)1223 EGLBoolean eglSurfaceAttrib(
1224 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1225 {
1226 clearError();
1227
1228 const egl_display_ptr dp = validate_display(dpy);
1229 if (!dp) return EGL_FALSE;
1230
1231 SurfaceRef _s(dp.get(), surface);
1232 if (!_s.get())
1233 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1234
1235 egl_surface_t const * const s = get_surface(surface);
1236 if (s->cnx->egl.eglSurfaceAttrib) {
1237 return s->cnx->egl.eglSurfaceAttrib(
1238 dp->disp.dpy, s->surface, attribute, value);
1239 }
1240 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1241 }
1242
eglBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)1243 EGLBoolean eglBindTexImage(
1244 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1245 {
1246 clearError();
1247
1248 const egl_display_ptr dp = validate_display(dpy);
1249 if (!dp) return EGL_FALSE;
1250
1251 SurfaceRef _s(dp.get(), surface);
1252 if (!_s.get())
1253 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1254
1255 egl_surface_t const * const s = get_surface(surface);
1256 if (s->cnx->egl.eglBindTexImage) {
1257 return s->cnx->egl.eglBindTexImage(
1258 dp->disp.dpy, s->surface, buffer);
1259 }
1260 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1261 }
1262
eglReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)1263 EGLBoolean eglReleaseTexImage(
1264 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1265 {
1266 clearError();
1267
1268 const egl_display_ptr dp = validate_display(dpy);
1269 if (!dp) return EGL_FALSE;
1270
1271 SurfaceRef _s(dp.get(), surface);
1272 if (!_s.get())
1273 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1274
1275 egl_surface_t const * const s = get_surface(surface);
1276 if (s->cnx->egl.eglReleaseTexImage) {
1277 return s->cnx->egl.eglReleaseTexImage(
1278 dp->disp.dpy, s->surface, buffer);
1279 }
1280 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1281 }
1282
eglSwapInterval(EGLDisplay dpy,EGLint interval)1283 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1284 {
1285 clearError();
1286
1287 const egl_display_ptr dp = validate_display(dpy);
1288 if (!dp) return EGL_FALSE;
1289
1290 EGLBoolean res = EGL_TRUE;
1291 egl_connection_t* const cnx = &gEGLImpl;
1292 if (cnx->dso && cnx->egl.eglSwapInterval) {
1293 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1294 }
1295
1296 return res;
1297 }
1298
1299
1300 // ----------------------------------------------------------------------------
1301 // EGL 1.2
1302 // ----------------------------------------------------------------------------
1303
eglWaitClient(void)1304 EGLBoolean eglWaitClient(void)
1305 {
1306 clearError();
1307
1308 egl_connection_t* const cnx = &gEGLImpl;
1309 if (!cnx->dso)
1310 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1311
1312 EGLBoolean res;
1313 if (cnx->egl.eglWaitClient) {
1314 res = cnx->egl.eglWaitClient();
1315 } else {
1316 res = cnx->egl.eglWaitGL();
1317 }
1318 return res;
1319 }
1320
eglBindAPI(EGLenum api)1321 EGLBoolean eglBindAPI(EGLenum api)
1322 {
1323 clearError();
1324
1325 if (egl_init_drivers() == EGL_FALSE) {
1326 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1327 }
1328
1329 // bind this API on all EGLs
1330 EGLBoolean res = EGL_TRUE;
1331 egl_connection_t* const cnx = &gEGLImpl;
1332 if (cnx->dso && cnx->egl.eglBindAPI) {
1333 res = cnx->egl.eglBindAPI(api);
1334 }
1335 return res;
1336 }
1337
eglQueryAPI(void)1338 EGLenum eglQueryAPI(void)
1339 {
1340 clearError();
1341
1342 if (egl_init_drivers() == EGL_FALSE) {
1343 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1344 }
1345
1346 egl_connection_t* const cnx = &gEGLImpl;
1347 if (cnx->dso && cnx->egl.eglQueryAPI) {
1348 return cnx->egl.eglQueryAPI();
1349 }
1350
1351 // or, it can only be OpenGL ES
1352 return EGL_OPENGL_ES_API;
1353 }
1354
eglReleaseThread(void)1355 EGLBoolean eglReleaseThread(void)
1356 {
1357 clearError();
1358
1359 #if EGL_TRACE
1360 if (getEGLDebugLevel() > 0)
1361 GLTrace_eglReleaseThread();
1362 #endif
1363
1364 // If there is context bound to the thread, release it
1365 egl_display_t::loseCurrent(get_context(getContext()));
1366
1367 egl_connection_t* const cnx = &gEGLImpl;
1368 if (cnx->dso && cnx->egl.eglReleaseThread) {
1369 cnx->egl.eglReleaseThread();
1370 }
1371 egl_tls_t::clearTLS();
1372 return EGL_TRUE;
1373 }
1374
eglCreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)1375 EGLSurface eglCreatePbufferFromClientBuffer(
1376 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1377 EGLConfig config, const EGLint *attrib_list)
1378 {
1379 clearError();
1380
1381 egl_connection_t* cnx = NULL;
1382 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1383 if (!dp) return EGL_FALSE;
1384 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1385 return cnx->egl.eglCreatePbufferFromClientBuffer(
1386 dp->disp.dpy, buftype, buffer, config, attrib_list);
1387 }
1388 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1389 }
1390
1391 // ----------------------------------------------------------------------------
1392 // EGL_EGLEXT_VERSION 3
1393 // ----------------------------------------------------------------------------
1394
eglLockSurfaceKHR(EGLDisplay dpy,EGLSurface surface,const EGLint * attrib_list)1395 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1396 const EGLint *attrib_list)
1397 {
1398 clearError();
1399
1400 const egl_display_ptr dp = validate_display(dpy);
1401 if (!dp) return EGL_FALSE;
1402
1403 SurfaceRef _s(dp.get(), surface);
1404 if (!_s.get())
1405 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1406
1407 egl_surface_t const * const s = get_surface(surface);
1408 if (s->cnx->egl.eglLockSurfaceKHR) {
1409 return s->cnx->egl.eglLockSurfaceKHR(
1410 dp->disp.dpy, s->surface, attrib_list);
1411 }
1412 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1413 }
1414
eglUnlockSurfaceKHR(EGLDisplay dpy,EGLSurface surface)1415 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1416 {
1417 clearError();
1418
1419 const egl_display_ptr dp = validate_display(dpy);
1420 if (!dp) return EGL_FALSE;
1421
1422 SurfaceRef _s(dp.get(), surface);
1423 if (!_s.get())
1424 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1425
1426 egl_surface_t const * const s = get_surface(surface);
1427 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1428 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1429 }
1430 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1431 }
1432
eglCreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)1433 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1434 EGLClientBuffer buffer, const EGLint *attrib_list)
1435 {
1436 clearError();
1437
1438 const egl_display_ptr dp = validate_display(dpy);
1439 if (!dp) return EGL_NO_IMAGE_KHR;
1440
1441 ContextRef _c(dp.get(), ctx);
1442 egl_context_t * const c = _c.get();
1443
1444 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1445 egl_connection_t* const cnx = &gEGLImpl;
1446 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1447 result = cnx->egl.eglCreateImageKHR(
1448 dp->disp.dpy,
1449 c ? c->context : EGL_NO_CONTEXT,
1450 target, buffer, attrib_list);
1451 }
1452 return result;
1453 }
1454
eglDestroyImageKHR(EGLDisplay dpy,EGLImageKHR img)1455 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1456 {
1457 clearError();
1458
1459 const egl_display_ptr dp = validate_display(dpy);
1460 if (!dp) return EGL_FALSE;
1461
1462 EGLBoolean result = EGL_FALSE;
1463 egl_connection_t* const cnx = &gEGLImpl;
1464 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1465 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
1466 }
1467 return result;
1468 }
1469
1470 // ----------------------------------------------------------------------------
1471 // EGL_EGLEXT_VERSION 5
1472 // ----------------------------------------------------------------------------
1473
1474
eglCreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1475 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1476 {
1477 clearError();
1478
1479 const egl_display_ptr dp = validate_display(dpy);
1480 if (!dp) return EGL_NO_SYNC_KHR;
1481
1482 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1483 egl_connection_t* const cnx = &gEGLImpl;
1484 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1485 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
1486 }
1487 return result;
1488 }
1489
eglDestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)1490 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1491 {
1492 clearError();
1493
1494 const egl_display_ptr dp = validate_display(dpy);
1495 if (!dp) return EGL_FALSE;
1496
1497 EGLBoolean result = EGL_FALSE;
1498 egl_connection_t* const cnx = &gEGLImpl;
1499 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1500 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
1501 }
1502 return result;
1503 }
1504
eglSignalSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLenum mode)1505 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1506 clearError();
1507
1508 const egl_display_ptr dp = validate_display(dpy);
1509 if (!dp) return EGL_FALSE;
1510
1511 EGLBoolean result = EGL_FALSE;
1512 egl_connection_t* const cnx = &gEGLImpl;
1513 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1514 result = cnx->egl.eglSignalSyncKHR(
1515 dp->disp.dpy, sync, mode);
1516 }
1517 return result;
1518 }
1519
eglClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1520 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1521 EGLint flags, EGLTimeKHR timeout)
1522 {
1523 clearError();
1524
1525 const egl_display_ptr dp = validate_display(dpy);
1526 if (!dp) return EGL_FALSE;
1527
1528 EGLBoolean result = EGL_FALSE;
1529 egl_connection_t* const cnx = &gEGLImpl;
1530 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1531 result = cnx->egl.eglClientWaitSyncKHR(
1532 dp->disp.dpy, sync, flags, timeout);
1533 }
1534 return result;
1535 }
1536
eglGetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1537 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1538 EGLint attribute, EGLint *value)
1539 {
1540 clearError();
1541
1542 const egl_display_ptr dp = validate_display(dpy);
1543 if (!dp) return EGL_FALSE;
1544
1545 EGLBoolean result = EGL_FALSE;
1546 egl_connection_t* const cnx = &gEGLImpl;
1547 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1548 result = cnx->egl.eglGetSyncAttribKHR(
1549 dp->disp.dpy, sync, attribute, value);
1550 }
1551 return result;
1552 }
1553
eglCreateStreamKHR(EGLDisplay dpy,const EGLint * attrib_list)1554 EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1555 {
1556 clearError();
1557
1558 const egl_display_ptr dp = validate_display(dpy);
1559 if (!dp) return EGL_NO_STREAM_KHR;
1560
1561 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1562 egl_connection_t* const cnx = &gEGLImpl;
1563 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1564 result = cnx->egl.eglCreateStreamKHR(
1565 dp->disp.dpy, attrib_list);
1566 }
1567 return result;
1568 }
1569
eglDestroyStreamKHR(EGLDisplay dpy,EGLStreamKHR stream)1570 EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1571 {
1572 clearError();
1573
1574 const egl_display_ptr dp = validate_display(dpy);
1575 if (!dp) return EGL_FALSE;
1576
1577 EGLBoolean result = EGL_FALSE;
1578 egl_connection_t* const cnx = &gEGLImpl;
1579 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1580 result = cnx->egl.eglDestroyStreamKHR(
1581 dp->disp.dpy, stream);
1582 }
1583 return result;
1584 }
1585
eglStreamAttribKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint value)1586 EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1587 EGLenum attribute, EGLint value)
1588 {
1589 clearError();
1590
1591 const egl_display_ptr dp = validate_display(dpy);
1592 if (!dp) return EGL_FALSE;
1593
1594 EGLBoolean result = EGL_FALSE;
1595 egl_connection_t* const cnx = &gEGLImpl;
1596 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1597 result = cnx->egl.eglStreamAttribKHR(
1598 dp->disp.dpy, stream, attribute, value);
1599 }
1600 return result;
1601 }
1602
eglQueryStreamKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint * value)1603 EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1604 EGLenum attribute, EGLint *value)
1605 {
1606 clearError();
1607
1608 const egl_display_ptr dp = validate_display(dpy);
1609 if (!dp) return EGL_FALSE;
1610
1611 EGLBoolean result = EGL_FALSE;
1612 egl_connection_t* const cnx = &gEGLImpl;
1613 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1614 result = cnx->egl.eglQueryStreamKHR(
1615 dp->disp.dpy, stream, attribute, value);
1616 }
1617 return result;
1618 }
1619
eglQueryStreamu64KHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLuint64KHR * value)1620 EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1621 EGLenum attribute, EGLuint64KHR *value)
1622 {
1623 clearError();
1624
1625 const egl_display_ptr dp = validate_display(dpy);
1626 if (!dp) return EGL_FALSE;
1627
1628 EGLBoolean result = EGL_FALSE;
1629 egl_connection_t* const cnx = &gEGLImpl;
1630 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1631 result = cnx->egl.eglQueryStreamu64KHR(
1632 dp->disp.dpy, stream, attribute, value);
1633 }
1634 return result;
1635 }
1636
eglQueryStreamTimeKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLTimeKHR * value)1637 EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1638 EGLenum attribute, EGLTimeKHR *value)
1639 {
1640 clearError();
1641
1642 const egl_display_ptr dp = validate_display(dpy);
1643 if (!dp) return EGL_FALSE;
1644
1645 EGLBoolean result = EGL_FALSE;
1646 egl_connection_t* const cnx = &gEGLImpl;
1647 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1648 result = cnx->egl.eglQueryStreamTimeKHR(
1649 dp->disp.dpy, stream, attribute, value);
1650 }
1651 return result;
1652 }
1653
eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy,EGLConfig config,EGLStreamKHR stream,const EGLint * attrib_list)1654 EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1655 EGLStreamKHR stream, const EGLint *attrib_list)
1656 {
1657 clearError();
1658
1659 egl_display_ptr dp = validate_display(dpy);
1660 if (!dp) return EGL_NO_SURFACE;
1661
1662 egl_connection_t* const cnx = &gEGLImpl;
1663 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1664 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1665 dp->disp.dpy, config, stream, attrib_list);
1666 if (surface != EGL_NO_SURFACE) {
1667 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1668 surface, cnx);
1669 return s;
1670 }
1671 }
1672 return EGL_NO_SURFACE;
1673 }
1674
eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,EGLStreamKHR stream)1675 EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1676 EGLStreamKHR stream)
1677 {
1678 clearError();
1679
1680 const egl_display_ptr dp = validate_display(dpy);
1681 if (!dp) return EGL_FALSE;
1682
1683 EGLBoolean result = EGL_FALSE;
1684 egl_connection_t* const cnx = &gEGLImpl;
1685 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1686 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1687 dp->disp.dpy, stream);
1688 }
1689 return result;
1690 }
1691
eglStreamConsumerAcquireKHR(EGLDisplay dpy,EGLStreamKHR stream)1692 EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1693 EGLStreamKHR stream)
1694 {
1695 clearError();
1696
1697 const egl_display_ptr dp = validate_display(dpy);
1698 if (!dp) return EGL_FALSE;
1699
1700 EGLBoolean result = EGL_FALSE;
1701 egl_connection_t* const cnx = &gEGLImpl;
1702 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1703 result = cnx->egl.eglStreamConsumerAcquireKHR(
1704 dp->disp.dpy, stream);
1705 }
1706 return result;
1707 }
1708
eglStreamConsumerReleaseKHR(EGLDisplay dpy,EGLStreamKHR stream)1709 EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1710 EGLStreamKHR stream)
1711 {
1712 clearError();
1713
1714 const egl_display_ptr dp = validate_display(dpy);
1715 if (!dp) return EGL_FALSE;
1716
1717 EGLBoolean result = EGL_FALSE;
1718 egl_connection_t* const cnx = &gEGLImpl;
1719 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1720 result = cnx->egl.eglStreamConsumerReleaseKHR(
1721 dp->disp.dpy, stream);
1722 }
1723 return result;
1724 }
1725
eglGetStreamFileDescriptorKHR(EGLDisplay dpy,EGLStreamKHR stream)1726 EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1727 EGLDisplay dpy, EGLStreamKHR stream)
1728 {
1729 clearError();
1730
1731 const egl_display_ptr dp = validate_display(dpy);
1732 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1733
1734 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1735 egl_connection_t* const cnx = &gEGLImpl;
1736 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1737 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1738 dp->disp.dpy, stream);
1739 }
1740 return result;
1741 }
1742
eglCreateStreamFromFileDescriptorKHR(EGLDisplay dpy,EGLNativeFileDescriptorKHR file_descriptor)1743 EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1744 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1745 {
1746 clearError();
1747
1748 const egl_display_ptr dp = validate_display(dpy);
1749 if (!dp) return EGL_NO_STREAM_KHR;
1750
1751 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1752 egl_connection_t* const cnx = &gEGLImpl;
1753 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1754 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1755 dp->disp.dpy, file_descriptor);
1756 }
1757 return result;
1758 }
1759
1760 // ----------------------------------------------------------------------------
1761 // EGL_EGLEXT_VERSION 15
1762 // ----------------------------------------------------------------------------
1763
eglWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags)1764 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1765 clearError();
1766 const egl_display_ptr dp = validate_display(dpy);
1767 if (!dp) return EGL_FALSE;
1768 EGLint result = EGL_FALSE;
1769 egl_connection_t* const cnx = &gEGLImpl;
1770 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1771 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1772 }
1773 return result;
1774 }
1775
1776 // ----------------------------------------------------------------------------
1777 // ANDROID extensions
1778 // ----------------------------------------------------------------------------
1779
eglDupNativeFenceFDANDROID(EGLDisplay dpy,EGLSyncKHR sync)1780 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1781 {
1782 clearError();
1783
1784 const egl_display_ptr dp = validate_display(dpy);
1785 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1786
1787 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1788 egl_connection_t* const cnx = &gEGLImpl;
1789 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1790 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1791 }
1792 return result;
1793 }
1794
eglPresentationTimeANDROID(EGLDisplay dpy,EGLSurface surface,EGLnsecsANDROID time)1795 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1796 EGLnsecsANDROID time)
1797 {
1798 clearError();
1799
1800 const egl_display_ptr dp = validate_display(dpy);
1801 if (!dp) {
1802 return EGL_FALSE;
1803 }
1804
1805 SurfaceRef _s(dp.get(), surface);
1806 if (!_s.get()) {
1807 setError(EGL_BAD_SURFACE, EGL_FALSE);
1808 return EGL_FALSE;
1809 }
1810
1811 egl_surface_t const * const s = get_surface(surface);
1812 native_window_set_buffers_timestamp(s->win.get(), time);
1813
1814 return EGL_TRUE;
1815 }
1816
1817 // ----------------------------------------------------------------------------
1818 // NVIDIA extensions
1819 // ----------------------------------------------------------------------------
eglGetSystemTimeFrequencyNV()1820 EGLuint64NV eglGetSystemTimeFrequencyNV()
1821 {
1822 clearError();
1823
1824 if (egl_init_drivers() == EGL_FALSE) {
1825 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1826 }
1827
1828 EGLuint64NV ret = 0;
1829 egl_connection_t* const cnx = &gEGLImpl;
1830
1831 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1832 return cnx->egl.eglGetSystemTimeFrequencyNV();
1833 }
1834
1835 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1836 }
1837
eglGetSystemTimeNV()1838 EGLuint64NV eglGetSystemTimeNV()
1839 {
1840 clearError();
1841
1842 if (egl_init_drivers() == EGL_FALSE) {
1843 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1844 }
1845
1846 EGLuint64NV ret = 0;
1847 egl_connection_t* const cnx = &gEGLImpl;
1848
1849 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1850 return cnx->egl.eglGetSystemTimeNV();
1851 }
1852
1853 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1854 }
1855
1856 // ----------------------------------------------------------------------------
1857 // Partial update extension
1858 // ----------------------------------------------------------------------------
eglSetDamageRegionKHR(EGLDisplay dpy,EGLSurface surface,EGLint * rects,EGLint n_rects)1859 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1860 EGLint *rects, EGLint n_rects)
1861 {
1862 clearError();
1863
1864 const egl_display_ptr dp = validate_display(dpy);
1865 if (!dp) {
1866 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1867 return EGL_FALSE;
1868 }
1869
1870 SurfaceRef _s(dp.get(), surface);
1871 if (!_s.get()) {
1872 setError(EGL_BAD_SURFACE, EGL_FALSE);
1873 return EGL_FALSE;
1874 }
1875
1876 egl_surface_t const * const s = get_surface(surface);
1877 if (s->cnx->egl.eglSetDamageRegionKHR) {
1878 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1879 rects, n_rects);
1880 }
1881
1882 return EGL_FALSE;
1883 }
1884