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