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