eglApi.cpp revision b1e2c72041da3d3fcc042d5f19ce1e33466a0e01
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
51using 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
61namespace android {
62
63struct 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 */
83extern 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        ;
93extern 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 */
140static 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
236static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
237static int sGLExtentionSlot = 0;
238static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
239
240static 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
252extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
253extern EGLBoolean egl_init_drivers();
254extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
255extern gl_hooks_t gHooksTrace;
256
257} // namespace android;
258
259
260// ----------------------------------------------------------------------------
261
262static inline void clearError() { egl_tls_t::clearError(); }
263static inline EGLContext getContext() { return egl_tls_t::getContext(); }
264
265// ----------------------------------------------------------------------------
266
267EGLDisplay 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
288EGLBoolean 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
300EGLBoolean 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
320EGLBoolean 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
345EGLBoolean 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
422EGLBoolean 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.
449static 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
459EGLSurface 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
566EGLSurface 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
586EGLSurface 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
605EGLBoolean 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
624EGLBoolean 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
641void 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
661EGLContext 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
702EGLBoolean 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
722EGLBoolean 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
817EGLBoolean 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
834EGLContext 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
845EGLSurface 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
865EGLDisplay 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
881EGLBoolean 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
892EGLBoolean 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
903EGLint 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
916static __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
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
1009class FrameCompletionThread : public Thread {
1010public:
1011
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
1030private:
1031    FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1032
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
1072EGLBoolean 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
1133EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1134{
1135    return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1136}
1137
1138EGLBoolean 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
1154const 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
1174EGLAPI 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
1198EGLBoolean 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
1233EGLBoolean 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
1253EGLBoolean 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
1273EGLBoolean 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
1294EGLBoolean 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
1311EGLBoolean 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
1328EGLenum 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
1345EGLBoolean 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
1360EGLSurface 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
1380EGLBoolean 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
1400EGLBoolean 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
1418EGLImageKHR 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
1440EGLBoolean 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
1460EGLSyncKHR 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
1475EGLBoolean 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
1490EGLBoolean 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
1505EGLint 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
1522EGLBoolean 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
1539EGLStreamKHR 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
1555EGLBoolean 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
1571EGLBoolean 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
1588EGLBoolean 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
1605EGLBoolean 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
1622EGLBoolean 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
1639EGLSurface 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
1660EGLBoolean 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
1677EGLBoolean 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
1694EGLBoolean 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
1711EGLNativeFileDescriptorKHR 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
1728EGLStreamKHR 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
1749EGLint 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
1765EGLint 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
1780EGLBoolean 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
1802EGLClientBuffer 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    const status_t err = gBuffer->initCheck();
1877    if (err != NO_ERROR) {
1878        ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1879                width, height, format, usage, err);
1880        // Destroy the buffer.
1881        sp<GraphicBuffer> holder(gBuffer);
1882        return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
1883    }
1884    ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1885            gBuffer, width, height, format, usage);
1886    return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
1887}
1888
1889// ----------------------------------------------------------------------------
1890// NVIDIA extensions
1891// ----------------------------------------------------------------------------
1892EGLuint64NV eglGetSystemTimeFrequencyNV()
1893{
1894    clearError();
1895
1896    if (egl_init_drivers() == EGL_FALSE) {
1897        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1898    }
1899
1900    EGLuint64NV ret = 0;
1901    egl_connection_t* const cnx = &gEGLImpl;
1902
1903    if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1904        return cnx->egl.eglGetSystemTimeFrequencyNV();
1905    }
1906
1907    return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1908}
1909
1910EGLuint64NV eglGetSystemTimeNV()
1911{
1912    clearError();
1913
1914    if (egl_init_drivers() == EGL_FALSE) {
1915        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1916    }
1917
1918    EGLuint64NV ret = 0;
1919    egl_connection_t* const cnx = &gEGLImpl;
1920
1921    if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1922        return cnx->egl.eglGetSystemTimeNV();
1923    }
1924
1925    return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1926}
1927
1928// ----------------------------------------------------------------------------
1929// Partial update extension
1930// ----------------------------------------------------------------------------
1931EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1932        EGLint *rects, EGLint n_rects)
1933{
1934    clearError();
1935
1936    const egl_display_ptr dp = validate_display(dpy);
1937    if (!dp) {
1938        setError(EGL_BAD_DISPLAY, EGL_FALSE);
1939        return EGL_FALSE;
1940    }
1941
1942    SurfaceRef _s(dp.get(), surface);
1943    if (!_s.get()) {
1944        setError(EGL_BAD_SURFACE, EGL_FALSE);
1945        return EGL_FALSE;
1946    }
1947
1948    egl_surface_t const * const s = get_surface(surface);
1949    if (s->cnx->egl.eglSetDamageRegionKHR) {
1950        return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1951                rects, n_rects);
1952    }
1953
1954    return EGL_FALSE;
1955}
1956
1957EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
1958        EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
1959        EGLnsecsANDROID *values)
1960{
1961    clearError();
1962
1963    const egl_display_ptr dp = validate_display(dpy);
1964    if (!dp) {
1965        setError(EGL_BAD_DISPLAY, EGL_FALSE);
1966        return EGL_FALSE;
1967    }
1968
1969    SurfaceRef _s(dp.get(), surface);
1970    if (!_s.get()) {
1971        setError(EGL_BAD_SURFACE, EGL_FALSE);
1972        return EGL_FALSE;
1973    }
1974
1975    egl_surface_t const * const s = get_surface(surface);
1976
1977    if (!s->enableTimestamps) {
1978        setError(EGL_BAD_SURFACE, EGL_FALSE);
1979        return EGL_FALSE;
1980    }
1981
1982    nsecs_t* postedTime = nullptr;
1983    nsecs_t* acquireTime = nullptr;
1984    nsecs_t* refreshStartTime = nullptr;
1985    nsecs_t* GLCompositionDoneTime = nullptr;
1986    nsecs_t* displayRetireTime = nullptr;
1987    nsecs_t* releaseTime = nullptr;
1988
1989    for (int i = 0; i < numTimestamps; i++) {
1990        switch (timestamps[i]) {
1991            case EGL_QUEUE_TIME_ANDROID:
1992                postedTime = &values[i];
1993                break;
1994            case EGL_RENDERING_COMPLETE_TIME_ANDROID:
1995                acquireTime = &values[i];
1996                break;
1997            case EGL_COMPOSITION_START_TIME_ANDROID:
1998                refreshStartTime = &values[i];
1999                break;
2000            case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
2001                GLCompositionDoneTime = &values[i];
2002                break;
2003            case EGL_DISPLAY_RETIRE_TIME_ANDROID:
2004                displayRetireTime = &values[i];
2005                break;
2006            case EGL_READS_DONE_TIME_ANDROID:
2007                releaseTime = &values[i];
2008                break;
2009            default:
2010                setError(EGL_BAD_PARAMETER, EGL_FALSE);
2011                return EGL_FALSE;
2012        }
2013    }
2014
2015    status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
2016            postedTime, acquireTime, refreshStartTime, GLCompositionDoneTime,
2017            displayRetireTime, releaseTime);
2018
2019    if (ret != NO_ERROR) {
2020        setError(EGL_BAD_ACCESS, EGL_FALSE);
2021        return EGL_FALSE;
2022    }
2023
2024    return EGL_TRUE;
2025}
2026
2027EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface,
2028        EGLint timestamp)
2029{
2030    clearError();
2031
2032    const egl_display_ptr dp = validate_display(dpy);
2033    if (!dp) {
2034        setError(EGL_BAD_DISPLAY, EGL_FALSE);
2035        return EGL_FALSE;
2036    }
2037
2038    SurfaceRef _s(dp.get(), surface);
2039    if (!_s.get()) {
2040        setError(EGL_BAD_SURFACE, EGL_FALSE);
2041        return EGL_FALSE;
2042    }
2043
2044    switch (timestamp) {
2045#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
2046        case EGL_QUEUE_TIME_ANDROID:
2047        case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2048        case EGL_COMPOSITION_START_TIME_ANDROID:
2049        case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
2050        case EGL_DISPLAY_RETIRE_TIME_ANDROID:
2051        case EGL_READS_DONE_TIME_ANDROID:
2052            return EGL_TRUE;
2053#endif
2054        default:
2055            return EGL_FALSE;
2056    }
2057}
2058