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