2 ** Copyright 2007, The Android Open Source Project
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
8 ** http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
24 #include <hardware/gralloc.h>
25 #include <system/window.h>
28 #include <EGL/eglext.h>
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>
36 #include <ui/GraphicBuffer.h>
38 #include <utils/KeyedVector.h>
39 #include <utils/SortedVector.h>
40 #include <utils/String8.h>
41 #include <utils/Trace.h>
43 #include "../egl_impl.h"
46 #include "egl_display.h"
47 #include "egl_object.h"
51 using namespace android;
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
57 // ----------------------------------------------------------------------------
61 struct extention_map_t {
63 __eglMustCastToProperFunctionPointerType address;
67 * This is the list of EGL extensions exposed to applications.
69 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
70 * wrapper and are always available.
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
79 * NOTE: Both strings MUST have a single space as the last character.
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 "
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 "
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 "
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 "
122 // extensions not exposed to applications but used by the ANDROID system
123 // "EGL_ANDROID_blob_cache " // strongly recommended
124 // "EGL_IMG_hibernate_process " // optional
125 // "EGL_ANDROID_native_fence_sync " // strongly recommended
126 // "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
127 // "EGL_ANDROID_image_crop " // optional
130 * EGL Extensions entry-points exposed to 3rd party applications
131 * (keep in sync with gExtensionString above)
134 static const extention_map_t sExtensionMap[] = {
135 // EGL_KHR_lock_surface
136 { "eglLockSurfaceKHR",
137 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
138 { "eglUnlockSurfaceKHR",
139 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
141 // EGL_KHR_image, EGL_KHR_image_base
142 { "eglCreateImageKHR",
143 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
144 { "eglDestroyImageKHR",
145 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
147 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
148 { "eglCreateSyncKHR",
149 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
150 { "eglDestroySyncKHR",
151 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
152 { "eglClientWaitSyncKHR",
153 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
154 { "eglSignalSyncKHR",
155 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
156 { "eglGetSyncAttribKHR",
157 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
159 // EGL_NV_system_time
160 { "eglGetSystemTimeFrequencyNV",
161 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
162 { "eglGetSystemTimeNV",
163 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
167 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
169 // EGL_ANDROID_presentation_time
170 { "eglPresentationTimeANDROID",
171 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
173 // EGL_KHR_swap_buffers_with_damage
174 { "eglSwapBuffersWithDamageKHR",
175 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
177 // EGL_ANDROID_native_client_buffer
178 { "eglCreateNativeClientBufferANDROID",
179 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
181 // EGL_KHR_partial_update
182 { "eglSetDamageRegionKHR",
183 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
185 { "eglCreateStreamKHR",
186 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
187 { "eglDestroyStreamKHR",
188 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
189 { "eglStreamAttribKHR",
190 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
191 { "eglQueryStreamKHR",
192 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
193 { "eglQueryStreamu64KHR",
194 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
195 { "eglQueryStreamTimeKHR",
196 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
197 { "eglCreateStreamProducerSurfaceKHR",
198 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
199 { "eglStreamConsumerGLTextureExternalKHR",
200 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
201 { "eglStreamConsumerAcquireKHR",
202 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
203 { "eglStreamConsumerReleaseKHR",
204 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
205 { "eglGetStreamFileDescriptorKHR",
206 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
207 { "eglCreateStreamFromFileDescriptorKHR",
208 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
212 * These extensions entry-points should not be exposed to applications.
213 * They're used internally by the Android EGL layer.
215 #define FILTER_EXTENSIONS(procname) \
216 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
217 !strcmp((procname), "eglHibernateProcessIMG") || \
218 !strcmp((procname), "eglAwakenProcessIMG") || \
219 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
223 // accesses protected by sExtensionMapMutex
224 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
225 static int sGLExtentionSlot = 0;
226 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
228 static void(*findProcAddress(const char* name,
229 const extention_map_t* map, size_t n))() {
230 for (uint32_t i=0 ; i<n ; i++) {
231 if (!strcmp(name, map[i].name)) {
232 return map[i].address;
238 // ----------------------------------------------------------------------------
240 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
241 extern EGLBoolean egl_init_drivers();
242 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
243 extern gl_hooks_t gHooksTrace;
245 } // namespace android;
248 // ----------------------------------------------------------------------------
250 static inline void clearError() { egl_tls_t::clearError(); }
251 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
253 // ----------------------------------------------------------------------------
255 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
259 uintptr_t index = reinterpret_cast<uintptr_t>(display);
260 if (index >= NUM_DISPLAYS) {
261 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
264 if (egl_init_drivers() == EGL_FALSE) {
265 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
268 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
272 // ----------------------------------------------------------------------------
274 // ----------------------------------------------------------------------------
276 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
280 egl_display_ptr dp = get_display(dpy);
281 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
283 EGLBoolean res = dp->initialize(major, minor);
288 EGLBoolean eglTerminate(EGLDisplay dpy)
290 // NOTE: don't unload the drivers b/c some APIs can be called
291 // after eglTerminate() has been called. eglTerminate() only
292 // terminates an EGLDisplay, not a EGL itself.
296 egl_display_ptr dp = get_display(dpy);
297 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
299 EGLBoolean res = dp->terminate();
304 // ----------------------------------------------------------------------------
306 // ----------------------------------------------------------------------------
308 EGLBoolean eglGetConfigs( EGLDisplay dpy,
310 EGLint config_size, EGLint *num_config)
314 const egl_display_ptr dp = validate_display(dpy);
315 if (!dp) return EGL_FALSE;
318 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
321 EGLBoolean res = EGL_FALSE;
324 egl_connection_t* const cnx = &gEGLImpl;
326 res = cnx->egl.eglGetConfigs(
327 dp->disp.dpy, configs, config_size, num_config);
333 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
334 EGLConfig *configs, EGLint config_size,
339 const egl_display_ptr dp = validate_display(dpy);
340 if (!dp) return EGL_FALSE;
343 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
346 EGLBoolean res = EGL_FALSE;
349 egl_connection_t* const cnx = &gEGLImpl;
352 char value[PROPERTY_VALUE_MAX];
353 property_get("debug.egl.force_msaa", value, "false");
355 if (!strcmp(value, "true")) {
356 size_t attribCount = 0;
357 EGLint attrib = attrib_list[0];
359 // Only enable MSAA if the context is OpenGL ES 2.0 and
360 // if no caveat is requested
361 const EGLint *attribRendererable = NULL;
362 const EGLint *attribCaveat = NULL;
364 // Count the number of attributes and look for
365 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
366 while (attrib != EGL_NONE) {
367 attrib = attrib_list[attribCount];
369 case EGL_RENDERABLE_TYPE:
370 attribRendererable = &attrib_list[attribCount];
372 case EGL_CONFIG_CAVEAT:
373 attribCaveat = &attrib_list[attribCount];
379 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
380 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
382 // Insert 2 extra attributes to force-enable MSAA 4x
383 EGLint aaAttribs[attribCount + 4];
384 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
386 aaAttribs[2] = EGL_SAMPLES;
389 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
392 EGLBoolean resAA = cnx->egl.eglChooseConfig(
393 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
395 if (resAA == EGL_TRUE && numConfigAA > 0) {
396 ALOGD("Enabling MSAA 4x");
397 *num_config = numConfigAA;
404 res = cnx->egl.eglChooseConfig(
405 dp->disp.dpy, attrib_list, configs, config_size, num_config);
410 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
411 EGLint attribute, EGLint *value)
415 egl_connection_t* cnx = NULL;
416 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
417 if (!dp) return EGL_FALSE;
419 return cnx->egl.eglGetConfigAttrib(
420 dp->disp.dpy, config, attribute, value);
423 // ----------------------------------------------------------------------------
425 // ----------------------------------------------------------------------------
427 // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
428 // been added to the Khronos egl.h.
429 #define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
430 #define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
431 #define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
433 // Turn linear formats into corresponding sRGB formats when colorspace is
434 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
435 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
436 // the modification isn't possible, the original dataSpace is returned.
437 static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
439 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
440 return HAL_DATASPACE_SRGB_LINEAR;
441 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
442 return HAL_DATASPACE_SRGB;
447 EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
448 NativeWindowType window,
449 const EGLint *attrib_list)
453 egl_connection_t* cnx = NULL;
454 egl_display_ptr dp = validate_display_connection(dpy, cnx);
456 EGLDisplay iDpy = dp->disp.dpy;
458 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
460 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
461 "failed (%#x) (already connected to another API?)",
463 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
466 // Set the native window's buffers format to match what this config requests.
467 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
468 // of our native format. So if sRGB gamma is requested, we have to
469 // modify the EGLconfig's format before setting the native window's
472 // by default, just pick RGBA_8888
473 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
474 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
477 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
479 // alpha-channel requested, there's really only one suitable format
480 format = HAL_PIXEL_FORMAT_RGBA_8888;
484 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
485 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
486 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
487 EGLint colorDepth = r + g + b;
488 if (colorDepth <= 16) {
489 format = HAL_PIXEL_FORMAT_RGB_565;
491 format = HAL_PIXEL_FORMAT_RGBX_8888;
495 // now select a corresponding sRGB format if needed
496 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
497 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
498 if (*attr == EGL_GL_COLORSPACE_KHR) {
499 if (ENABLE_EGL_KHR_GL_COLORSPACE) {
500 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
502 // Normally we'd pass through unhandled attributes to
503 // the driver. But in case the driver implements this
504 // extension but we're disabling it, we want to prevent
505 // it getting through -- support will be broken without
507 ALOGE("sRGB window surfaces not supported");
508 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
515 int err = native_window_set_buffers_format(window, format);
517 ALOGE("error setting native window pixel format: %s (%d)",
518 strerror(-err), err);
519 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
520 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
524 if (dataSpace != 0) {
525 int err = native_window_set_buffers_data_space(window, dataSpace);
527 ALOGE("error setting native window pixel dataSpace: %s (%d)",
528 strerror(-err), err);
529 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
530 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
534 // the EGL spec requires that a new EGLSurface default to swap interval
535 // 1, so explicitly set that on the window here.
536 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
537 anw->setSwapInterval(anw, 1);
539 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
540 iDpy, config, window, attrib_list);
541 if (surface != EGL_NO_SURFACE) {
542 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
547 // EGLSurface creation failed
548 native_window_set_buffers_format(window, 0);
549 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
551 return EGL_NO_SURFACE;
554 EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
555 NativePixmapType pixmap,
556 const EGLint *attrib_list)
560 egl_connection_t* cnx = NULL;
561 egl_display_ptr dp = validate_display_connection(dpy, cnx);
563 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
564 dp->disp.dpy, config, pixmap, attrib_list);
565 if (surface != EGL_NO_SURFACE) {
566 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
571 return EGL_NO_SURFACE;
574 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
575 const EGLint *attrib_list)
579 egl_connection_t* cnx = NULL;
580 egl_display_ptr dp = validate_display_connection(dpy, cnx);
582 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
583 dp->disp.dpy, config, attrib_list);
584 if (surface != EGL_NO_SURFACE) {
585 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
590 return EGL_NO_SURFACE;
593 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
597 const egl_display_ptr dp = validate_display(dpy);
598 if (!dp) return EGL_FALSE;
600 SurfaceRef _s(dp.get(), surface);
602 return setError(EGL_BAD_SURFACE, EGL_FALSE);
604 egl_surface_t * const s = get_surface(surface);
605 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
606 if (result == EGL_TRUE) {
612 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
613 EGLint attribute, EGLint *value)
617 const egl_display_ptr dp = validate_display(dpy);
618 if (!dp) return EGL_FALSE;
620 SurfaceRef _s(dp.get(), surface);
622 return setError(EGL_BAD_SURFACE, EGL_FALSE);
624 egl_surface_t const * const s = get_surface(surface);
625 return s->cnx->egl.eglQuerySurface(
626 dp->disp.dpy, s->surface, attribute, value);
629 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
633 const egl_display_ptr dp = validate_display(dpy);
638 SurfaceRef _s(dp.get(), surface);
640 setError(EGL_BAD_SURFACE, EGL_FALSE);
645 // ----------------------------------------------------------------------------
647 // ----------------------------------------------------------------------------
649 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
650 EGLContext share_list, const EGLint *attrib_list)
654 egl_connection_t* cnx = NULL;
655 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
657 if (share_list != EGL_NO_CONTEXT) {
658 if (!ContextRef(dp.get(), share_list).get()) {
659 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
661 egl_context_t* const c = get_context(share_list);
662 share_list = c->context;
664 EGLContext context = cnx->egl.eglCreateContext(
665 dp->disp.dpy, config, share_list, attrib_list);
666 if (context != EGL_NO_CONTEXT) {
667 // figure out if it's a GLESv1 or GLESv2
670 while (*attrib_list != EGL_NONE) {
671 GLint attr = *attrib_list++;
672 GLint value = *attrib_list++;
673 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
675 version = egl_connection_t::GLESv1_INDEX;
676 } else if (value == 2 || value == 3) {
677 version = egl_connection_t::GLESv2_INDEX;
682 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
687 return EGL_NO_CONTEXT;
690 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
694 const egl_display_ptr dp = validate_display(dpy);
698 ContextRef _c(dp.get(), ctx);
700 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
702 egl_context_t * const c = get_context(ctx);
703 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
704 if (result == EGL_TRUE) {
710 EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
711 EGLSurface read, EGLContext ctx)
715 egl_display_ptr dp = validate_display(dpy);
716 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
718 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
719 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
720 // a valid but uninitialized display.
721 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
722 (draw != EGL_NO_SURFACE) ) {
723 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
726 // get a reference to the object passed in
727 ContextRef _c(dp.get(), ctx);
728 SurfaceRef _d(dp.get(), draw);
729 SurfaceRef _r(dp.get(), read);
731 // validate the context (if not EGL_NO_CONTEXT)
732 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
733 // EGL_NO_CONTEXT is valid
734 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
737 // these are the underlying implementation's object
738 EGLContext impl_ctx = EGL_NO_CONTEXT;
739 EGLSurface impl_draw = EGL_NO_SURFACE;
740 EGLSurface impl_read = EGL_NO_SURFACE;
742 // these are our objects structs passed in
743 egl_context_t * c = NULL;
744 egl_surface_t const * d = NULL;
745 egl_surface_t const * r = NULL;
747 // these are the current objects structs
748 egl_context_t * cur_c = get_context(getContext());
750 if (ctx != EGL_NO_CONTEXT) {
751 c = get_context(ctx);
752 impl_ctx = c->context;
754 // no context given, use the implementation of the current context
755 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
756 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
757 return setError(EGL_BAD_MATCH, EGL_FALSE);
760 // no current context
761 // not an error, there is just no current context.
766 // retrieve the underlying implementation's draw EGLSurface
767 if (draw != EGL_NO_SURFACE) {
768 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
769 d = get_surface(draw);
770 impl_draw = d->surface;
773 // retrieve the underlying implementation's read EGLSurface
774 if (read != EGL_NO_SURFACE) {
775 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
776 r = get_surface(read);
777 impl_read = r->surface;
781 EGLBoolean result = dp->makeCurrent(c, cur_c,
783 impl_draw, impl_read, impl_ctx);
785 if (result == EGL_TRUE) {
787 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
788 egl_tls_t::setContext(ctx);
793 setGLHooksThreadSpecific(&gHooksNoContext);
794 egl_tls_t::setContext(EGL_NO_CONTEXT);
797 // this will ALOGE the error
798 egl_connection_t* const cnx = &gEGLImpl;
799 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
805 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
806 EGLint attribute, EGLint *value)
810 const egl_display_ptr dp = validate_display(dpy);
811 if (!dp) return EGL_FALSE;
813 ContextRef _c(dp.get(), ctx);
814 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
816 egl_context_t * const c = get_context(ctx);
817 return c->cnx->egl.eglQueryContext(
818 dp->disp.dpy, c->context, attribute, value);
822 EGLContext eglGetCurrentContext(void)
824 // could be called before eglInitialize(), but we wouldn't have a context
825 // then, and this function would correctly return EGL_NO_CONTEXT.
829 EGLContext ctx = getContext();
833 EGLSurface eglGetCurrentSurface(EGLint readdraw)
835 // could be called before eglInitialize(), but we wouldn't have a context
836 // then, and this function would correctly return EGL_NO_SURFACE.
840 EGLContext ctx = getContext();
842 egl_context_t const * const c = get_context(ctx);
843 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
845 case EGL_READ: return c->read;
846 case EGL_DRAW: return c->draw;
847 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
850 return EGL_NO_SURFACE;
853 EGLDisplay eglGetCurrentDisplay(void)
855 // could be called before eglInitialize(), but we wouldn't have a context
856 // then, and this function would correctly return EGL_NO_DISPLAY.
860 EGLContext ctx = getContext();
862 egl_context_t const * const c = get_context(ctx);
863 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
866 return EGL_NO_DISPLAY;
869 EGLBoolean eglWaitGL(void)
873 egl_connection_t* const cnx = &gEGLImpl;
875 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
877 return cnx->egl.eglWaitGL();
880 EGLBoolean eglWaitNative(EGLint engine)
884 egl_connection_t* const cnx = &gEGLImpl;
886 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
888 return cnx->egl.eglWaitNative(engine);
891 EGLint eglGetError(void)
893 EGLint err = EGL_SUCCESS;
894 egl_connection_t* const cnx = &gEGLImpl;
896 err = cnx->egl.eglGetError();
898 if (err == EGL_SUCCESS) {
899 err = egl_tls_t::getError();
904 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
905 const char* procname) {
906 const egl_connection_t* cnx = &gEGLImpl;
909 proc = dlsym(cnx->libEgl, procname);
910 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
912 proc = dlsym(cnx->libGles2, procname);
913 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
915 proc = dlsym(cnx->libGles1, procname);
916 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
921 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
923 // eglGetProcAddress() could be the very first function called
924 // in which case we must make sure we've initialized ourselves, this
925 // happens the first time egl_get_display() is called.
929 if (egl_init_drivers() == EGL_FALSE) {
930 setError(EGL_BAD_PARAMETER, NULL);
934 if (FILTER_EXTENSIONS(procname)) {
938 __eglMustCastToProperFunctionPointerType addr;
939 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
940 if (addr) return addr;
942 addr = findBuiltinWrapper(procname);
943 if (addr) return addr;
945 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
946 pthread_mutex_lock(&sExtensionMapMutex);
949 * Since eglGetProcAddress() is not associated to anything, it needs
950 * to return a function pointer that "works" regardless of what
951 * the current context is.
953 * For this reason, we return a "forwarder", a small stub that takes
954 * care of calling the function associated with the context
957 * We first look for extensions we've already resolved, if we're seeing
958 * this extension for the first time, we go through all our
959 * implementations and call eglGetProcAddress() and record the
960 * result in the appropriate implementation hooks and return the
961 * address of the forwarder corresponding to that hook set.
965 const String8 name(procname);
966 addr = sGLExtentionMap.valueFor(name);
967 const int slot = sGLExtentionSlot;
969 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
970 "no more slots for eglGetProcAddress(\"%s\")",
973 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
976 egl_connection_t* const cnx = &gEGLImpl;
977 if (cnx->dso && cnx->egl.eglGetProcAddress) {
978 // Extensions are independent of the bound context
980 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
981 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
982 cnx->egl.eglGetProcAddress(procname);
983 if (addr) found = true;
987 addr = gExtensionForwarders[slot];
988 sGLExtentionMap.add(name, addr);
993 pthread_mutex_unlock(&sExtensionMapMutex);
997 class FrameCompletionThread : public Thread {
1000 static void queueSync(EGLSyncKHR sync) {
1001 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1002 static bool running = false;
1004 thread->run("GPUFrameCompletion");
1008 Mutex::Autolock lock(thread->mMutex);
1009 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1010 thread->mFramesQueued).string());
1011 thread->mQueue.push_back(sync);
1012 thread->mCondition.signal();
1013 thread->mFramesQueued++;
1014 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1019 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1021 virtual bool threadLoop() {
1025 Mutex::Autolock lock(mMutex);
1026 while (mQueue.isEmpty()) {
1027 mCondition.wait(mMutex);
1030 frameNum = mFramesCompleted;
1032 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1034 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1035 frameNum).string());
1036 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1037 if (result == EGL_FALSE) {
1038 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1039 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1040 ALOGE("FrameCompletion: timeout waiting for fence");
1042 eglDestroySyncKHR(dpy, sync);
1045 Mutex::Autolock lock(mMutex);
1048 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1053 uint32_t mFramesQueued;
1054 uint32_t mFramesCompleted;
1055 Vector<EGLSyncKHR> mQueue;
1056 Condition mCondition;
1060 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1061 EGLint *rects, EGLint n_rects)
1066 const egl_display_ptr dp = validate_display(dpy);
1067 if (!dp) return EGL_FALSE;
1069 SurfaceRef _s(dp.get(), draw);
1071 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1073 egl_surface_t const * const s = get_surface(draw);
1075 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1076 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1077 if (sync != EGL_NO_SYNC_KHR) {
1078 FrameCompletionThread::queueSync(sync);
1082 if (CC_UNLIKELY(dp->finishOnSwap)) {
1084 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1086 // glReadPixels() ensures that the frame is complete
1087 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1088 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1093 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1096 Vector<android_native_rect_t> androidRects;
1097 for (int r = 0; r < n_rects; ++r) {
1099 int x = rects[offset];
1100 int y = rects[offset + 1];
1101 int width = rects[offset + 2];
1102 int height = rects[offset + 3];
1103 android_native_rect_t androidRect;
1104 androidRect.left = x;
1105 androidRect.top = y + height;
1106 androidRect.right = x + width;
1107 androidRect.bottom = y;
1108 androidRects.push_back(androidRect);
1110 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1111 androidRects.size());
1113 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1114 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1117 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1121 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1123 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1126 EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1127 NativePixmapType target)
1131 const egl_display_ptr dp = validate_display(dpy);
1132 if (!dp) return EGL_FALSE;
1134 SurfaceRef _s(dp.get(), surface);
1136 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1138 egl_surface_t const * const s = get_surface(surface);
1139 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1142 const char* eglQueryString(EGLDisplay dpy, EGLint name)
1146 const egl_display_ptr dp = validate_display(dpy);
1147 if (!dp) return (const char *) NULL;
1151 return dp->getVendorString();
1153 return dp->getVersionString();
1154 case EGL_EXTENSIONS:
1155 return dp->getExtensionString();
1156 case EGL_CLIENT_APIS:
1157 return dp->getClientApiString();
1159 return setError(EGL_BAD_PARAMETER, (const char *)0);
1162 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1166 const egl_display_ptr dp = validate_display(dpy);
1167 if (!dp) return (const char *) NULL;
1171 return dp->disp.queryString.vendor;
1173 return dp->disp.queryString.version;
1174 case EGL_EXTENSIONS:
1175 return dp->disp.queryString.extensions;
1176 case EGL_CLIENT_APIS:
1177 return dp->disp.queryString.clientApi;
1179 return setError(EGL_BAD_PARAMETER, (const char *)0);
1182 // ----------------------------------------------------------------------------
1184 // ----------------------------------------------------------------------------
1186 EGLBoolean eglSurfaceAttrib(
1187 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1191 const egl_display_ptr dp = validate_display(dpy);
1192 if (!dp) return EGL_FALSE;
1194 SurfaceRef _s(dp.get(), surface);
1196 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1198 egl_surface_t const * const s = get_surface(surface);
1200 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
1201 int err = native_window_set_auto_refresh(s->win.get(),
1202 value ? true : false);
1203 return (err == NO_ERROR) ? EGL_TRUE :
1204 setError(EGL_BAD_SURFACE, EGL_FALSE);
1207 if (s->cnx->egl.eglSurfaceAttrib) {
1208 return s->cnx->egl.eglSurfaceAttrib(
1209 dp->disp.dpy, s->surface, attribute, value);
1211 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1214 EGLBoolean eglBindTexImage(
1215 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1219 const egl_display_ptr dp = validate_display(dpy);
1220 if (!dp) return EGL_FALSE;
1222 SurfaceRef _s(dp.get(), surface);
1224 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1226 egl_surface_t const * const s = get_surface(surface);
1227 if (s->cnx->egl.eglBindTexImage) {
1228 return s->cnx->egl.eglBindTexImage(
1229 dp->disp.dpy, s->surface, buffer);
1231 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1234 EGLBoolean eglReleaseTexImage(
1235 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1239 const egl_display_ptr dp = validate_display(dpy);
1240 if (!dp) return EGL_FALSE;
1242 SurfaceRef _s(dp.get(), surface);
1244 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1246 egl_surface_t const * const s = get_surface(surface);
1247 if (s->cnx->egl.eglReleaseTexImage) {
1248 return s->cnx->egl.eglReleaseTexImage(
1249 dp->disp.dpy, s->surface, buffer);
1251 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1254 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1258 const egl_display_ptr dp = validate_display(dpy);
1259 if (!dp) return EGL_FALSE;
1261 EGLBoolean res = EGL_TRUE;
1262 egl_connection_t* const cnx = &gEGLImpl;
1263 if (cnx->dso && cnx->egl.eglSwapInterval) {
1264 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1271 // ----------------------------------------------------------------------------
1273 // ----------------------------------------------------------------------------
1275 EGLBoolean eglWaitClient(void)
1279 egl_connection_t* const cnx = &gEGLImpl;
1281 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1284 if (cnx->egl.eglWaitClient) {
1285 res = cnx->egl.eglWaitClient();
1287 res = cnx->egl.eglWaitGL();
1292 EGLBoolean eglBindAPI(EGLenum api)
1296 if (egl_init_drivers() == EGL_FALSE) {
1297 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1300 // bind this API on all EGLs
1301 EGLBoolean res = EGL_TRUE;
1302 egl_connection_t* const cnx = &gEGLImpl;
1303 if (cnx->dso && cnx->egl.eglBindAPI) {
1304 res = cnx->egl.eglBindAPI(api);
1309 EGLenum eglQueryAPI(void)
1313 if (egl_init_drivers() == EGL_FALSE) {
1314 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1317 egl_connection_t* const cnx = &gEGLImpl;
1318 if (cnx->dso && cnx->egl.eglQueryAPI) {
1319 return cnx->egl.eglQueryAPI();
1322 // or, it can only be OpenGL ES
1323 return EGL_OPENGL_ES_API;
1326 EGLBoolean eglReleaseThread(void)
1330 // If there is context bound to the thread, release it
1331 egl_display_t::loseCurrent(get_context(getContext()));
1333 egl_connection_t* const cnx = &gEGLImpl;
1334 if (cnx->dso && cnx->egl.eglReleaseThread) {
1335 cnx->egl.eglReleaseThread();
1337 egl_tls_t::clearTLS();
1341 EGLSurface eglCreatePbufferFromClientBuffer(
1342 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1343 EGLConfig config, const EGLint *attrib_list)
1347 egl_connection_t* cnx = NULL;
1348 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1349 if (!dp) return EGL_FALSE;
1350 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1351 return cnx->egl.eglCreatePbufferFromClientBuffer(
1352 dp->disp.dpy, buftype, buffer, config, attrib_list);
1354 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1357 // ----------------------------------------------------------------------------
1358 // EGL_EGLEXT_VERSION 3
1359 // ----------------------------------------------------------------------------
1361 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1362 const EGLint *attrib_list)
1366 const egl_display_ptr dp = validate_display(dpy);
1367 if (!dp) return EGL_FALSE;
1369 SurfaceRef _s(dp.get(), surface);
1371 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1373 egl_surface_t const * const s = get_surface(surface);
1374 if (s->cnx->egl.eglLockSurfaceKHR) {
1375 return s->cnx->egl.eglLockSurfaceKHR(
1376 dp->disp.dpy, s->surface, attrib_list);
1378 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1381 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1385 const egl_display_ptr dp = validate_display(dpy);
1386 if (!dp) return EGL_FALSE;
1388 SurfaceRef _s(dp.get(), surface);
1390 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1392 egl_surface_t const * const s = get_surface(surface);
1393 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1394 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1396 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1399 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1400 EGLClientBuffer buffer, const EGLint *attrib_list)
1404 const egl_display_ptr dp = validate_display(dpy);
1405 if (!dp) return EGL_NO_IMAGE_KHR;
1407 ContextRef _c(dp.get(), ctx);
1408 egl_context_t * const c = _c.get();
1410 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1411 egl_connection_t* const cnx = &gEGLImpl;
1412 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1413 result = cnx->egl.eglCreateImageKHR(
1415 c ? c->context : EGL_NO_CONTEXT,
1416 target, buffer, attrib_list);
1421 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1425 const egl_display_ptr dp = validate_display(dpy);
1426 if (!dp) return EGL_FALSE;
1428 EGLBoolean result = EGL_FALSE;
1429 egl_connection_t* const cnx = &gEGLImpl;
1430 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1431 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
1436 // ----------------------------------------------------------------------------
1437 // EGL_EGLEXT_VERSION 5
1438 // ----------------------------------------------------------------------------
1441 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1445 const egl_display_ptr dp = validate_display(dpy);
1446 if (!dp) return EGL_NO_SYNC_KHR;
1448 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1449 egl_connection_t* const cnx = &gEGLImpl;
1450 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1451 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
1456 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1460 const egl_display_ptr dp = validate_display(dpy);
1461 if (!dp) return EGL_FALSE;
1463 EGLBoolean result = EGL_FALSE;
1464 egl_connection_t* const cnx = &gEGLImpl;
1465 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1466 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
1471 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1474 const egl_display_ptr dp = validate_display(dpy);
1475 if (!dp) return EGL_FALSE;
1477 EGLBoolean result = EGL_FALSE;
1478 egl_connection_t* const cnx = &gEGLImpl;
1479 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1480 result = cnx->egl.eglSignalSyncKHR(
1481 dp->disp.dpy, sync, mode);
1486 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1487 EGLint flags, EGLTimeKHR timeout)
1491 const egl_display_ptr dp = validate_display(dpy);
1492 if (!dp) return EGL_FALSE;
1494 EGLBoolean result = EGL_FALSE;
1495 egl_connection_t* const cnx = &gEGLImpl;
1496 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1497 result = cnx->egl.eglClientWaitSyncKHR(
1498 dp->disp.dpy, sync, flags, timeout);
1503 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1504 EGLint attribute, EGLint *value)
1508 const egl_display_ptr dp = validate_display(dpy);
1509 if (!dp) return EGL_FALSE;
1511 EGLBoolean result = EGL_FALSE;
1512 egl_connection_t* const cnx = &gEGLImpl;
1513 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1514 result = cnx->egl.eglGetSyncAttribKHR(
1515 dp->disp.dpy, sync, attribute, value);
1520 EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1524 const egl_display_ptr dp = validate_display(dpy);
1525 if (!dp) return EGL_NO_STREAM_KHR;
1527 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1528 egl_connection_t* const cnx = &gEGLImpl;
1529 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1530 result = cnx->egl.eglCreateStreamKHR(
1531 dp->disp.dpy, attrib_list);
1536 EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1540 const egl_display_ptr dp = validate_display(dpy);
1541 if (!dp) return EGL_FALSE;
1543 EGLBoolean result = EGL_FALSE;
1544 egl_connection_t* const cnx = &gEGLImpl;
1545 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1546 result = cnx->egl.eglDestroyStreamKHR(
1547 dp->disp.dpy, stream);
1552 EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1553 EGLenum attribute, EGLint value)
1557 const egl_display_ptr dp = validate_display(dpy);
1558 if (!dp) return EGL_FALSE;
1560 EGLBoolean result = EGL_FALSE;
1561 egl_connection_t* const cnx = &gEGLImpl;
1562 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1563 result = cnx->egl.eglStreamAttribKHR(
1564 dp->disp.dpy, stream, attribute, value);
1569 EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1570 EGLenum attribute, EGLint *value)
1574 const egl_display_ptr dp = validate_display(dpy);
1575 if (!dp) return EGL_FALSE;
1577 EGLBoolean result = EGL_FALSE;
1578 egl_connection_t* const cnx = &gEGLImpl;
1579 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1580 result = cnx->egl.eglQueryStreamKHR(
1581 dp->disp.dpy, stream, attribute, value);
1586 EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1587 EGLenum attribute, EGLuint64KHR *value)
1591 const egl_display_ptr dp = validate_display(dpy);
1592 if (!dp) return EGL_FALSE;
1594 EGLBoolean result = EGL_FALSE;
1595 egl_connection_t* const cnx = &gEGLImpl;
1596 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1597 result = cnx->egl.eglQueryStreamu64KHR(
1598 dp->disp.dpy, stream, attribute, value);
1603 EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1604 EGLenum attribute, EGLTimeKHR *value)
1608 const egl_display_ptr dp = validate_display(dpy);
1609 if (!dp) return EGL_FALSE;
1611 EGLBoolean result = EGL_FALSE;
1612 egl_connection_t* const cnx = &gEGLImpl;
1613 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1614 result = cnx->egl.eglQueryStreamTimeKHR(
1615 dp->disp.dpy, stream, attribute, value);
1620 EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1621 EGLStreamKHR stream, const EGLint *attrib_list)
1625 egl_display_ptr dp = validate_display(dpy);
1626 if (!dp) return EGL_NO_SURFACE;
1628 egl_connection_t* const cnx = &gEGLImpl;
1629 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1630 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1631 dp->disp.dpy, config, stream, attrib_list);
1632 if (surface != EGL_NO_SURFACE) {
1633 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1638 return EGL_NO_SURFACE;
1641 EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1642 EGLStreamKHR stream)
1646 const egl_display_ptr dp = validate_display(dpy);
1647 if (!dp) return EGL_FALSE;
1649 EGLBoolean result = EGL_FALSE;
1650 egl_connection_t* const cnx = &gEGLImpl;
1651 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1652 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1653 dp->disp.dpy, stream);
1658 EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1659 EGLStreamKHR stream)
1663 const egl_display_ptr dp = validate_display(dpy);
1664 if (!dp) return EGL_FALSE;
1666 EGLBoolean result = EGL_FALSE;
1667 egl_connection_t* const cnx = &gEGLImpl;
1668 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1669 result = cnx->egl.eglStreamConsumerAcquireKHR(
1670 dp->disp.dpy, stream);
1675 EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1676 EGLStreamKHR stream)
1680 const egl_display_ptr dp = validate_display(dpy);
1681 if (!dp) return EGL_FALSE;
1683 EGLBoolean result = EGL_FALSE;
1684 egl_connection_t* const cnx = &gEGLImpl;
1685 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1686 result = cnx->egl.eglStreamConsumerReleaseKHR(
1687 dp->disp.dpy, stream);
1692 EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1693 EGLDisplay dpy, EGLStreamKHR stream)
1697 const egl_display_ptr dp = validate_display(dpy);
1698 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1700 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1701 egl_connection_t* const cnx = &gEGLImpl;
1702 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1703 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1704 dp->disp.dpy, stream);
1709 EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1710 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1714 const egl_display_ptr dp = validate_display(dpy);
1715 if (!dp) return EGL_NO_STREAM_KHR;
1717 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1718 egl_connection_t* const cnx = &gEGLImpl;
1719 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1720 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1721 dp->disp.dpy, file_descriptor);
1726 // ----------------------------------------------------------------------------
1727 // EGL_EGLEXT_VERSION 15
1728 // ----------------------------------------------------------------------------
1730 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1732 const egl_display_ptr dp = validate_display(dpy);
1733 if (!dp) return EGL_FALSE;
1734 EGLint result = EGL_FALSE;
1735 egl_connection_t* const cnx = &gEGLImpl;
1736 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1737 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1742 // ----------------------------------------------------------------------------
1743 // ANDROID extensions
1744 // ----------------------------------------------------------------------------
1746 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1750 const egl_display_ptr dp = validate_display(dpy);
1751 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1753 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1754 egl_connection_t* const cnx = &gEGLImpl;
1755 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1756 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1761 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1762 EGLnsecsANDROID time)
1766 const egl_display_ptr dp = validate_display(dpy);
1771 SurfaceRef _s(dp.get(), surface);
1773 setError(EGL_BAD_SURFACE, EGL_FALSE);
1777 egl_surface_t const * const s = get_surface(surface);
1778 native_window_set_buffers_timestamp(s->win.get(), time);
1783 EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1789 uint32_t height = 0;
1790 uint32_t format = 0;
1791 uint32_t red_size = 0;
1792 uint32_t green_size = 0;
1793 uint32_t blue_size = 0;
1794 uint32_t alpha_size = 0;
1796 #define GET_POSITIVE_VALUE(case_name, target) \
1801 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1806 while (*attrib_list != EGL_NONE) {
1807 GLint attr = *attrib_list++;
1808 GLint value = *attrib_list++;
1810 GET_POSITIVE_VALUE(EGL_WIDTH, width);
1811 GET_POSITIVE_VALUE(EGL_HEIGHT, height);
1812 GET_POSITIVE_VALUE(EGL_RED_SIZE, red_size);
1813 GET_POSITIVE_VALUE(EGL_GREEN_SIZE, green_size);
1814 GET_POSITIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1815 GET_POSITIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
1816 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1817 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1818 usage |= GRALLOC_USAGE_PROTECTED;
1820 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
1821 usage |= GRALLOC_USAGE_HW_RENDER;
1823 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
1824 usage |= GRALLOC_USAGE_HW_TEXTURE;
1826 // The buffer must be used for either a texture or a
1828 if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1829 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
1830 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1834 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1838 #undef GET_POSITIVE_VALUE
1841 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1842 if (alpha_size == 8) {
1843 format = HAL_PIXEL_FORMAT_RGBA_8888;
1845 format = HAL_PIXEL_FORMAT_RGB_888;
1847 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1849 format == HAL_PIXEL_FORMAT_RGB_565;
1851 ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1852 red_size, green_size, blue_size, alpha_size);
1853 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1856 GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage);
1857 const status_t err = gBuffer->initCheck();
1858 if (err != NO_ERROR) {
1859 ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1860 width, height, format, usage, err);
1861 // Destroy the buffer.
1862 sp<GraphicBuffer> holder(gBuffer);
1863 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
1865 ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1866 gBuffer, width, height, format, usage);
1867 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
1870 // ----------------------------------------------------------------------------
1871 // NVIDIA extensions
1872 // ----------------------------------------------------------------------------
1873 EGLuint64NV eglGetSystemTimeFrequencyNV()
1877 if (egl_init_drivers() == EGL_FALSE) {
1878 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1881 EGLuint64NV ret = 0;
1882 egl_connection_t* const cnx = &gEGLImpl;
1884 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1885 return cnx->egl.eglGetSystemTimeFrequencyNV();
1888 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1891 EGLuint64NV eglGetSystemTimeNV()
1895 if (egl_init_drivers() == EGL_FALSE) {
1896 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1899 EGLuint64NV ret = 0;
1900 egl_connection_t* const cnx = &gEGLImpl;
1902 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1903 return cnx->egl.eglGetSystemTimeNV();
1906 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1909 // ----------------------------------------------------------------------------
1910 // Partial update extension
1911 // ----------------------------------------------------------------------------
1912 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1913 EGLint *rects, EGLint n_rects)
1917 const egl_display_ptr dp = validate_display(dpy);
1919 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1923 SurfaceRef _s(dp.get(), surface);
1925 setError(EGL_BAD_SURFACE, EGL_FALSE);
1929 egl_surface_t const * const s = get_surface(surface);
1930 if (s->cnx->egl.eglSetDamageRegionKHR) {
1931 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,