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 "HostConnection.h"
     18 #include "ThreadInfo.h"
     19 #include "eglDisplay.h"
     20 #include "egl_ftable.h"
     21 #include <cutils/log.h>
     22 #include "gralloc_cb.h"
     23 #include "GLClientState.h"
     24 #include "GLSharedGroup.h"
     25 #include "eglContext.h"
     26 #include "ClientAPIExts.h"
     27 
     28 #include "GLEncoder.h"
     29 #ifdef WITH_GLES2
     30 #include "GL2Encoder.h"
     31 #endif
     32 
     33 #include <system/window.h>
     34 
     35 template<typename T>
     36 static T setErrorFunc(GLint error, T returnValue) {
     37     getEGLThreadInfo()->eglError = error;
     38     return returnValue;
     39 }
     40 
     41 const char *  eglStrError(EGLint err)
     42 {
     43     switch (err){
     44         case EGL_SUCCESS:           return "EGL_SUCCESS";
     45         case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
     46         case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
     47         case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
     48         case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
     49         case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
     50         case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
     51         case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
     52         case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
     53         case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
     54         case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
     55         case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
     56         case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
     57         case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
     58         case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
     59         default: return "UNKNOWN";
     60     }
     61 }
     62 
     63 #define LOG_EGL_ERRORS 1
     64 
     65 #ifdef LOG_EGL_ERRORS
     66 
     67 #define setErrorReturn(error, retVal)     \
     68     {                                                \
     69         ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
     70         return setErrorFunc(error, retVal);            \
     71     }
     72 
     73 #define RETURN_ERROR(ret,err)           \
     74     ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
     75     getEGLThreadInfo()->eglError = err;    \
     76     return ret;
     77 
     78 #else //!LOG_EGL_ERRORS
     79 
     80 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
     81 
     82 #define RETURN_ERROR(ret,err)           \
     83     getEGLThreadInfo()->eglError = err; \
     84     return ret;
     85 
     86 #endif //LOG_EGL_ERRORS
     87 
     88 #define VALIDATE_CONFIG(cfg,ret) \
     89     if(((int)cfg<0)||((int)cfg>s_display.getNumConfigs())) { \
     90         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
     91     }
     92 
     93 #define VALIDATE_DISPLAY(dpy,ret) \
     94     if ((dpy) != (EGLDisplay)&s_display) { \
     95         RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
     96     }
     97 
     98 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
     99     VALIDATE_DISPLAY(dpy, ret)    \
    100     if (!s_display.initialized()) {        \
    101         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
    102     }
    103 
    104 #define DEFINE_HOST_CONNECTION \
    105     HostConnection *hostCon = HostConnection::get(); \
    106     renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
    107 
    108 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
    109     HostConnection *hostCon = HostConnection::get(); \
    110     if (!hostCon) { \
    111         ALOGE("egl: Failed to get host connection\n"); \
    112         return ret; \
    113     } \
    114     renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
    115     if (!rcEnc) { \
    116         ALOGE("egl: Failed to get renderControl encoder context\n"); \
    117         return ret; \
    118     }
    119 
    120 #define VALIDATE_CONTEXT_RETURN(context,ret)        \
    121     if (!context) {                                    \
    122         RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
    123     }
    124 
    125 #define VALIDATE_SURFACE_RETURN(surface, ret)    \
    126     if (surface != EGL_NO_SURFACE) {    \
    127         egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
    128         if (s->dpy != (EGLDisplay)&s_display)    \
    129             setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
    130     }
    131 
    132 
    133 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
    134     dpy(dpy),
    135     config(config),
    136     read(EGL_NO_SURFACE),
    137     draw(EGL_NO_SURFACE),
    138     shareCtx(shareCtx),
    139     rcContext(0),
    140     versionString(NULL),
    141     vendorString(NULL),
    142     rendererString(NULL),
    143     extensionString(NULL)
    144 {
    145     flags = 0;
    146     version = 1;
    147     clientState = new GLClientState();
    148     if (shareCtx)
    149         sharedGroup = shareCtx->getSharedGroup();
    150     else
    151         sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
    152 };
    153 
    154 EGLContext_t::~EGLContext_t()
    155 {
    156     delete clientState;
    157     delete [] versionString;
    158     delete [] vendorString;
    159     delete [] rendererString;
    160     delete [] extensionString;
    161 }
    162 
    163 // ----------------------------------------------------------------------------
    164 //egl_surface_t
    165 
    166 //we don't need to handle depth since it's handled when window created on the host
    167 
    168 struct egl_surface_t {
    169 
    170     EGLDisplay          dpy;
    171     EGLConfig           config;
    172 
    173 
    174     egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
    175     virtual     ~egl_surface_t();
    176 
    177     virtual     void        setSwapInterval(int interval) = 0;
    178     virtual     EGLBoolean  swapBuffers() = 0;
    179 
    180     EGLint      getSwapBehavior() const;
    181     uint32_t    getRcSurface()   { return rcSurface; }
    182     EGLint      getSurfaceType() { return surfaceType; }
    183 
    184     EGLint      getWidth(){ return width; }
    185     EGLint      getHeight(){ return height; }
    186     void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
    187     EGLint      getTextureFormat() { return texFormat; }
    188     void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
    189     EGLint      getTextureTarget() { return texTarget; }
    190 
    191 private:
    192     //
    193     //Surface attributes
    194     //
    195     EGLint      width;
    196     EGLint      height;
    197     EGLint      texFormat;
    198     EGLint      texTarget;
    199 
    200 protected:
    201     void        setWidth(EGLint w)  { width = w;  }
    202     void        setHeight(EGLint h) { height = h; }
    203 
    204     EGLint      surfaceType;
    205     uint32_t    rcSurface; //handle to surface created via remote control
    206 };
    207 
    208 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
    209     : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
    210 {
    211     width = 0;
    212     height = 0;
    213     texFormat = EGL_NO_TEXTURE;
    214     texTarget = EGL_NO_TEXTURE;
    215 }
    216 
    217 EGLint egl_surface_t::getSwapBehavior() const {
    218     return EGL_BUFFER_PRESERVED;
    219 }
    220 
    221 egl_surface_t::~egl_surface_t()
    222 {
    223 }
    224 
    225 // ----------------------------------------------------------------------------
    226 // egl_window_surface_t
    227 
    228 struct egl_window_surface_t : public egl_surface_t {
    229     static egl_window_surface_t* create(
    230             EGLDisplay dpy, EGLConfig config, EGLint surfType,
    231             ANativeWindow* window);
    232 
    233     virtual ~egl_window_surface_t();
    234 
    235     virtual void       setSwapInterval(int interval);
    236     virtual EGLBoolean swapBuffers();
    237 
    238 private:
    239     egl_window_surface_t(
    240             EGLDisplay dpy, EGLConfig config, EGLint surfType,
    241             ANativeWindow* window);
    242     EGLBoolean init();
    243 
    244     ANativeWindow*              nativeWindow;
    245     android_native_buffer_t*    buffer;
    246 };
    247 
    248 egl_window_surface_t::egl_window_surface_t (
    249         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    250         ANativeWindow* window)
    251 :   egl_surface_t(dpy, config, surfType),
    252     nativeWindow(window),
    253     buffer(NULL)
    254 {
    255     // keep a reference on the window
    256     nativeWindow->common.incRef(&nativeWindow->common);
    257     EGLint w,h;
    258     nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w);
    259     setWidth(w);
    260     nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h);
    261     setHeight(h);
    262 }
    263 
    264 EGLBoolean egl_window_surface_t::init()
    265 {
    266     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
    267         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    268     }
    269     nativeWindow->lockBuffer(nativeWindow, buffer);
    270 
    271     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    272     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
    273             getWidth(), getHeight());
    274     if (!rcSurface) {
    275         ALOGE("rcCreateWindowSurface returned 0");
    276         return EGL_FALSE;
    277     }
    278     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    279             ((cb_handle_t*)(buffer->handle))->hostHandle);
    280 
    281     return EGL_TRUE;
    282 }
    283 
    284 egl_window_surface_t* egl_window_surface_t::create(
    285         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    286         ANativeWindow* window)
    287 {
    288     egl_window_surface_t* wnd = new egl_window_surface_t(
    289             dpy, config, surfType, window);
    290     if (wnd && !wnd->init()) {
    291         delete wnd;
    292         wnd = NULL;
    293     }
    294     return wnd;
    295 }
    296 
    297 egl_window_surface_t::~egl_window_surface_t() {
    298     DEFINE_HOST_CONNECTION;
    299     if (rcSurface && rcEnc) {
    300         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    301     }
    302     if (buffer) {
    303         nativeWindow->cancelBuffer(nativeWindow, buffer);
    304     }
    305     nativeWindow->common.decRef(&nativeWindow->common);
    306 }
    307 
    308 void egl_window_surface_t::setSwapInterval(int interval)
    309 {
    310     nativeWindow->setSwapInterval(nativeWindow, interval);
    311 }
    312 
    313 EGLBoolean egl_window_surface_t::swapBuffers()
    314 {
    315     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    316 
    317     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
    318 
    319     nativeWindow->queueBuffer(nativeWindow, buffer);
    320     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) {
    321         buffer = NULL;
    322         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    323     }
    324     nativeWindow->lockBuffer(nativeWindow, buffer);
    325 
    326     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    327             ((cb_handle_t *)(buffer->handle))->hostHandle);
    328 
    329     return EGL_TRUE;
    330 }
    331 
    332 // ----------------------------------------------------------------------------
    333 //egl_pbuffer_surface_t
    334 
    335 struct egl_pbuffer_surface_t : public egl_surface_t {
    336     static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
    337             EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
    338 
    339     virtual ~egl_pbuffer_surface_t();
    340 
    341     virtual void       setSwapInterval(int interval) {}
    342     virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
    343 
    344     uint32_t getRcColorBuffer() { return rcColorBuffer; }
    345 
    346 private:
    347     egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
    348             int32_t w, int32_t h);
    349     EGLBoolean init(GLenum format);
    350 
    351     uint32_t rcColorBuffer;
    352 };
    353 
    354 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
    355         EGLint surfType, int32_t w, int32_t h)
    356 :   egl_surface_t(dpy, config, surfType),
    357     rcColorBuffer(0)
    358 {
    359     setWidth(w);
    360     setHeight(h);
    361 }
    362 
    363 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
    364 {
    365     DEFINE_HOST_CONNECTION;
    366     if (rcEnc) {
    367         if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
    368         if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    369     }
    370 }
    371 
    372 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
    373 {
    374     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    375 
    376     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
    377             getWidth(), getHeight());
    378     if (!rcSurface) {
    379         ALOGE("rcCreateWindowSurface returned 0");
    380         return EGL_FALSE;
    381     }
    382 
    383     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
    384             pixelFormat);
    385     if (!rcColorBuffer) {
    386         ALOGE("rcCreateColorBuffer returned 0");
    387         return EGL_FALSE;
    388     }
    389 
    390     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
    391 
    392     return EGL_TRUE;
    393 }
    394 
    395 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
    396         EGLConfig config, EGLint surfType, int32_t w, int32_t h,
    397         GLenum pixelFormat)
    398 {
    399     egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
    400             w, h);
    401     if (pb && !pb->init(pixelFormat)) {
    402         delete pb;
    403         pb = NULL;
    404     }
    405     return pb;
    406 }
    407 
    408 static const char *getGLString(int glEnum)
    409 {
    410     EGLThreadInfo *tInfo = getEGLThreadInfo();
    411     if (!tInfo || !tInfo->currentContext) {
    412         return NULL;
    413     }
    414 
    415     const char** strPtr = NULL;
    416 
    417 #define GL_VENDOR                         0x1F00
    418 #define GL_RENDERER                       0x1F01
    419 #define GL_VERSION                        0x1F02
    420 #define GL_EXTENSIONS                     0x1F03
    421 
    422     switch(glEnum) {
    423         case GL_VERSION:
    424             strPtr = &tInfo->currentContext->versionString;
    425             break;
    426         case GL_VENDOR:
    427             strPtr = &tInfo->currentContext->vendorString;
    428             break;
    429         case GL_RENDERER:
    430             strPtr = &tInfo->currentContext->rendererString;
    431             break;
    432         case GL_EXTENSIONS:
    433             strPtr = &tInfo->currentContext->extensionString;
    434             break;
    435     }
    436 
    437     if (!strPtr) {
    438         return NULL;
    439     }
    440 
    441     if (*strPtr != NULL) {
    442         //
    443         // string is already cached
    444         //
    445         return *strPtr;
    446     }
    447 
    448     //
    449     // first query of that string - need to query host
    450     //
    451     DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
    452     char *hostStr = NULL;
    453     int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
    454     if (n < 0) {
    455         hostStr = new char[-n+1];
    456         n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
    457         if (n <= 0) {
    458             delete [] hostStr;
    459             hostStr = NULL;
    460         }
    461     }
    462 
    463     //
    464     // keep the string in the context and return its value
    465     //
    466     *strPtr = hostStr;
    467     return hostStr;
    468 }
    469 
    470 // ----------------------------------------------------------------------------
    471 
    472 // The one and only supported display object.
    473 static eglDisplay s_display;
    474 
    475 static EGLClient_eglInterface s_eglIface = {
    476     getThreadInfo: getEGLThreadInfo,
    477     getGLString: getGLString
    478 };
    479 
    480 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
    481 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
    482 {
    483     //
    484     // we support only EGL_DEFAULT_DISPLAY.
    485     //
    486     if (display_id != EGL_DEFAULT_DISPLAY) {
    487         return EGL_NO_DISPLAY;
    488     }
    489 
    490     return (EGLDisplay)&s_display;
    491 }
    492 
    493 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
    494 {
    495     VALIDATE_DISPLAY(dpy,EGL_FALSE);
    496 
    497     if (!s_display.initialize(&s_eglIface)) {
    498         return EGL_FALSE;
    499     }
    500     if (major!=NULL)
    501         *major = s_display.getVersionMajor();
    502     if (minor!=NULL)
    503         *minor = s_display.getVersionMinor();
    504     return EGL_TRUE;
    505 }
    506 
    507 EGLBoolean eglTerminate(EGLDisplay dpy)
    508 {
    509     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    510 
    511     s_display.terminate();
    512     return EGL_TRUE;
    513 }
    514 
    515 EGLint eglGetError()
    516 {
    517     EGLint error = getEGLThreadInfo()->eglError;
    518     getEGLThreadInfo()->eglError = EGL_SUCCESS;
    519     return error;
    520 }
    521 
    522 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
    523 {
    524     // search in EGL function table
    525     for (int i=0; i<egl_num_funcs; i++) {
    526         if (!strcmp(egl_funcs_by_name[i].name, procname)) {
    527             return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
    528         }
    529     }
    530 
    531     //
    532     // Make sure display is initialized before searching in client APIs
    533     //
    534     if (!s_display.initialized()) {
    535         if (!s_display.initialize(&s_eglIface)) {
    536             return NULL;
    537         }
    538     }
    539 
    540     // look in gles client api's extensions table
    541     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
    542 
    543     // Fail - function not found.
    544     return NULL;
    545 }
    546 
    547 const char* eglQueryString(EGLDisplay dpy, EGLint name)
    548 {
    549     VALIDATE_DISPLAY_INIT(dpy, NULL);
    550 
    551     return s_display.queryString(name);
    552 }
    553 
    554 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    555 {
    556     VALIDATE_DISPLAY_INIT(dpy, NULL);
    557 
    558     if(!num_config) {
    559         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
    560     }
    561 
    562     GLint numConfigs = s_display.getNumConfigs();
    563     if (!configs) {
    564         *num_config = numConfigs;
    565         return EGL_TRUE;
    566     }
    567 
    568     int i=0;
    569     for (i=0 ; i<numConfigs && i<config_size ; i++) {
    570         *configs++ = (EGLConfig)i;
    571     }
    572     *num_config = i;
    573     return EGL_TRUE;
    574 }
    575 
    576 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    577 {
    578     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    579 
    580     int attribs_size = 0;
    581     if (attrib_list) {
    582         const EGLint * attrib_p = attrib_list;
    583         while (attrib_p[0] != EGL_NONE) {
    584             attribs_size += 2;
    585             attrib_p += 2;
    586         }
    587         attribs_size++; //for the terminating EGL_NONE
    588     }
    589 
    590     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    591     *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)configs, config_size);
    592 
    593     return EGL_TRUE;
    594 }
    595 
    596 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
    597 {
    598     VALIDATE_DISPLAY_INIT(dpy, NULL);
    599     VALIDATE_CONFIG(config, EGL_FALSE);
    600 
    601     if (s_display.getConfigAttrib(config, attribute, value))
    602     {
    603         return EGL_TRUE;
    604     }
    605     else
    606     {
    607         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
    608     }
    609 }
    610 
    611 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
    612 {
    613     VALIDATE_DISPLAY_INIT(dpy, NULL);
    614     VALIDATE_CONFIG(config, EGL_FALSE);
    615     if (win == 0) {
    616         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    617     }
    618 
    619     EGLint surfaceType;
    620     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
    621 
    622     if (!(surfaceType & EGL_WINDOW_BIT)) {
    623         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    624     }
    625 
    626     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
    627         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    628     }
    629 
    630     egl_surface_t* surface = egl_window_surface_t::create(
    631             &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
    632     if (!surface) {
    633         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    634     }
    635 
    636     return surface;
    637 }
    638 
    639 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
    640 {
    641     VALIDATE_DISPLAY_INIT(dpy, NULL);
    642     VALIDATE_CONFIG(config, EGL_FALSE);
    643 
    644     EGLint surfaceType;
    645     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
    646 
    647     if (!(surfaceType & EGL_PBUFFER_BIT)) {
    648         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    649     }
    650 
    651     int32_t w = 0;
    652     int32_t h = 0;
    653     EGLint texFormat = EGL_NO_TEXTURE;
    654     EGLint texTarget = EGL_NO_TEXTURE;
    655     while (attrib_list[0]) {
    656         switch (attrib_list[0]) {
    657             case EGL_WIDTH:
    658                 w = attrib_list[1];
    659                 break;
    660             case EGL_HEIGHT:
    661                 h = attrib_list[1];
    662                 break;
    663             case EGL_TEXTURE_FORMAT:
    664                 texFormat = attrib_list[1];
    665                 break;
    666             case EGL_TEXTURE_TARGET:
    667                 texTarget = attrib_list[1];
    668                 break;
    669             default:
    670                 break;
    671         };
    672         attrib_list+=2;
    673     }
    674     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
    675         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
    676         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    677     }
    678     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
    679 
    680     GLenum pixelFormat;
    681     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
    682         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    683 
    684     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
    685             surfaceType, w, h, pixelFormat);
    686     if (!surface) {
    687         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    688     }
    689 
    690     //setup attributes
    691     surface->setTextureFormat(texFormat);
    692     surface->setTextureTarget(texTarget);
    693 
    694     return surface;
    695 }
    696 
    697 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
    698 {
    699     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
    700     //     located on host. In order to support Pixmaps we should either punt
    701     //     to s/w rendering -or- let the host render to a buffer that will be
    702     //     copied back to guest at some sync point. None of those methods not
    703     //     implemented and pixmaps are not used with OpenGL anyway ...
    704     return EGL_NO_SURFACE;
    705 }
    706 
    707 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
    708 {
    709     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    710     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    711 
    712     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
    713     delete surface;
    714 
    715     return EGL_TRUE;
    716 }
    717 
    718 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
    719 {
    720     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    721     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    722 
    723     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
    724     EGLBoolean ret = EGL_TRUE;
    725     switch (attribute) {
    726         case EGL_CONFIG_ID:
    727             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
    728             break;
    729         case EGL_WIDTH:
    730             *value = surface->getWidth();
    731             break;
    732         case EGL_HEIGHT:
    733             *value = surface->getHeight();
    734             break;
    735         case EGL_TEXTURE_FORMAT:
    736             *value = surface->getTextureFormat();
    737             break;
    738         case EGL_TEXTURE_TARGET:
    739             *value = surface->getTextureTarget();
    740             break;
    741         case EGL_SWAP_BEHAVIOR:
    742             *value = surface->getSwapBehavior();
    743             break;
    744         case EGL_LARGEST_PBUFFER:
    745             // not modified for a window or pixmap surface
    746             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
    747             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
    748             break;
    749         //TODO: complete other attributes
    750         default:
    751             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
    752             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    753             break;
    754     }
    755 
    756     return ret;
    757 }
    758 
    759 EGLBoolean eglBindAPI(EGLenum api)
    760 {
    761     if (api != EGL_OPENGL_ES_API)
    762         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    763     return EGL_TRUE;
    764 }
    765 
    766 EGLenum eglQueryAPI()
    767 {
    768     return EGL_OPENGL_ES_API;
    769 }
    770 
    771 EGLBoolean eglWaitClient()
    772 {
    773     return eglWaitGL();
    774 }
    775 
    776 EGLBoolean eglReleaseThread()
    777 {
    778     EGLThreadInfo *tInfo = getEGLThreadInfo();
    779     if (tInfo && tInfo->currentContext) {
    780         return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
    781     }
    782     return EGL_TRUE;
    783 }
    784 
    785 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
    786 {
    787     //TODO
    788     ALOGW("%s not implemented", __FUNCTION__);
    789     return 0;
    790 }
    791 
    792 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
    793 {
    794     //TODO
    795     ALOGW("%s not implemented", __FUNCTION__);
    796     return 0;
    797 }
    798 
    799 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
    800 {
    801     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    802     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    803     if (eglSurface == EGL_NO_SURFACE) {
    804         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    805     }
    806 
    807     if (buffer != EGL_BACK_BUFFER) {
    808         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    809     }
    810 
    811     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
    812 
    813     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
    814         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    815     }
    816 
    817     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
    818         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    819     }
    820 
    821     //It's now safe to cast to pbuffer surface
    822     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
    823 
    824     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    825     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
    826 
    827     return GL_TRUE;
    828 }
    829 
    830 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    831 {
    832     //TODO
    833     ALOGW("%s not implemented", __FUNCTION__);
    834     return 0;
    835 }
    836 
    837 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
    838 {
    839     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    840     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    841 
    842     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
    843     if (!ctx) {
    844         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
    845     }
    846     if (!ctx->draw) {
    847         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    848     }
    849     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
    850     draw->setSwapInterval(interval);
    851 
    852     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
    853 
    854     return EGL_TRUE;
    855 }
    856 
    857 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
    858 {
    859     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
    860     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
    861 
    862     EGLint version = 1; //default
    863     while (attrib_list && attrib_list[0]) {
    864         if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
    865         attrib_list+=2;
    866     }
    867 
    868     uint32_t rcShareCtx = 0;
    869     EGLContext_t * shareCtx = NULL;
    870     if (share_context) {
    871         shareCtx = static_cast<EGLContext_t*>(share_context);
    872         rcShareCtx = shareCtx->rcContext;
    873         if (shareCtx->dpy != dpy)
    874             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
    875     }
    876 
    877     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
    878     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uint32_t)config, rcShareCtx, version);
    879     if (!rcContext) {
    880         ALOGE("rcCreateContext returned 0");
    881         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
    882     }
    883 
    884     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
    885     if (!context)
    886         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
    887 
    888     context->version = version;
    889     context->rcContext = rcContext;
    890 
    891 
    892     return context;
    893 }
    894 
    895 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    896 {
    897     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    898     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
    899 
    900     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
    901 
    902     if (getEGLThreadInfo()->currentContext == context)
    903     {
    904         eglMakeCurrent(dpy, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
    905     }
    906 
    907     if (context->rcContext) {
    908         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    909         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
    910         context->rcContext = 0;
    911     }
    912 
    913     delete context;
    914     return EGL_TRUE;
    915 }
    916 
    917 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
    918 {
    919     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    920     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
    921     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
    922 
    923     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
    924         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    925     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
    926         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    927 
    928     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
    929     uint32_t ctxHandle = (context) ? context->rcContext : 0;
    930     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
    931     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
    932     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
    933     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
    934 
    935     //
    936     // Nothing to do if no binding change has made
    937     //
    938     EGLThreadInfo *tInfo = getEGLThreadInfo();
    939     if (tInfo->currentContext == context &&
    940         (context == NULL ||
    941         (context && context->draw == draw && context->read == read))) {
    942         return EGL_TRUE;
    943     }
    944 
    945     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
    946         //context is current to another thread
    947         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
    948     }
    949 
    950     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    951     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
    952         ALOGE("rcMakeCurrent returned EGL_FALSE");
    953         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
    954     }
    955 
    956     //Now make the local bind
    957     if (context) {
    958         context->draw = draw;
    959         context->read = read;
    960         context->flags |= EGLContext_t::IS_CURRENT;
    961         //set the client state
    962         if (context->version == 2) {
    963             hostCon->gl2Encoder()->setClientState(context->getClientState());
    964             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
    965         }
    966         else {
    967             hostCon->glEncoder()->setClientState(context->getClientState());
    968             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
    969         }
    970     }
    971     else {
    972         //release ClientState & SharedGroup
    973         if (tInfo->currentContext->version == 2) {
    974             hostCon->gl2Encoder()->setClientState(NULL);
    975             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
    976         }
    977         else {
    978             hostCon->glEncoder()->setClientState(NULL);
    979             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
    980         }
    981 
    982     }
    983 
    984     if (tInfo->currentContext)
    985         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
    986 
    987     //Now make current
    988     tInfo->currentContext = context;
    989 
    990     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
    991     if (tInfo->currentContext) {
    992         if (tInfo->currentContext->version == 2) {
    993             if (!hostCon->gl2Encoder()->isInitialized()) {
    994                 s_display.gles2_iface()->init();
    995                 hostCon->gl2Encoder()->setInitialized();
    996                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
    997             }
    998         }
    999         else {
   1000             if (!hostCon->glEncoder()->isInitialized()) {
   1001                 s_display.gles_iface()->init();
   1002                 hostCon->glEncoder()->setInitialized();
   1003                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
   1004             }
   1005         }
   1006     }
   1007 
   1008     return EGL_TRUE;
   1009 }
   1010 
   1011 EGLContext eglGetCurrentContext()
   1012 {
   1013     return getEGLThreadInfo()->currentContext;
   1014 }
   1015 
   1016 EGLSurface eglGetCurrentSurface(EGLint readdraw)
   1017 {
   1018     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1019     if (!context)
   1020         return EGL_NO_SURFACE; //not an error
   1021 
   1022     switch (readdraw) {
   1023         case EGL_READ:
   1024             return context->read;
   1025         case EGL_DRAW:
   1026             return context->draw;
   1027         default:
   1028             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1029     }
   1030 }
   1031 
   1032 EGLDisplay eglGetCurrentDisplay()
   1033 {
   1034     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1035     if (!context)
   1036         return EGL_NO_DISPLAY; //not an error
   1037 
   1038     return context->dpy;
   1039 }
   1040 
   1041 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
   1042 {
   1043     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1044     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
   1045 
   1046     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
   1047 
   1048     EGLBoolean ret = EGL_TRUE;
   1049     switch (attribute) {
   1050         case EGL_CONFIG_ID:
   1051             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
   1052             break;
   1053         case EGL_CONTEXT_CLIENT_TYPE:
   1054             *value = EGL_OPENGL_ES_API;
   1055             break;
   1056         case EGL_CONTEXT_CLIENT_VERSION:
   1057             *value = context->version;
   1058             break;
   1059         case EGL_RENDER_BUFFER:
   1060             if (!context->draw)
   1061                 *value = EGL_NONE;
   1062             else
   1063                 *value = EGL_BACK_BUFFER; //single buffer not supported
   1064             break;
   1065         default:
   1066             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
   1067             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1068             break;
   1069     }
   1070 
   1071     return ret;
   1072 }
   1073 
   1074 EGLBoolean eglWaitGL()
   1075 {
   1076     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1077     if (!tInfo || !tInfo->currentContext) {
   1078         return EGL_FALSE;
   1079     }
   1080 
   1081     if (tInfo->currentContext->version == 2) {
   1082         s_display.gles2_iface()->finish();
   1083     }
   1084     else {
   1085         s_display.gles_iface()->finish();
   1086     }
   1087 
   1088     return EGL_TRUE;
   1089 }
   1090 
   1091 EGLBoolean eglWaitNative(EGLint engine)
   1092 {
   1093     return EGL_TRUE;
   1094 }
   1095 
   1096 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
   1097 {
   1098     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1099     if (eglSurface == EGL_NO_SURFACE)
   1100         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1101 
   1102     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1103 
   1104     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
   1105     if (d->dpy != dpy)
   1106         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
   1107 
   1108     // post the surface
   1109     d->swapBuffers();
   1110 
   1111     hostCon->flush();
   1112     return EGL_TRUE;
   1113 }
   1114 
   1115 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
   1116 {
   1117     //TODO :later
   1118     return 0;
   1119 }
   1120 
   1121 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
   1122 {
   1123     //TODO later
   1124     return 0;
   1125 }
   1126 
   1127 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
   1128 {
   1129     //TODO later
   1130     return 0;
   1131 }
   1132 
   1133 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
   1134 {
   1135     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
   1136     if (ctx != EGL_NO_CONTEXT) {
   1137         setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   1138     }
   1139     if (target != EGL_NATIVE_BUFFER_ANDROID) {
   1140         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1141     }
   1142 
   1143     android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
   1144 
   1145     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   1146         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1147 
   1148     if (native_buffer->common.version != sizeof(android_native_buffer_t))
   1149         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1150 
   1151     switch (native_buffer->format) {
   1152         case HAL_PIXEL_FORMAT_RGBA_8888:
   1153         case HAL_PIXEL_FORMAT_RGBX_8888:
   1154         case HAL_PIXEL_FORMAT_RGB_888:
   1155         case HAL_PIXEL_FORMAT_RGB_565:
   1156         case HAL_PIXEL_FORMAT_BGRA_8888:
   1157         case HAL_PIXEL_FORMAT_RGBA_5551:
   1158         case HAL_PIXEL_FORMAT_RGBA_4444:
   1159             break;
   1160         default:
   1161             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1162     }
   1163 
   1164     native_buffer->common.incRef(&native_buffer->common);
   1165     return (EGLImageKHR)native_buffer;
   1166 }
   1167 
   1168 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
   1169 {
   1170     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1171     android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
   1172 
   1173     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   1174         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1175 
   1176     if (native_buffer->common.version != sizeof(android_native_buffer_t))
   1177         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1178 
   1179     native_buffer->common.decRef(&native_buffer->common);
   1180 
   1181     return EGL_TRUE;
   1182 }
   1183 
   1184 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
   1185 
   1186 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
   1187         const EGLint *attrib_list)
   1188 {
   1189     // TODO: This implementation could be faster. We should require the host EGL
   1190     // to support KHR_fence_sync, or at least pipe the fence command to the host
   1191     // and wait for it (probably involving a glFinish on the host) in
   1192     // eglClientWaitSyncKHR.
   1193 
   1194     VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
   1195 
   1196     if (type != EGL_SYNC_FENCE_KHR ||
   1197             (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
   1198         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
   1199     }
   1200 
   1201     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1202     if (!tInfo || !tInfo->currentContext) {
   1203         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   1204     }
   1205 
   1206     if (tInfo->currentContext->version == 2) {
   1207         s_display.gles2_iface()->finish();
   1208     } else {
   1209         s_display.gles_iface()->finish();
   1210     }
   1211 
   1212     return FENCE_SYNC_HANDLE;
   1213 }
   1214 
   1215 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
   1216 {
   1217     if (sync != FENCE_SYNC_HANDLE) {
   1218         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1219     }
   1220 
   1221     return EGL_TRUE;
   1222 }
   1223 
   1224 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
   1225         EGLTimeKHR timeout)
   1226 {
   1227     if (sync != FENCE_SYNC_HANDLE) {
   1228         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1229     }
   1230 
   1231     return EGL_CONDITION_SATISFIED_KHR;
   1232 }
   1233 
   1234 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
   1235         EGLint attribute, EGLint *value)
   1236 {
   1237     if (sync != FENCE_SYNC_HANDLE) {
   1238         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1239     }
   1240 
   1241     switch (attribute) {
   1242     case EGL_SYNC_TYPE_KHR:
   1243         *value = EGL_SYNC_FENCE_KHR;
   1244         return EGL_TRUE;
   1245     case EGL_SYNC_STATUS_KHR:
   1246         *value = EGL_SIGNALED_KHR;
   1247         return EGL_TRUE;
   1248     case EGL_SYNC_CONDITION_KHR:
   1249         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
   1250         return EGL_TRUE;
   1251     default:
   1252         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1253     }
   1254 }
   1255