Home | History | Annotate | Download | only in egl
      1 /*
      2 * Copyright (C) 2011 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 #include <assert.h>
     18 #include "HostConnection.h"
     19 #include "ThreadInfo.h"
     20 #include "eglDisplay.h"
     21 #include "eglSync.h"
     22 #include "egl_ftable.h"
     23 #include <cutils/log.h>
     24 #include <cutils/properties.h>
     25 #include "goldfish_sync.h"
     26 #include "gralloc_cb.h"
     27 #include "GLClientState.h"
     28 #include "GLSharedGroup.h"
     29 #include "eglContext.h"
     30 #include "ClientAPIExts.h"
     31 #include "EGLImage.h"
     32 #include "ProcessPipe.h"
     33 
     34 #include "GLEncoder.h"
     35 #ifdef WITH_GLES2
     36 #include "GL2Encoder.h"
     37 #endif
     38 
     39 #include <GLES3/gl31.h>
     40 
     41 #if PLATFORM_SDK_VERSION < 18
     42 #define override
     43 #endif
     44 
     45 #if PLATFORM_SDK_VERSION >= 16
     46 #include <system/window.h>
     47 #else // PLATFORM_SDK_VERSION >= 16
     48 #include <private/ui/android_natives_priv.h>
     49 #endif // PLATFORM_SDK_VERSION >= 16
     50 
     51 #if PLATFORM_SDK_VERSION <= 16
     52 #define queueBuffer_DEPRECATED queueBuffer
     53 #define dequeueBuffer_DEPRECATED dequeueBuffer
     54 #define cancelBuffer_DEPRECATED cancelBuffer
     55 #endif // PLATFORM_SDK_VERSION <= 16
     56 
     57 #define DEBUG_EGL 0
     58 
     59 #if DEBUG_EGL
     60 #define DPRINT(fmt,...) ALOGD("%s: " fmt, __FUNCTION__, ##__VA_ARGS__);
     61 #else
     62 #define DPRINT(...)
     63 #endif
     64 
     65 template<typename T>
     66 static T setErrorFunc(GLint error, T returnValue) {
     67     getEGLThreadInfo()->eglError = error;
     68     return returnValue;
     69 }
     70 
     71 const char *  eglStrError(EGLint err)
     72 {
     73     switch (err){
     74         case EGL_SUCCESS:           return "EGL_SUCCESS";
     75         case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
     76         case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
     77         case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
     78         case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
     79         case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
     80         case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
     81         case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
     82         case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
     83         case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
     84         case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
     85         case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
     86         case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
     87         case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
     88         case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
     89         default: return "UNKNOWN";
     90     }
     91 }
     92 
     93 #define LOG_EGL_ERRORS 1
     94 
     95 #ifdef LOG_EGL_ERRORS
     96 
     97 #define setErrorReturn(error, retVal)     \
     98     {                                                \
     99         ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
    100         return setErrorFunc(error, retVal);            \
    101     }
    102 
    103 #define RETURN_ERROR(ret,err)           \
    104     ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
    105     getEGLThreadInfo()->eglError = err;    \
    106     return ret;
    107 
    108 #else //!LOG_EGL_ERRORS
    109 
    110 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
    111 
    112 #define RETURN_ERROR(ret,err)           \
    113     getEGLThreadInfo()->eglError = err; \
    114     return ret;
    115 
    116 #endif //LOG_EGL_ERRORS
    117 
    118 #define VALIDATE_CONFIG(cfg,ret) \
    119     if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
    120         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
    121     }
    122 
    123 #define VALIDATE_DISPLAY(dpy,ret) \
    124     if ((dpy) != (EGLDisplay)&s_display) { \
    125         RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
    126     }
    127 
    128 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
    129     VALIDATE_DISPLAY(dpy, ret)    \
    130     if (!s_display.initialized()) {        \
    131         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
    132     }
    133 
    134 #define DEFINE_HOST_CONNECTION \
    135     HostConnection *hostCon = HostConnection::get(); \
    136     ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
    137 
    138 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
    139     HostConnection *hostCon = HostConnection::get(); \
    140     if (!hostCon) { \
    141         ALOGE("egl: Failed to get host connection\n"); \
    142         return ret; \
    143     } \
    144     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
    145     if (!rcEnc) { \
    146         ALOGE("egl: Failed to get renderControl encoder context\n"); \
    147         return ret; \
    148     }
    149 
    150 #define DEFINE_AND_VALIDATE_HOST_CONNECTION_FOR_TLS(ret, tls) \
    151     HostConnection *hostCon = HostConnection::getWithThreadInfo(tls); \
    152     if (!hostCon) { \
    153         ALOGE("egl: Failed to get host connection\n"); \
    154         return ret; \
    155     } \
    156     ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
    157     if (!rcEnc) { \
    158         ALOGE("egl: Failed to get renderControl encoder context\n"); \
    159         return ret; \
    160     }
    161 
    162 #define VALIDATE_CONTEXT_RETURN(context,ret)  \
    163     if (!(context) || !s_display.isContext((context))) {                         \
    164         RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
    165     }
    166 
    167 #define VALIDATE_SURFACE_RETURN(surface, ret)    \
    168     if ((surface) != EGL_NO_SURFACE) {    \
    169         if (!s_display.isSurface((surface))) \
    170             setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); \
    171         egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
    172         if (s->dpy != (EGLDisplay)&s_display)    \
    173             setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
    174     }
    175 
    176 // The one and only supported display object.
    177 static eglDisplay s_display;
    178 
    179 // Extra defines not in the official EGL spec yet,
    180 // but required in Android CTS.
    181 
    182 #define EGL_TIMESTAMPS_ANDROID 0x314D
    183 
    184 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx, int maj, int min) :
    185     dpy(dpy),
    186     config(config),
    187     read(EGL_NO_SURFACE),
    188     draw(EGL_NO_SURFACE),
    189     shareCtx(shareCtx),
    190     rcContext(0),
    191     versionString(NULL),
    192     majorVersion(maj),
    193     minorVersion(min),
    194     vendorString(NULL) ,
    195     rendererString(NULL),
    196     shaderVersionString(NULL),
    197     extensionString(NULL),
    198     deletePending(0),
    199     goldfishSyncFd(-1)
    200 {
    201 
    202     DEFINE_HOST_CONNECTION;
    203     switch (rcEnc->getGLESMaxVersion()) {
    204         case GLES_MAX_VERSION_3_0:
    205             deviceMajorVersion = 3;
    206             deviceMinorVersion = 0;
    207             break;
    208         case GLES_MAX_VERSION_3_1:
    209             deviceMajorVersion = 3;
    210             deviceMinorVersion = 1;
    211             break;
    212         case GLES_MAX_VERSION_3_2:
    213             deviceMajorVersion = 3;
    214             deviceMinorVersion = 2;
    215             break;
    216         default:
    217             deviceMajorVersion = 2;
    218             deviceMinorVersion = 0;
    219             break;
    220     }
    221 
    222     flags = 0;
    223     clientState = new GLClientState(majorVersion, minorVersion);
    224      if (shareCtx)
    225         sharedGroup = shareCtx->getSharedGroup();
    226     else
    227         sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
    228     assert(dpy == (EGLDisplay)&s_display);
    229     s_display.onCreateContext((EGLContext)this);
    230 };
    231 
    232 int EGLContext_t::getGoldfishSyncFd() {
    233     if (goldfishSyncFd < 0) {
    234         goldfishSyncFd = goldfish_sync_open();
    235     }
    236     return goldfishSyncFd;
    237 }
    238 
    239 EGLContext_t::~EGLContext_t()
    240 {
    241     if (goldfishSyncFd > 0) {
    242         goldfish_sync_close(goldfishSyncFd);
    243         goldfishSyncFd = -1;
    244     }
    245     assert(dpy == (EGLDisplay)&s_display);
    246     s_display.onDestroyContext((EGLContext)this);
    247     delete clientState;
    248     delete [] versionString;
    249     delete [] vendorString;
    250     delete [] rendererString;
    251     delete [] shaderVersionString;
    252     delete [] extensionString;
    253 }
    254 
    255 // ----------------------------------------------------------------------------
    256 //egl_surface_t
    257 
    258 //we don't need to handle depth since it's handled when window created on the host
    259 
    260 struct egl_surface_t {
    261 
    262     EGLDisplay          dpy;
    263     EGLConfig           config;
    264 
    265 
    266     egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
    267     virtual     ~egl_surface_t();
    268 
    269     virtual     void        setSwapInterval(int interval) = 0;
    270     virtual     EGLBoolean  swapBuffers() = 0;
    271 
    272     EGLint      getSwapBehavior() const;
    273     uint32_t    getRcSurface()   { return rcSurface; }
    274     EGLint      getSurfaceType() { return surfaceType; }
    275 
    276     EGLint      getWidth(){ return width; }
    277     EGLint      getHeight(){ return height; }
    278     EGLint      getNativeWidth(){ return nativeWidth; }
    279     EGLint      getNativeHeight(){ return nativeHeight; }
    280     void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
    281     EGLint      getTextureFormat() { return texFormat; }
    282     void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
    283     EGLint      getTextureTarget() { return texTarget; }
    284 
    285     virtual     void setCollectingTimestamps(EGLint collect) { }
    286     virtual     EGLint isCollectingTimestamps() const { return EGL_FALSE; }
    287     EGLint      deletePending;
    288     void        setIsCurrent(bool isCurrent) { mIsCurrent = isCurrent; }
    289     bool        isCurrent() const { return mIsCurrent;}
    290 private:
    291     //
    292     //Surface attributes
    293     //
    294     EGLint      width;
    295     EGLint      height;
    296     EGLint      texFormat;
    297     EGLint      texTarget;
    298 
    299     // Width of the actual window being presented (not the EGL texture)
    300     // Give it some default values.
    301     int nativeWidth;
    302     int nativeHeight;
    303     bool mIsCurrent;
    304 protected:
    305     void        setWidth(EGLint w)  { width = w;  }
    306     void        setHeight(EGLint h) { height = h; }
    307     void        setNativeWidth(int w)  { nativeWidth = w;  }
    308     void        setNativeHeight(int h) { nativeHeight = h; }
    309 
    310     EGLint      surfaceType;
    311     uint32_t    rcSurface; //handle to surface created via remote control
    312 };
    313 
    314 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
    315     : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0),
    316       deletePending(0), mIsCurrent(false)
    317 {
    318     width = 0;
    319     height = 0;
    320     // prevent div by 0 in EGL_(HORIZONTAL|VERTICAL)_RESOLUTION queries.
    321     nativeWidth = 1;
    322     nativeHeight = 1;
    323     texFormat = EGL_NO_TEXTURE;
    324     texTarget = EGL_NO_TEXTURE;
    325     assert(dpy == (EGLDisplay)&s_display);
    326     s_display.onCreateSurface((EGLSurface)this);
    327 }
    328 
    329 EGLint egl_surface_t::getSwapBehavior() const {
    330     return EGL_BUFFER_PRESERVED;
    331 }
    332 
    333 egl_surface_t::~egl_surface_t()
    334 {
    335     assert(dpy == (EGLDisplay)&s_display);
    336     s_display.onDestroySurface((EGLSurface)this);
    337 }
    338 
    339 // ----------------------------------------------------------------------------
    340 // egl_window_surface_t
    341 
    342 struct egl_window_surface_t : public egl_surface_t {
    343     static egl_window_surface_t* create(
    344             EGLDisplay dpy, EGLConfig config, EGLint surfType,
    345             ANativeWindow* window);
    346 
    347     virtual ~egl_window_surface_t();
    348 
    349     virtual void       setSwapInterval(int interval);
    350     virtual EGLBoolean swapBuffers();
    351 
    352     virtual     void        setCollectingTimestamps(EGLint collect)
    353         override { collectingTimestamps = (collect == EGL_TRUE) ? true : false; }
    354     virtual     EGLint isCollectingTimestamps() const override { return collectingTimestamps ? EGL_TRUE : EGL_FALSE; }
    355 
    356 
    357 private:
    358     egl_window_surface_t(
    359             EGLDisplay dpy, EGLConfig config, EGLint surfType,
    360             ANativeWindow* window);
    361     EGLBoolean init();
    362 
    363     ANativeWindow*              nativeWindow;
    364     android_native_buffer_t*    buffer;
    365     bool collectingTimestamps;
    366 };
    367 
    368 egl_window_surface_t::egl_window_surface_t (
    369         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    370         ANativeWindow* window)
    371 :   egl_surface_t(dpy, config, surfType),
    372     nativeWindow(window),
    373     buffer(NULL),
    374     collectingTimestamps(false)
    375 {
    376     // keep a reference on the window
    377     nativeWindow->common.incRef(&nativeWindow->common);
    378 }
    379 
    380 
    381 EGLBoolean egl_window_surface_t::init()
    382 {
    383     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
    384         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    385     }
    386     setWidth(buffer->width);
    387     setHeight(buffer->height);
    388 
    389     int nativeWidth, nativeHeight;
    390           nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &nativeWidth);
    391           nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &nativeHeight);
    392 
    393     setNativeWidth(nativeWidth);
    394     setNativeHeight(nativeHeight);
    395 
    396     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    397     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
    398             getWidth(), getHeight());
    399     if (!rcSurface) {
    400         ALOGE("rcCreateWindowSurface returned 0");
    401         return EGL_FALSE;
    402     }
    403     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    404             ((cb_handle_t*)(buffer->handle))->hostHandle);
    405 
    406     return EGL_TRUE;
    407 }
    408 
    409 egl_window_surface_t* egl_window_surface_t::create(
    410         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    411         ANativeWindow* window)
    412 {
    413     egl_window_surface_t* wnd = new egl_window_surface_t(
    414             dpy, config, surfType, window);
    415     if (wnd && !wnd->init()) {
    416         delete wnd;
    417         wnd = NULL;
    418     }
    419     return wnd;
    420 }
    421 
    422 egl_window_surface_t::~egl_window_surface_t() {
    423     DEFINE_HOST_CONNECTION;
    424     if (rcSurface && rcEnc) {
    425         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    426     }
    427     if (buffer) {
    428         nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
    429     }
    430     nativeWindow->common.decRef(&nativeWindow->common);
    431 }
    432 
    433 void egl_window_surface_t::setSwapInterval(int interval)
    434 {
    435     nativeWindow->setSwapInterval(nativeWindow, interval);
    436 }
    437 
    438 // createNativeSync() creates an OpenGL sync object on the host
    439 // using rcCreateSyncKHR. If necessary, a native fence FD will
    440 // also be created through the goldfish sync device.
    441 // Returns a handle to the host-side FenceSync object.
    442 static uint64_t createNativeSync(EGLenum type,
    443                                  const EGLint* attrib_list,
    444                                  int num_actual_attribs,
    445                                  bool destroy_when_signaled,
    446                                  int fd_in,
    447                                  int* fd_out) {
    448     DEFINE_HOST_CONNECTION;
    449 
    450     uint64_t sync_handle;
    451     uint64_t thread_handle;
    452 
    453     EGLint* actual_attribs =
    454         (EGLint*)(num_actual_attribs == 0 ? NULL : attrib_list);
    455 
    456     rcEnc->rcCreateSyncKHR(rcEnc, type,
    457                            actual_attribs,
    458                            num_actual_attribs * sizeof(EGLint),
    459                            destroy_when_signaled,
    460                            &sync_handle,
    461                            &thread_handle);
    462 
    463     if (type == EGL_SYNC_NATIVE_FENCE_ANDROID && fd_in < 0) {
    464         int queue_work_err =
    465             goldfish_sync_queue_work(
    466                     getEGLThreadInfo()->currentContext->getGoldfishSyncFd(),
    467                     sync_handle,
    468                     thread_handle,
    469                     fd_out);
    470 
    471         DPRINT("got native fence fd=%d queue_work_err=%d",
    472                *fd_out, queue_work_err);
    473     }
    474 
    475     return sync_handle;
    476 }
    477 
    478 // createGoldfishOpenGLNativeSync() is for creating host-only sync objects
    479 // that are needed by only this goldfish opengl driver,
    480 // such as in swapBuffers().
    481 // The guest will not see any of these, and these sync objects will be
    482 // destroyed on the host when signaled.
    483 // A native fence FD is possibly returned.
    484 static void createGoldfishOpenGLNativeSync(int* fd_out) {
    485     createNativeSync(EGL_SYNC_NATIVE_FENCE_ANDROID,
    486                      NULL /* empty attrib list */,
    487                      0 /* 0 attrib count */,
    488                      true /* destroy when signaled. this is host-only
    489                              and there will only be one waiter */,
    490                      -1 /* we want a new fd */,
    491                      fd_out);
    492 }
    493 
    494 EGLBoolean egl_window_surface_t::swapBuffers()
    495 {
    496 
    497     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    498 
    499     // Follow up flushWindowColorBuffer with a fence command.
    500     // When the fence command finishes,
    501     // we're sure that the buffer on the host
    502     // has been blitted.
    503     //
    504     // |presentFenceFd| guards the presentation of the
    505     // current frame with a goldfish sync fence fd.
    506     //
    507     // When |presentFenceFd| is signaled, the recipient
    508     // of the buffer that was sent through queueBuffer
    509     // can be sure that the buffer is current.
    510     //
    511     // If we don't take care of this synchronization,
    512     // an old frame can be processed by surfaceflinger,
    513     // resulting in out of order frames.
    514 
    515     int presentFenceFd = -1;
    516 
    517     if (buffer == NULL) {
    518         ALOGE("egl_window_surface_t::swapBuffers called with NULL buffer");
    519         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    520     }
    521 
    522 #if PLATFORM_SDK_VERSION <= 16
    523     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
    524     // equivalent to glFinish if no native sync
    525     eglWaitClient();
    526     nativeWindow->queueBuffer(nativeWindow, buffer);
    527 #else
    528     if (rcEnc->hasNativeSync()) {
    529         rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
    530         createGoldfishOpenGLNativeSync(&presentFenceFd);
    531     } else {
    532         rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
    533         // equivalent to glFinish if no native sync
    534         eglWaitClient();
    535     }
    536 
    537     DPRINT("queueBuffer with fence %d", presentFenceFd);
    538     nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
    539 #endif
    540 
    541     DPRINT("calling dequeueBuffer...");
    542 
    543 #if PLATFORM_SDK_VERSION <= 16
    544     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
    545         buffer = NULL;
    546         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    547     }
    548 #else
    549     int acquireFenceFd = -1;
    550     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &acquireFenceFd)) {
    551         buffer = NULL;
    552         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    553     }
    554 
    555     DPRINT("dequeueBuffer with fence %d", acquireFenceFd);
    556 
    557     if (acquireFenceFd > 0) {
    558         close(acquireFenceFd);
    559     }
    560 #endif
    561 
    562     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    563             ((cb_handle_t *)(buffer->handle))->hostHandle);
    564 
    565     setWidth(buffer->width);
    566     setHeight(buffer->height);
    567 
    568     return EGL_TRUE;
    569 }
    570 
    571 // ----------------------------------------------------------------------------
    572 //egl_pbuffer_surface_t
    573 
    574 struct egl_pbuffer_surface_t : public egl_surface_t {
    575     static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
    576             EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
    577 
    578     virtual ~egl_pbuffer_surface_t();
    579 
    580     virtual void       setSwapInterval(int interval) { (void)interval; }
    581     virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
    582 
    583     uint32_t getRcColorBuffer() { return rcColorBuffer; }
    584 
    585 private:
    586     egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
    587             int32_t w, int32_t h);
    588     EGLBoolean init(GLenum format);
    589 
    590     uint32_t rcColorBuffer;
    591 };
    592 
    593 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
    594         EGLint surfType, int32_t w, int32_t h)
    595 :   egl_surface_t(dpy, config, surfType),
    596     rcColorBuffer(0)
    597 {
    598     setWidth(w);
    599     setHeight(h);
    600 }
    601 
    602 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
    603 {
    604     DEFINE_HOST_CONNECTION;
    605     if (rcEnc) {
    606         if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
    607         if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    608     }
    609 }
    610 
    611 // Destroy a pending surface and set it to NULL.
    612 
    613 static void s_destroyPendingSurfaceAndSetNull(EGLSurface* surface) {
    614     if (!s_display.isSurface(surface)) {
    615         *surface = NULL;
    616         return;
    617     }
    618 
    619     egl_surface_t* surf = static_cast<egl_surface_t *>(*surface);
    620     if (surf && surf->deletePending) {
    621         delete surf;
    622         *surface = NULL;
    623     }
    624 }
    625 
    626 static void s_destroyPendingSurfacesInContext(EGLContext_t* context) {
    627     if (context->read == context->draw) {
    628         // If they are the same, delete it only once
    629         s_destroyPendingSurfaceAndSetNull(&context->draw);
    630         if (context->draw == NULL) {
    631             context->read = NULL;
    632         }
    633     } else {
    634         s_destroyPendingSurfaceAndSetNull(&context->draw);
    635         s_destroyPendingSurfaceAndSetNull(&context->read);
    636     }
    637 }
    638 
    639 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
    640 {
    641     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    642 
    643     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
    644             getWidth(), getHeight());
    645     if (!rcSurface) {
    646         ALOGE("rcCreateWindowSurface returned 0");
    647         return EGL_FALSE;
    648     }
    649 
    650     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), pixelFormat);
    651     if (!rcColorBuffer) {
    652         ALOGE("rcCreateColorBuffer returned 0");
    653         return EGL_FALSE;
    654     }
    655 
    656     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
    657 
    658     return EGL_TRUE;
    659 }
    660 
    661 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
    662         EGLConfig config, EGLint surfType, int32_t w, int32_t h,
    663         GLenum pixelFormat)
    664 {
    665     egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
    666             w, h);
    667     if (pb && !pb->init(pixelFormat)) {
    668         delete pb;
    669         pb = NULL;
    670     }
    671     return pb;
    672 }
    673 
    674 // Required for Skia.
    675 static const char kOESEGLImageExternalEssl3[] = "GL_OES_EGL_image_external_essl3";
    676 
    677 static bool sWantES30OrAbove(const char* exts) {
    678     if (strstr(exts, kGLESMaxVersion_3_0) ||
    679         strstr(exts, kGLESMaxVersion_3_1) ||
    680         strstr(exts, kGLESMaxVersion_3_2)) {
    681         return true;
    682     }
    683     return false;
    684 }
    685 
    686 static std::vector<std::string> getExtStringArray() {
    687     std::vector<std::string> res;
    688 
    689     EGLThreadInfo *tInfo = getEGLThreadInfo();
    690     if (!tInfo || !tInfo->currentContext) {
    691         return res;
    692     }
    693 
    694 #define GL_EXTENSIONS                     0x1F03
    695 
    696     DEFINE_AND_VALIDATE_HOST_CONNECTION(res);
    697 
    698     char *hostStr = NULL;
    699     int n = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, NULL, 0);
    700     if (n < 0) {
    701         hostStr = new char[-n+1];
    702         n = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, hostStr, -n);
    703         if (n <= 0) {
    704             delete [] hostStr;
    705             hostStr = NULL;
    706         }
    707     }
    708 
    709     if (!hostStr || !strlen(hostStr)) { return res; }
    710 
    711     // find the number of extensions
    712     int extStart = 0;
    713     int extEnd = 0;
    714     int currentExtIndex = 0;
    715     int numExts = 0;
    716 
    717     if (sWantES30OrAbove(hostStr) &&
    718         !strstr(hostStr, kOESEGLImageExternalEssl3)) {
    719         res.push_back(kOESEGLImageExternalEssl3);
    720     }
    721 
    722     while (extEnd < strlen(hostStr)) {
    723         if (hostStr[extEnd] == ' ') {
    724             int extSz = extEnd - extStart;
    725             res.push_back(std::string(hostStr + extStart, extSz));
    726             currentExtIndex++;
    727             extStart = extEnd + 1;
    728         }
    729         extEnd++;
    730     }
    731 
    732     delete [] hostStr;
    733     return res;
    734 }
    735 
    736 static const char *getGLString(int glEnum)
    737 {
    738     EGLThreadInfo *tInfo = getEGLThreadInfo();
    739     if (!tInfo || !tInfo->currentContext) {
    740         return NULL;
    741     }
    742 
    743     const char** strPtr = NULL;
    744 
    745 #define GL_VENDOR                         0x1F00
    746 #define GL_RENDERER                       0x1F01
    747 #define GL_VERSION                        0x1F02
    748 #define GL_SHADING_LANGUAGE_VERSION       0x8B8C
    749 #define GL_EXTENSIONS                     0x1F03
    750 
    751     switch(glEnum) {
    752         case GL_VERSION:
    753             strPtr = &tInfo->currentContext->versionString;
    754             break;
    755         case GL_VENDOR:
    756             strPtr = &tInfo->currentContext->vendorString;
    757             break;
    758         case GL_RENDERER:
    759             strPtr = &tInfo->currentContext->rendererString;
    760             break;
    761         case GL_SHADING_LANGUAGE_VERSION:
    762             strPtr = &tInfo->currentContext->shaderVersionString;
    763             break;
    764         case GL_EXTENSIONS:
    765             strPtr = &tInfo->currentContext->extensionString;
    766             break;
    767     }
    768 
    769     if (!strPtr) {
    770         return NULL;
    771     }
    772 
    773     char* hostStr = NULL;
    774 
    775     if (glEnum == GL_EXTENSIONS) {
    776 
    777         std::vector<std::string> exts = getExtStringArray();
    778 
    779         int totalSz = 1; // null terminator
    780         for (int i = 0; i < exts.size(); i++) {
    781             totalSz += exts[i].size() + 1; // for space
    782         }
    783 
    784         if (totalSz == 1) return NULL;
    785 
    786         hostStr = new char[totalSz];
    787         memset(hostStr, 0, totalSz);
    788 
    789         char* current = hostStr;
    790         for (int i = 0; i < exts.size(); i++) {
    791             memcpy(current, exts[i].c_str(), exts[i].size());
    792             current += exts[i].size();
    793             *current = ' ';
    794             ++current;
    795         }
    796     } else {
    797         //
    798         // first query of that string - need to query host
    799         //
    800         DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
    801         int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
    802         if (n < 0) {
    803             hostStr = new char[-n+1];
    804             n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
    805             if (n <= 0) {
    806                 delete [] hostStr;
    807                 hostStr = NULL;
    808             }
    809         }
    810     }
    811 
    812     //
    813     // keep the string in the context and return its value
    814     //
    815     *strPtr = hostStr;
    816     return hostStr;
    817 }
    818 
    819 // ----------------------------------------------------------------------------
    820 
    821 static EGLClient_eglInterface s_eglIface = {
    822     getThreadInfo: getEGLThreadInfo,
    823     getGLString: getGLString,
    824 };
    825 
    826 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
    827 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
    828 {
    829     //
    830     // we support only EGL_DEFAULT_DISPLAY.
    831     //
    832     if (display_id != EGL_DEFAULT_DISPLAY) {
    833         return EGL_NO_DISPLAY;
    834     }
    835 
    836     return (EGLDisplay)&s_display;
    837 }
    838 
    839 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
    840 {
    841     VALIDATE_DISPLAY(dpy,EGL_FALSE);
    842 
    843     if (!s_display.initialize(&s_eglIface)) {
    844         return EGL_FALSE;
    845     }
    846     if (major!=NULL)
    847         *major = s_display.getVersionMajor();
    848     if (minor!=NULL)
    849         *minor = s_display.getVersionMinor();
    850     return EGL_TRUE;
    851 }
    852 
    853 EGLBoolean eglTerminate(EGLDisplay dpy)
    854 {
    855     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    856 
    857     s_display.terminate();
    858     return EGL_TRUE;
    859 }
    860 
    861 EGLint eglGetError()
    862 {
    863     EGLint error = getEGLThreadInfo()->eglError;
    864     getEGLThreadInfo()->eglError = EGL_SUCCESS;
    865     return error;
    866 }
    867 
    868 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
    869 {
    870     // search in EGL function table
    871     for (int i=0; i<egl_num_funcs; i++) {
    872         if (!strcmp(egl_funcs_by_name[i].name, procname)) {
    873             return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
    874         }
    875     }
    876 
    877     // look in gles client api's extensions table
    878     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
    879 
    880     // Fail - function not found.
    881     return NULL;
    882 }
    883 
    884 const char* eglQueryString(EGLDisplay dpy, EGLint name)
    885 {
    886     VALIDATE_DISPLAY_INIT(dpy, NULL);
    887 
    888     return s_display.queryString(name);
    889 }
    890 
    891 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    892 {
    893     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    894 
    895     if(!num_config) {
    896         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
    897     }
    898 
    899     GLint numConfigs = s_display.getNumConfigs();
    900     if (!configs) {
    901         *num_config = numConfigs;
    902         return EGL_TRUE;
    903     }
    904 
    905     EGLint i;
    906     for (i = 0 ; i < numConfigs && i < config_size ; i++) {
    907         *configs++ = (EGLConfig)(uintptr_t)i;
    908     }
    909     *num_config = i;
    910     return EGL_TRUE;
    911 }
    912 
    913 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    914 {
    915     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    916 
    917     if (!num_config) {
    918         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    919     }
    920 
    921     int attribs_size = 0;
    922     if (attrib_list) {
    923         const EGLint * attrib_p = attrib_list;
    924         while (attrib_p[0] != EGL_NONE) {
    925             attribs_size += 2;
    926             attrib_p += 2;
    927         }
    928         attribs_size++; //for the terminating EGL_NONE
    929     }
    930 
    931     // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
    932     // while the host never supports it.
    933     // We remove the bit here.
    934     EGLint* local_attrib_list = NULL;
    935     if (PLATFORM_SDK_VERSION <= 19) {
    936         local_attrib_list = new EGLint[attribs_size];
    937         memcpy(local_attrib_list, attrib_list, attribs_size * sizeof(EGLint));
    938         EGLint* local_attrib_p = local_attrib_list;
    939         while (local_attrib_p[0] != EGL_NONE) {
    940             if (local_attrib_p[0] == EGL_SURFACE_TYPE) {
    941                 local_attrib_p[1] &= ~(EGLint)EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
    942             }
    943             local_attrib_p += 2;
    944         }
    945     }
    946 
    947     uint32_t* tempConfigs[config_size];
    948     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    949     *num_config = rcEnc->rcChooseConfig(rcEnc,
    950             local_attrib_list ? local_attrib_list:(EGLint*)attrib_list,
    951             attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
    952 
    953     if (local_attrib_list) delete [] local_attrib_list;
    954     if (*num_config <= 0) {
    955         EGLint err = -(*num_config);
    956         *num_config = 0;
    957         switch (err) {
    958             case EGL_BAD_ATTRIBUTE:
    959                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    960             default:
    961                 return EGL_FALSE;
    962         }
    963     }
    964 
    965     if (configs!=NULL) {
    966         EGLint i=0;
    967         for (i=0;i<(*num_config);i++) {
    968              *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
    969         }
    970     }
    971 
    972     return EGL_TRUE;
    973 }
    974 
    975 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
    976 {
    977     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    978     VALIDATE_CONFIG(config, EGL_FALSE);
    979 
    980     if (s_display.getConfigAttrib(config, attribute, value))
    981     {
    982         return EGL_TRUE;
    983     }
    984     else
    985     {
    986         ALOGD("%s: bad attrib 0x%x", __FUNCTION__, attribute);
    987         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
    988     }
    989 }
    990 
    991 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
    992 {
    993     (void)attrib_list;
    994 
    995     VALIDATE_DISPLAY_INIT(dpy, NULL);
    996     VALIDATE_CONFIG(config, EGL_FALSE);
    997     if (win == 0) {
    998         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    999     }
   1000 
   1001     EGLint surfaceType;
   1002     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
   1003 
   1004     if (!(surfaceType & EGL_WINDOW_BIT)) {
   1005         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1006     }
   1007 
   1008     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
   1009         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
   1010     }
   1011 
   1012     egl_surface_t* surface = egl_window_surface_t::create(
   1013             &s_display, config, EGL_WINDOW_BIT, static_cast<ANativeWindow*>(win));
   1014     if (!surface) {
   1015         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
   1016     }
   1017 
   1018     return surface;
   1019 }
   1020 
   1021 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
   1022 {
   1023     VALIDATE_DISPLAY_INIT(dpy, NULL);
   1024     VALIDATE_CONFIG(config, EGL_FALSE);
   1025 
   1026     EGLint surfaceType;
   1027     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
   1028 
   1029     if (!(surfaceType & EGL_PBUFFER_BIT)) {
   1030         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1031     }
   1032 
   1033     int32_t w = 0;
   1034     int32_t h = 0;
   1035     EGLint texFormat = EGL_NO_TEXTURE;
   1036     EGLint texTarget = EGL_NO_TEXTURE;
   1037     while (attrib_list[0] != EGL_NONE) {
   1038         switch (attrib_list[0]) {
   1039             case EGL_WIDTH:
   1040                 w = attrib_list[1];
   1041                 if (w < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1042                 break;
   1043             case EGL_HEIGHT:
   1044                 h = attrib_list[1];
   1045                 if (h < 0) setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1046                 break;
   1047             case EGL_TEXTURE_FORMAT:
   1048                 texFormat = attrib_list[1];
   1049                 break;
   1050             case EGL_TEXTURE_TARGET:
   1051                 texTarget = attrib_list[1];
   1052                 break;
   1053             // the followings are not supported
   1054             case EGL_LARGEST_PBUFFER:
   1055             case EGL_MIPMAP_TEXTURE:
   1056             case EGL_VG_ALPHA_FORMAT:
   1057             case EGL_VG_COLORSPACE:
   1058                 break;
   1059             default:
   1060                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
   1061         };
   1062         attrib_list+=2;
   1063     }
   1064     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
   1065         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
   1066         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1067     }
   1068     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
   1069 
   1070     GLenum pixelFormat;
   1071     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
   1072         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1073 
   1074     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
   1075             EGL_PBUFFER_BIT, w, h, pixelFormat);
   1076     if (!surface) {
   1077         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
   1078     }
   1079 
   1080     //setup attributes
   1081     surface->setTextureFormat(texFormat);
   1082     surface->setTextureTarget(texTarget);
   1083 
   1084     return surface;
   1085 }
   1086 
   1087 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
   1088 {
   1089     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
   1090     //     located on host. In order to support Pixmaps we should either punt
   1091     //     to s/w rendering -or- let the host render to a buffer that will be
   1092     //     copied back to guest at some sync point. None of those methods not
   1093     //     implemented and pixmaps are not used with OpenGL anyway ...
   1094     VALIDATE_CONFIG(config, EGL_FALSE);
   1095     (void)dpy;
   1096     (void)pixmap;
   1097     (void)attrib_list;
   1098     return EGL_NO_SURFACE;
   1099 }
   1100 
   1101 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
   1102 {
   1103     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1104     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
   1105 
   1106     EGLThreadInfo* tInfo = getEGLThreadInfo();
   1107     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
   1108     if (surface->isCurrent()) {
   1109         surface->deletePending = 1;
   1110     } else {
   1111         delete surface;
   1112     }
   1113 
   1114     return EGL_TRUE;
   1115 }
   1116 
   1117 static float s_getNativeDpi() {
   1118     float nativeDPI = 560.0f;
   1119     const char* dpiPropName = "qemu.sf.lcd_density";
   1120     char dpiProp[PROPERTY_VALUE_MAX];
   1121     if (property_get(dpiPropName, dpiProp, NULL) > 0) {
   1122         nativeDPI = atof(dpiProp);
   1123     }
   1124     return nativeDPI;
   1125 }
   1126 
   1127 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
   1128 {
   1129     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1130     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
   1131 
   1132     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
   1133 
   1134     // Parameters involved in queries of EGL_(HORIZONTAL|VERTICAL)_RESOLUTION
   1135     float currWidth, currHeight, scaledResolution, effectiveSurfaceDPI;
   1136     EGLBoolean ret = EGL_TRUE;
   1137     switch (attribute) {
   1138         case EGL_CONFIG_ID:
   1139             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
   1140             break;
   1141         case EGL_WIDTH:
   1142             *value = surface->getWidth();
   1143             break;
   1144         case EGL_HEIGHT:
   1145             *value = surface->getHeight();
   1146             break;
   1147         case EGL_TEXTURE_FORMAT:
   1148             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
   1149                 *value = surface->getTextureFormat();
   1150             }
   1151             break;
   1152         case EGL_TEXTURE_TARGET:
   1153             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) {
   1154                 *value = surface->getTextureTarget();
   1155             }
   1156             break;
   1157         case EGL_SWAP_BEHAVIOR:
   1158         {
   1159             EGLint surfaceType;
   1160             ret = s_display.getConfigAttrib(surface->config, EGL_SURFACE_TYPE,
   1161                     &surfaceType);
   1162             if (ret == EGL_TRUE) {
   1163                 if (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
   1164                     *value = EGL_BUFFER_PRESERVED;
   1165                 } else {
   1166                     *value = EGL_BUFFER_DESTROYED;
   1167                 }
   1168             }
   1169             break;
   1170         }
   1171         case EGL_LARGEST_PBUFFER:
   1172             // not modified for a window or pixmap surface
   1173             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
   1174             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
   1175             break;
   1176         case EGL_MIPMAP_TEXTURE:
   1177             // not modified for a window or pixmap surface
   1178             // and we ignore it when creating a PBuffer surface (default is 0)
   1179             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = false;
   1180             break;
   1181         case EGL_MIPMAP_LEVEL:
   1182             // not modified for a window or pixmap surface
   1183             // and we ignore it when creating a PBuffer surface (default is 0)
   1184             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = 0;
   1185             break;
   1186         case EGL_MULTISAMPLE_RESOLVE:
   1187             // ignored when creating the surface, return default
   1188             *value = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
   1189             break;
   1190         case EGL_HORIZONTAL_RESOLUTION:
   1191             // pixel/mm * EGL_DISPLAY_SCALING
   1192             // TODO: get the DPI from avd config
   1193             currWidth = surface->getWidth();
   1194             scaledResolution = currWidth / surface->getNativeWidth();
   1195             effectiveSurfaceDPI =
   1196                 scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
   1197             *value = (EGLint)(effectiveSurfaceDPI);
   1198             break;
   1199         case EGL_VERTICAL_RESOLUTION:
   1200             // pixel/mm * EGL_DISPLAY_SCALING
   1201             // TODO: get the real DPI from avd config
   1202             currHeight = surface->getHeight();
   1203             scaledResolution = currHeight / surface->getNativeHeight();
   1204             effectiveSurfaceDPI =
   1205                 scaledResolution * s_getNativeDpi() * EGL_DISPLAY_SCALING;
   1206             *value = (EGLint)(effectiveSurfaceDPI);
   1207             break;
   1208         case EGL_PIXEL_ASPECT_RATIO:
   1209             // w / h * EGL_DISPLAY_SCALING
   1210             // Please don't ask why * EGL_DISPLAY_SCALING, the document says it
   1211             *value = 1 * EGL_DISPLAY_SCALING;
   1212             break;
   1213         case EGL_RENDER_BUFFER:
   1214             switch (surface->getSurfaceType()) {
   1215                 case EGL_PBUFFER_BIT:
   1216                     *value = EGL_BACK_BUFFER;
   1217                     break;
   1218                 case EGL_PIXMAP_BIT:
   1219                     *value = EGL_SINGLE_BUFFER;
   1220                     break;
   1221                 case EGL_WINDOW_BIT:
   1222                     // ignored when creating the surface, return default
   1223                     *value = EGL_BACK_BUFFER;
   1224                     break;
   1225                 default:
   1226                     ALOGE("eglQuerySurface %x unknown surface type %x",
   1227                             attribute, surface->getSurfaceType());
   1228                     ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1229                     break;
   1230             }
   1231             break;
   1232         case EGL_VG_COLORSPACE:
   1233             // ignored when creating the surface, return default
   1234             *value = EGL_VG_COLORSPACE_sRGB;
   1235             break;
   1236         case EGL_VG_ALPHA_FORMAT:
   1237             // ignored when creating the surface, return default
   1238             *value = EGL_VG_ALPHA_FORMAT_NONPRE;
   1239             break;
   1240         case EGL_TIMESTAMPS_ANDROID:
   1241             *value = surface->isCollectingTimestamps();
   1242             break;
   1243         //TODO: complete other attributes
   1244         default:
   1245             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
   1246             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1247             break;
   1248     }
   1249 
   1250     return ret;
   1251 }
   1252 
   1253 EGLBoolean eglBindAPI(EGLenum api)
   1254 {
   1255     if (api != EGL_OPENGL_ES_API)
   1256         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1257     return EGL_TRUE;
   1258 }
   1259 
   1260 EGLenum eglQueryAPI()
   1261 {
   1262     return EGL_OPENGL_ES_API;
   1263 }
   1264 
   1265 EGLBoolean eglWaitClient()
   1266 {
   1267     return eglWaitGL();
   1268 }
   1269 
   1270 // We may need to trigger this directly from the TLS destructor.
   1271 static EGLBoolean s_eglReleaseThreadImpl(EGLThreadInfo* tInfo) {
   1272     if (!tInfo) return EGL_TRUE;
   1273 
   1274     tInfo->eglError = EGL_SUCCESS;
   1275     EGLContext_t* context = tInfo->currentContext;
   1276 
   1277     if (!context || !s_display.isContext(context)) return EGL_TRUE;
   1278 
   1279     // The following code is doing pretty much the same thing as
   1280     // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
   1281     // with the only issue that we do not require a valid display here.
   1282     DEFINE_AND_VALIDATE_HOST_CONNECTION_FOR_TLS(EGL_FALSE, tInfo);
   1283     // We are going to call makeCurrent on the null context and surface
   1284     // anyway once we are on the host, so skip rcMakeCurrent here.
   1285     // rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
   1286     context->flags &= ~EGLContext_t::IS_CURRENT;
   1287 
   1288     s_destroyPendingSurfacesInContext(context);
   1289 
   1290     if (context->deletePending) {
   1291         if (context->rcContext) {
   1292             rcEnc->rcDestroyContext(rcEnc, context->rcContext);
   1293             context->rcContext = 0;
   1294         }
   1295         delete context;
   1296     }
   1297     tInfo->currentContext = 0;
   1298 
   1299     return EGL_TRUE;
   1300 }
   1301 
   1302 EGLBoolean eglReleaseThread()
   1303 {
   1304     return s_eglReleaseThreadImpl(getEGLThreadInfo());
   1305 }
   1306 
   1307 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
   1308 {
   1309     //TODO
   1310     (void)dpy;
   1311     (void)buftype;
   1312     (void)buffer;
   1313     (void)config;
   1314     (void)attrib_list;
   1315     ALOGW("%s not implemented", __FUNCTION__);
   1316     return 0;
   1317 }
   1318 
   1319 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
   1320 {
   1321     // Right now we don't do anything when using host GPU.
   1322     // This is purely just to pass the data through
   1323     // without issuing a warning. We may benefit from validating the
   1324     // display and surface for debug purposes.
   1325     // TODO: Find cases where we actually need to do something.
   1326     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1327     VALIDATE_SURFACE_RETURN(surface, EGL_FALSE);
   1328     if (surface == EGL_NO_SURFACE) {
   1329         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1330     }
   1331 
   1332     (void)value;
   1333 
   1334     egl_surface_t* p_surface( static_cast<egl_surface_t*>(surface) );
   1335     switch (attribute) {
   1336     case EGL_MIPMAP_LEVEL:
   1337         return true;
   1338     case EGL_MULTISAMPLE_RESOLVE:
   1339     {
   1340         if (value == EGL_MULTISAMPLE_RESOLVE_BOX) {
   1341             EGLint surface_type;
   1342             s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
   1343             if (0 == (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) {
   1344                 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
   1345             }
   1346         }
   1347         return true;
   1348     }
   1349     case EGL_SWAP_BEHAVIOR:
   1350         if (value == EGL_BUFFER_PRESERVED) {
   1351             EGLint surface_type;
   1352             s_display.getConfigAttrib(p_surface->config, EGL_SURFACE_TYPE, &surface_type);
   1353             if (0 == (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) {
   1354                 setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
   1355             }
   1356         }
   1357         return true;
   1358     case EGL_TIMESTAMPS_ANDROID:
   1359         ALOGD("%s: set frame timestamps collecting %d\n", __func__, value);
   1360         p_surface->setCollectingTimestamps(value);
   1361         return true;
   1362     default:
   1363         ALOGW("%s: attr=0x%x not implemented", __FUNCTION__, attribute);
   1364         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1365     }
   1366     return false;
   1367 }
   1368 
   1369 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
   1370 {
   1371     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1372     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
   1373     if (eglSurface == EGL_NO_SURFACE) {
   1374         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1375     }
   1376 
   1377     if (buffer != EGL_BACK_BUFFER) {
   1378         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1379     }
   1380 
   1381     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
   1382 
   1383     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
   1384         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
   1385     }
   1386 
   1387     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
   1388         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1389     }
   1390 
   1391     //It's now safe to cast to pbuffer surface
   1392     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
   1393 
   1394     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1395     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
   1396 
   1397     return GL_TRUE;
   1398 }
   1399 
   1400 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
   1401 {
   1402     //TODO
   1403     (void)dpy;
   1404     (void)surface;
   1405     (void)buffer;
   1406     ALOGW("%s not implemented", __FUNCTION__);
   1407     return 0;
   1408 }
   1409 
   1410 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
   1411 {
   1412     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1413     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1414 
   1415     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
   1416     if (!ctx) {
   1417         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
   1418     }
   1419     if (!ctx->draw) {
   1420         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1421     }
   1422     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
   1423     draw->setSwapInterval(interval);
   1424 
   1425     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
   1426 
   1427     return EGL_TRUE;
   1428 }
   1429 
   1430 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
   1431 {
   1432     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
   1433     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
   1434 
   1435     EGLint majorVersion = 1; //default
   1436     EGLint minorVersion = 0;
   1437     EGLint context_flags = 0;
   1438     EGLint profile_mask = 0;
   1439     EGLint reset_notification_strategy = 0;
   1440 
   1441     bool wantedMajorVersion = false;
   1442     bool wantedMinorVersion = false;
   1443 
   1444     while (attrib_list && attrib_list[0] != EGL_NONE) {
   1445            EGLint attrib_val = attrib_list[1];
   1446         switch(attrib_list[0]) {
   1447         case EGL_CONTEXT_MAJOR_VERSION_KHR:
   1448             majorVersion = attrib_val;
   1449             wantedMajorVersion = true;
   1450             break;
   1451         case EGL_CONTEXT_MINOR_VERSION_KHR:
   1452             minorVersion = attrib_val;
   1453             wantedMinorVersion = true;
   1454             break;
   1455         case EGL_CONTEXT_FLAGS_KHR:
   1456             if ((attrib_val | EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) ||
   1457                 (attrib_val | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)  ||
   1458                 (attrib_val | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
   1459                 context_flags = attrib_val;
   1460             } else {
   1461                 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
   1462             }
   1463             break;
   1464         case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
   1465             if ((attrib_val | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) ||
   1466                 (attrib_val | EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR)) {
   1467                 profile_mask = attrib_val;
   1468             } else {
   1469                 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
   1470             }
   1471             break;
   1472         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
   1473             // According to the spec, we are allowed not to honor this hint.
   1474             // https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt
   1475             break;
   1476         default:
   1477             ALOGV("eglCreateContext unsupported attrib 0x%x", attrib_list[0]);
   1478             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
   1479         }
   1480         attrib_list+=2;
   1481     }
   1482 
   1483     // Support up to GLES 3.2 depending on advertised version from the host system.
   1484     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
   1485     if (rcEnc->getGLESMaxVersion() >= GLES_MAX_VERSION_3_0) {
   1486         if (!wantedMajorVersion) {
   1487             majorVersion = 1;
   1488             wantedMinorVersion = false;
   1489         }
   1490 
   1491         if (wantedMajorVersion &&
   1492             majorVersion == 2) {
   1493             majorVersion = 3;
   1494             wantedMinorVersion = false;
   1495         }
   1496 
   1497         if (majorVersion == 3 && !wantedMinorVersion) {
   1498             switch (rcEnc->getGLESMaxVersion()) {
   1499                 case GLES_MAX_VERSION_3_0:
   1500                     minorVersion = 0;
   1501                     break;
   1502                 case GLES_MAX_VERSION_3_1:
   1503                     minorVersion = 1;
   1504                     break;
   1505                 case GLES_MAX_VERSION_3_2:
   1506                     minorVersion = 2;
   1507                     break;
   1508                 default:
   1509                     minorVersion = 0;
   1510                     break;
   1511             }
   1512         }
   1513     } else {
   1514         if (!wantedMajorVersion) {
   1515             majorVersion = 1;
   1516         }
   1517     }
   1518 
   1519     switch (majorVersion) {
   1520     case 1:
   1521     case 2:
   1522         break;
   1523     case 3:
   1524         if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_0) {
   1525             ALOGE("%s: EGL_BAD_CONFIG: no ES 3 support", __FUNCTION__);
   1526             setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
   1527         }
   1528         switch (minorVersion) {
   1529             case 0:
   1530                 break;
   1531             case 1:
   1532                 if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_1) {
   1533                     ALOGE("%s: EGL_BAD_CONFIG: no ES 3.1 support", __FUNCTION__);
   1534                     setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
   1535                 }
   1536                 break;
   1537             case 2:
   1538                 if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_2) {
   1539                     ALOGE("%s: EGL_BAD_CONFIG: no ES 3.2 support", __FUNCTION__);
   1540                     setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
   1541                 }
   1542                 break;
   1543             default:
   1544                 ALOGE("%s: EGL_BAD_CONFIG: Unknown ES version %d.%d",
   1545                       __FUNCTION__, majorVersion, minorVersion);
   1546                 setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
   1547         }
   1548         break;
   1549     default:
   1550         setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
   1551     }
   1552 
   1553     uint32_t rcShareCtx = 0;
   1554     EGLContext_t * shareCtx = NULL;
   1555     if (share_context) {
   1556         shareCtx = static_cast<EGLContext_t*>(share_context);
   1557         rcShareCtx = shareCtx->rcContext;
   1558         if (shareCtx->dpy != dpy)
   1559             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
   1560     }
   1561 
   1562     // We've created EGL context. Disconnecting
   1563     // would be dangerous at this point.
   1564     hostCon->setGrallocOnly(false);
   1565 
   1566     int rcMajorVersion = majorVersion;
   1567     if (majorVersion == 3 && minorVersion == 1) {
   1568         rcMajorVersion = 4;
   1569     }
   1570     if (majorVersion == 3 && minorVersion == 2) {
   1571         rcMajorVersion = 4;
   1572     }
   1573     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, rcMajorVersion);
   1574     if (!rcContext) {
   1575         ALOGE("rcCreateContext returned 0");
   1576         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
   1577     }
   1578 
   1579     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx, majorVersion, minorVersion);
   1580     ALOGD("%s: %p: maj %d min %d rcv %d", __FUNCTION__, context, majorVersion, minorVersion, rcMajorVersion);
   1581     if (!context) {
   1582         ALOGE("could not alloc egl context!");
   1583         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
   1584     }
   1585 
   1586     context->rcContext = rcContext;
   1587     return context;
   1588 }
   1589 
   1590 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
   1591 {
   1592     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1593     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
   1594 
   1595     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
   1596 
   1597     if (context->flags & EGLContext_t::IS_CURRENT) {
   1598         context->deletePending = 1;
   1599         return EGL_TRUE;
   1600     }
   1601 
   1602     if (context->rcContext) {
   1603         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1604         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
   1605         context->rcContext = 0;
   1606     }
   1607 
   1608     delete context;
   1609     return EGL_TRUE;
   1610 }
   1611 
   1612 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
   1613 {
   1614     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1615     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
   1616     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
   1617 
   1618     // Only place to initialize the TLS destructor; any
   1619     // thread can suddenly jump in any eglMakeCurrent
   1620     setTlsDestructor((tlsDtorCallback)s_eglReleaseThreadImpl);
   1621 
   1622     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
   1623         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
   1624     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
   1625         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
   1626 
   1627     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
   1628     uint32_t ctxHandle = (context) ? context->rcContext : 0;
   1629     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
   1630     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
   1631     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
   1632     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
   1633 
   1634     //
   1635     // Nothing to do if no binding change has made
   1636     //
   1637     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1638 
   1639     if (tInfo->currentContext == context &&
   1640         (context == NULL ||
   1641         (context && (context->draw == draw) && (context->read == read)))) {
   1642         return EGL_TRUE;
   1643     }
   1644 
   1645     if (tInfo->currentContext) {
   1646         EGLContext_t* prevCtx = tInfo->currentContext;
   1647 
   1648         if (prevCtx->draw) {
   1649             static_cast<egl_surface_t *>(prevCtx->draw)->setIsCurrent(false);
   1650         }
   1651         if (prevCtx->read) {
   1652             static_cast<egl_surface_t *>(prevCtx->read)->setIsCurrent(false);
   1653         }
   1654         s_destroyPendingSurfacesInContext(tInfo->currentContext);
   1655 
   1656         if (prevCtx->deletePending && prevCtx != context) {
   1657             tInfo->currentContext = 0;
   1658             eglDestroyContext(dpy, prevCtx);
   1659         }
   1660     }
   1661 
   1662     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
   1663         // context is current to another thread
   1664         ALOGE("%s: error: EGL_BAD_ACCESS: context %p current to another thread!\n", __FUNCTION__, context);
   1665         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
   1666     }
   1667 
   1668     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1669     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
   1670         ALOGE("rcMakeCurrent returned EGL_FALSE");
   1671         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
   1672     }
   1673 
   1674     //Now make the local bind
   1675     if (context) {
   1676 
   1677         ALOGD("%s: %p: ver %d %d (tinfo %p)", __FUNCTION__, context, context->majorVersion, context->minorVersion, tInfo);
   1678         // This is a nontrivial context.
   1679         // The thread cannot be gralloc-only anymore.
   1680         hostCon->setGrallocOnly(false);
   1681         context->draw = draw;
   1682         context->read = read;
   1683         if (drawSurf) {
   1684             drawSurf->setIsCurrent(true);
   1685         }
   1686         if (readSurf) {
   1687             readSurf->setIsCurrent(true);
   1688         }
   1689         context->flags |= EGLContext_t::IS_CURRENT;
   1690         GLClientState* contextState =
   1691             context->getClientState();
   1692 
   1693         if (!hostCon->gl2Encoder()->isInitialized()) {
   1694             s_display.gles2_iface()->init();
   1695             hostCon->gl2Encoder()->setInitialized();
   1696             ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
   1697         }
   1698         if (contextState->needsInitFromCaps()) {
   1699             // Need to set the version first if
   1700             // querying caps, or validation will trip incorrectly.
   1701             hostCon->gl2Encoder()->setVersion(
   1702                 context->majorVersion,
   1703                 context->minorVersion,
   1704                 context->deviceMajorVersion,
   1705                 context->deviceMinorVersion);
   1706             // Get caps for indexed buffers from host.
   1707             // Some need a current context.
   1708             int max_transform_feedback_separate_attribs = 0;
   1709             int max_uniform_buffer_bindings = 0;
   1710             int max_atomic_counter_buffer_bindings = 0;
   1711             int max_shader_storage_buffer_bindings = 0;
   1712             int max_vertex_attrib_bindings = 0;
   1713             int max_color_attachments = 1;
   1714             int max_draw_buffers = 1;
   1715             if (context->majorVersion > 2) {
   1716                 s_display.gles2_iface()->getIntegerv(
   1717                         GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
   1718                 s_display.gles2_iface()->getIntegerv(
   1719                         GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uniform_buffer_bindings);
   1720                 if (context->minorVersion > 0) {
   1721                     s_display.gles2_iface()->getIntegerv(
   1722                             GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &max_atomic_counter_buffer_bindings);
   1723                     s_display.gles2_iface()->getIntegerv(
   1724                             GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &max_shader_storage_buffer_bindings);
   1725                     s_display.gles2_iface()->getIntegerv(
   1726                             GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
   1727                 }
   1728                 s_display.gles2_iface()->getIntegerv(
   1729                         GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
   1730                 s_display.gles2_iface()->getIntegerv(
   1731                         GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
   1732             }
   1733             contextState->initFromCaps(
   1734                     max_transform_feedback_separate_attribs,
   1735                     max_uniform_buffer_bindings,
   1736                     max_atomic_counter_buffer_bindings,
   1737                     max_shader_storage_buffer_bindings,
   1738                     max_vertex_attrib_bindings,
   1739                     max_color_attachments,
   1740                     max_draw_buffers);
   1741         }
   1742 
   1743         // update the client state, share group, and version
   1744         if (context->majorVersion > 1) {
   1745             hostCon->gl2Encoder()->setClientStateMakeCurrent(
   1746                     contextState,
   1747                     context->majorVersion,
   1748                     context->minorVersion,
   1749                     context->deviceMajorVersion,
   1750                     context->deviceMinorVersion);
   1751             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
   1752         }
   1753         else {
   1754             hostCon->glEncoder()->setClientState(context->getClientState());
   1755             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
   1756         }
   1757     }
   1758     else if (tInfo->currentContext) {
   1759         //release ClientState & SharedGroup
   1760         if (tInfo->currentContext->majorVersion > 1) {
   1761             hostCon->gl2Encoder()->setClientState(NULL);
   1762             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
   1763         }
   1764         else {
   1765             hostCon->glEncoder()->setClientState(NULL);
   1766             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
   1767         }
   1768 
   1769     }
   1770 
   1771     if (tInfo->currentContext && (tInfo->currentContext != context)) {
   1772         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
   1773     }
   1774 
   1775     //Now make current
   1776     tInfo->currentContext = context;
   1777 
   1778     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
   1779     if (tInfo->currentContext) {
   1780         if (tInfo->currentContext->majorVersion  > 1) {
   1781             if (!hostCon->gl2Encoder()->isInitialized()) {
   1782                 s_display.gles2_iface()->init();
   1783                 hostCon->gl2Encoder()->setInitialized();
   1784                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
   1785             }
   1786             const char* exts = getGLString(GL_EXTENSIONS);
   1787             if (exts) {
   1788                 hostCon->gl2Encoder()->setExtensions(exts, getExtStringArray());
   1789             }
   1790         }
   1791         else {
   1792             if (!hostCon->glEncoder()->isInitialized()) {
   1793                 s_display.gles_iface()->init();
   1794                 hostCon->glEncoder()->setInitialized();
   1795                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
   1796             }
   1797         }
   1798     }
   1799 
   1800     return EGL_TRUE;
   1801 }
   1802 
   1803 EGLContext eglGetCurrentContext()
   1804 {
   1805     return getEGLThreadInfo()->currentContext;
   1806 }
   1807 
   1808 EGLSurface eglGetCurrentSurface(EGLint readdraw)
   1809 {
   1810     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1811     if (!context)
   1812         return EGL_NO_SURFACE; //not an error
   1813 
   1814     switch (readdraw) {
   1815         case EGL_READ:
   1816             return context->read;
   1817         case EGL_DRAW:
   1818             return context->draw;
   1819         default:
   1820             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1821     }
   1822 }
   1823 
   1824 EGLDisplay eglGetCurrentDisplay()
   1825 {
   1826     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1827     if (!context)
   1828         return EGL_NO_DISPLAY; //not an error
   1829 
   1830     return context->dpy;
   1831 }
   1832 
   1833 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
   1834 {
   1835     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1836     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
   1837 
   1838     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
   1839 
   1840     EGLBoolean ret = EGL_TRUE;
   1841     switch (attribute) {
   1842         case EGL_CONFIG_ID:
   1843             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
   1844             break;
   1845         case EGL_CONTEXT_CLIENT_TYPE:
   1846             *value = EGL_OPENGL_ES_API;
   1847             break;
   1848         case EGL_CONTEXT_CLIENT_VERSION:
   1849             *value = context->majorVersion;
   1850             break;
   1851         case EGL_RENDER_BUFFER:
   1852             if (!context->draw)
   1853                 *value = EGL_NONE;
   1854             else
   1855                 *value = EGL_BACK_BUFFER; //single buffer not supported
   1856             break;
   1857         default:
   1858             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
   1859             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1860             break;
   1861     }
   1862 
   1863     return ret;
   1864 }
   1865 
   1866 EGLBoolean eglWaitGL()
   1867 {
   1868     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1869     if (!tInfo || !tInfo->currentContext) {
   1870         return EGL_FALSE;
   1871     }
   1872 
   1873     if (tInfo->currentContext->majorVersion > 1) {
   1874         s_display.gles2_iface()->finish();
   1875     }
   1876     else {
   1877         s_display.gles_iface()->finish();
   1878     }
   1879 
   1880     return EGL_TRUE;
   1881 }
   1882 
   1883 EGLBoolean eglWaitNative(EGLint engine)
   1884 {
   1885     (void)engine;
   1886     return EGL_TRUE;
   1887 }
   1888 
   1889 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
   1890 {
   1891     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1892     if (eglSurface == EGL_NO_SURFACE)
   1893         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1894 
   1895     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1896 
   1897     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
   1898     if (d->dpy != dpy)
   1899         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
   1900 
   1901     // post the surface
   1902     EGLBoolean ret = d->swapBuffers();
   1903 
   1904     hostCon->flush();
   1905     return ret;
   1906 }
   1907 
   1908 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
   1909 {
   1910     //TODO :later
   1911     (void)dpy;
   1912     (void)surface;
   1913     (void)target;
   1914     return 0;
   1915 }
   1916 
   1917 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
   1918 {
   1919     //TODO later
   1920     (void)display;
   1921     (void)surface;
   1922     (void)attrib_list;
   1923     return 0;
   1924 }
   1925 
   1926 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
   1927 {
   1928     //TODO later
   1929     (void)display;
   1930     (void)surface;
   1931     return 0;
   1932 }
   1933 
   1934 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
   1935 {
   1936     (void)attrib_list;
   1937 
   1938     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
   1939 
   1940     if (target == EGL_NATIVE_BUFFER_ANDROID) {
   1941         if (ctx != EGL_NO_CONTEXT) {
   1942             setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   1943         }
   1944 
   1945         android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
   1946 
   1947         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   1948             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1949 
   1950         if (native_buffer->common.version != sizeof(android_native_buffer_t))
   1951             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1952 
   1953         cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
   1954 
   1955         switch (cb->format) {
   1956             case HAL_PIXEL_FORMAT_RGBA_8888:
   1957             case HAL_PIXEL_FORMAT_RGBX_8888:
   1958             case HAL_PIXEL_FORMAT_RGB_888:
   1959             case HAL_PIXEL_FORMAT_RGB_565:
   1960             case HAL_PIXEL_FORMAT_YV12:
   1961             case HAL_PIXEL_FORMAT_BGRA_8888:
   1962             case HAL_PIXEL_FORMAT_RGBA_FP16:
   1963             case HAL_PIXEL_FORMAT_RGBA_1010102:
   1964                 break;
   1965             default:
   1966                 setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1967         }
   1968 
   1969         native_buffer->common.incRef(&native_buffer->common);
   1970 
   1971         EGLImage_t *image = new EGLImage_t();
   1972         image->dpy = dpy;
   1973         image->target = target;
   1974         image->native_buffer = native_buffer;
   1975 
   1976         return (EGLImageKHR)image;
   1977     }
   1978     else if (target == EGL_GL_TEXTURE_2D_KHR) {
   1979         VALIDATE_CONTEXT_RETURN(ctx, EGL_NO_IMAGE_KHR);
   1980 
   1981         EGLContext_t *context = static_cast<EGLContext_t*>(ctx);
   1982         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_IMAGE_KHR);
   1983 
   1984         uint32_t ctxHandle = (context) ? context->rcContext : 0;
   1985         GLuint texture = (GLuint)reinterpret_cast<uintptr_t>(buffer);
   1986         uint32_t img = rcEnc->rcCreateClientImage(rcEnc, ctxHandle, target, texture);
   1987         EGLImage_t *image = new EGLImage_t();
   1988         image->dpy = dpy;
   1989         image->target = target;
   1990         image->host_egl_image = img;
   1991 
   1992         return (EGLImageKHR)image;
   1993     }
   1994 
   1995     setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1996 }
   1997 
   1998 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
   1999 {
   2000     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   2001     EGLImage_t *image = (EGLImage_t*)img;
   2002 
   2003     if (!image || image->dpy != dpy) {
   2004         RETURN_ERROR(EGL_FALSE, EGL_BAD_PARAMETER);
   2005     }
   2006 
   2007     if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
   2008         android_native_buffer_t* native_buffer = image->native_buffer;
   2009 
   2010         if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   2011             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   2012 
   2013         if (native_buffer->common.version != sizeof(android_native_buffer_t))
   2014             setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   2015 
   2016         native_buffer->common.decRef(&native_buffer->common);
   2017         delete image;
   2018 
   2019         return EGL_TRUE;
   2020     }
   2021     else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
   2022         uint32_t host_egl_image = image->host_egl_image;
   2023         delete image;
   2024         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   2025         return rcEnc->rcDestroyClientImage(rcEnc, host_egl_image);
   2026     }
   2027 
   2028     setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   2029 }
   2030 
   2031 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
   2032 #define MAX_EGL_SYNC_ATTRIBS 10
   2033 
   2034 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
   2035         const EGLint *attrib_list)
   2036 {
   2037     VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
   2038     DPRINT("type for eglCreateSyncKHR: 0x%x", type);
   2039 
   2040     DEFINE_HOST_CONNECTION;
   2041 
   2042     if ((type != EGL_SYNC_FENCE_KHR &&
   2043          type != EGL_SYNC_NATIVE_FENCE_ANDROID) ||
   2044         (type != EGL_SYNC_FENCE_KHR &&
   2045          !rcEnc->hasNativeSync())) {
   2046         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
   2047     }
   2048 
   2049     EGLThreadInfo *tInfo = getEGLThreadInfo();
   2050     if (!tInfo || !tInfo->currentContext) {
   2051         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   2052     }
   2053 
   2054     int num_actual_attribs = 0;
   2055 
   2056     // If attrib_list is not NULL,
   2057     // ensure attrib_list contains (key, value) pairs
   2058     // followed by a single EGL_NONE.
   2059     // Also validate attribs.
   2060     int inputFenceFd = -1;
   2061     if (attrib_list) {
   2062         for (int i = 0; i < MAX_EGL_SYNC_ATTRIBS; i += 2) {
   2063             if (attrib_list[i] == EGL_NONE) {
   2064                 num_actual_attribs = i;
   2065                 break;
   2066             }
   2067             if (i + 1 == MAX_EGL_SYNC_ATTRIBS) {
   2068                 DPRINT("ERROR: attrib list without EGL_NONE");
   2069                 setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
   2070             }
   2071         }
   2072 
   2073         // Validate and input attribs
   2074         for (int i = 0; i < num_actual_attribs; i += 2) {
   2075             if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
   2076                 DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
   2077             }
   2078             if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
   2079                 DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
   2080             }
   2081             if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
   2082                 DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
   2083             }
   2084             EGLint attrib_key = attrib_list[i];
   2085             EGLint attrib_val = attrib_list[i + 1];
   2086             if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
   2087                 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
   2088                     inputFenceFd = attrib_val;
   2089                 }
   2090             }
   2091             DPRINT("attrib: 0x%x : 0x%x", attrib_key, attrib_val);
   2092         }
   2093     }
   2094 
   2095     uint64_t sync_handle = 0;
   2096     int newFenceFd = -1;
   2097 
   2098     if (rcEnc->hasNativeSync()) {
   2099         sync_handle =
   2100             createNativeSync(type, attrib_list, num_actual_attribs,
   2101                              false /* don't destroy when signaled on the host;
   2102                                       let the guest clean this up,
   2103                                       because the guest called eglCreateSyncKHR. */,
   2104                              inputFenceFd,
   2105                              &newFenceFd);
   2106 
   2107     } else {
   2108         // Just trigger a glFinish if the native sync on host
   2109         // is unavailable.
   2110         eglWaitClient();
   2111     }
   2112 
   2113     EGLSync_t* syncRes = new EGLSync_t(sync_handle);
   2114 
   2115     if (type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
   2116         syncRes->type = EGL_SYNC_NATIVE_FENCE_ANDROID;
   2117 
   2118         if (inputFenceFd < 0) {
   2119             syncRes->android_native_fence_fd = newFenceFd;
   2120         } else {
   2121             DPRINT("has input fence fd %d",
   2122                     inputFenceFd);
   2123             syncRes->android_native_fence_fd = inputFenceFd;
   2124         }
   2125     } else {
   2126         syncRes->type = EGL_SYNC_FENCE_KHR;
   2127         syncRes->android_native_fence_fd = -1;
   2128         if (!rcEnc->hasNativeSync()) {
   2129             syncRes->status = EGL_SIGNALED_KHR;
   2130         }
   2131     }
   2132 
   2133     return (EGLSyncKHR)syncRes;
   2134 }
   2135 
   2136 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync)
   2137 {
   2138     (void)dpy;
   2139 
   2140     if (!eglsync) {
   2141         DPRINT("WARNING: null sync object")
   2142         return EGL_TRUE;
   2143     }
   2144 
   2145     EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
   2146 
   2147     if (sync && sync->android_native_fence_fd > 0) {
   2148         close(sync->android_native_fence_fd);
   2149         sync->android_native_fence_fd = -1;
   2150     }
   2151 
   2152     if (sync) {
   2153         DEFINE_HOST_CONNECTION;
   2154         if (rcEnc->hasNativeSync()) {
   2155             rcEnc->rcDestroySyncKHR(rcEnc, sync->handle);
   2156         }
   2157         delete sync;
   2158     }
   2159 
   2160     return EGL_TRUE;
   2161 }
   2162 
   2163 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags,
   2164         EGLTimeKHR timeout)
   2165 {
   2166     (void)dpy;
   2167 
   2168     if (!eglsync) {
   2169         DPRINT("WARNING: null sync object");
   2170         return EGL_CONDITION_SATISFIED_KHR;
   2171     }
   2172 
   2173     EGLSync_t* sync = (EGLSync_t*)eglsync;
   2174 
   2175     DPRINT("sync=0x%lx (handle=0x%lx) flags=0x%x timeout=0x%llx",
   2176            sync, sync->handle, flags, timeout);
   2177 
   2178     DEFINE_HOST_CONNECTION;
   2179 
   2180     EGLint retval;
   2181     if (rcEnc->hasNativeSync()) {
   2182         retval = rcEnc->rcClientWaitSyncKHR
   2183             (rcEnc, sync->handle, flags, timeout);
   2184     } else {
   2185         retval = EGL_CONDITION_SATISFIED_KHR;
   2186     }
   2187     EGLint res_status;
   2188     switch (sync->type) {
   2189         case EGL_SYNC_FENCE_KHR:
   2190             res_status = EGL_SIGNALED_KHR;
   2191             break;
   2192         case EGL_SYNC_NATIVE_FENCE_ANDROID:
   2193             res_status = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
   2194             break;
   2195         default:
   2196             res_status = EGL_SIGNALED_KHR;
   2197     }
   2198     sync->status = res_status;
   2199     return retval;
   2200 }
   2201 
   2202 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR eglsync,
   2203         EGLint attribute, EGLint *value)
   2204 {
   2205     (void)dpy;
   2206 
   2207     EGLSync_t* sync = (EGLSync_t*)eglsync;
   2208 
   2209     switch (attribute) {
   2210     case EGL_SYNC_TYPE_KHR:
   2211         *value = sync->type;
   2212         return EGL_TRUE;
   2213     case EGL_SYNC_STATUS_KHR:
   2214         *value = sync->status;
   2215         return EGL_TRUE;
   2216     case EGL_SYNC_CONDITION_KHR:
   2217         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
   2218         return EGL_TRUE;
   2219     default:
   2220         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   2221     }
   2222 }
   2223 
   2224 int eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR eglsync) {
   2225     (void)dpy;
   2226 
   2227     DPRINT("call");
   2228 
   2229     EGLSync_t* sync = (EGLSync_t*)eglsync;
   2230     if (sync && sync->android_native_fence_fd > 0) {
   2231         int res = dup(sync->android_native_fence_fd);
   2232         return res;
   2233     } else {
   2234         return -1;
   2235     }
   2236 }
   2237 
   2238 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {
   2239     (void)dpy;
   2240 
   2241     if (!eglsync) {
   2242         ALOGE("%s: null sync object!", __FUNCTION__);
   2243         return EGL_FALSE;
   2244     }
   2245 
   2246     if (flags) {
   2247         ALOGE("%s: flags must be 0, got 0x%x", __FUNCTION__, flags);
   2248         return EGL_FALSE;
   2249     }
   2250 
   2251     DEFINE_HOST_CONNECTION;
   2252     if (rcEnc->hasNativeSyncV3()) {
   2253         EGLSync_t* sync = (EGLSync_t*)eglsync;
   2254         rcEnc->rcWaitSyncKHR(rcEnc, sync->handle, flags);
   2255     }
   2256 
   2257     return EGL_TRUE;
   2258 }
   2259