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_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
    267         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    268     }
    269 
    270     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    271     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
    272             getWidth(), getHeight());
    273     if (!rcSurface) {
    274         ALOGE("rcCreateWindowSurface returned 0");
    275         return EGL_FALSE;
    276     }
    277     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    278             ((cb_handle_t*)(buffer->handle))->hostHandle);
    279 
    280     return EGL_TRUE;
    281 }
    282 
    283 egl_window_surface_t* egl_window_surface_t::create(
    284         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    285         ANativeWindow* window)
    286 {
    287     egl_window_surface_t* wnd = new egl_window_surface_t(
    288             dpy, config, surfType, window);
    289     if (wnd && !wnd->init()) {
    290         delete wnd;
    291         wnd = NULL;
    292     }
    293     return wnd;
    294 }
    295 
    296 egl_window_surface_t::~egl_window_surface_t() {
    297     DEFINE_HOST_CONNECTION;
    298     if (rcSurface && rcEnc) {
    299         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    300     }
    301     if (buffer) {
    302         nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
    303     }
    304     nativeWindow->common.decRef(&nativeWindow->common);
    305 }
    306 
    307 void egl_window_surface_t::setSwapInterval(int interval)
    308 {
    309     nativeWindow->setSwapInterval(nativeWindow, interval);
    310 }
    311 
    312 EGLBoolean egl_window_surface_t::swapBuffers()
    313 {
    314     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    315 
    316     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
    317 
    318     nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
    319     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
    320         buffer = NULL;
    321         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    322     }
    323 
    324     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    325             ((cb_handle_t *)(buffer->handle))->hostHandle);
    326 
    327     return EGL_TRUE;
    328 }
    329 
    330 // ----------------------------------------------------------------------------
    331 //egl_pbuffer_surface_t
    332 
    333 struct egl_pbuffer_surface_t : public egl_surface_t {
    334     static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
    335             EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
    336 
    337     virtual ~egl_pbuffer_surface_t();
    338 
    339     virtual void       setSwapInterval(int interval) {}
    340     virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
    341 
    342     uint32_t getRcColorBuffer() { return rcColorBuffer; }
    343 
    344 private:
    345     egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
    346             int32_t w, int32_t h);
    347     EGLBoolean init(GLenum format);
    348 
    349     uint32_t rcColorBuffer;
    350 };
    351 
    352 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
    353         EGLint surfType, int32_t w, int32_t h)
    354 :   egl_surface_t(dpy, config, surfType),
    355     rcColorBuffer(0)
    356 {
    357     setWidth(w);
    358     setHeight(h);
    359 }
    360 
    361 egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
    362 {
    363     DEFINE_HOST_CONNECTION;
    364     if (rcEnc) {
    365         if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
    366         if (rcSurface)     rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    367     }
    368 }
    369 
    370 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
    371 {
    372     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    373 
    374     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config,
    375             getWidth(), getHeight());
    376     if (!rcSurface) {
    377         ALOGE("rcCreateWindowSurface returned 0");
    378         return EGL_FALSE;
    379     }
    380 
    381     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
    382             pixelFormat);
    383     if (!rcColorBuffer) {
    384         ALOGE("rcCreateColorBuffer returned 0");
    385         return EGL_FALSE;
    386     }
    387 
    388     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
    389 
    390     return EGL_TRUE;
    391 }
    392 
    393 egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
    394         EGLConfig config, EGLint surfType, int32_t w, int32_t h,
    395         GLenum pixelFormat)
    396 {
    397     egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
    398             w, h);
    399     if (pb && !pb->init(pixelFormat)) {
    400         delete pb;
    401         pb = NULL;
    402     }
    403     return pb;
    404 }
    405 
    406 static const char *getGLString(int glEnum)
    407 {
    408     EGLThreadInfo *tInfo = getEGLThreadInfo();
    409     if (!tInfo || !tInfo->currentContext) {
    410         return NULL;
    411     }
    412 
    413     const char** strPtr = NULL;
    414 
    415 #define GL_VENDOR                         0x1F00
    416 #define GL_RENDERER                       0x1F01
    417 #define GL_VERSION                        0x1F02
    418 #define GL_EXTENSIONS                     0x1F03
    419 
    420     switch(glEnum) {
    421         case GL_VERSION:
    422             strPtr = &tInfo->currentContext->versionString;
    423             break;
    424         case GL_VENDOR:
    425             strPtr = &tInfo->currentContext->vendorString;
    426             break;
    427         case GL_RENDERER:
    428             strPtr = &tInfo->currentContext->rendererString;
    429             break;
    430         case GL_EXTENSIONS:
    431             strPtr = &tInfo->currentContext->extensionString;
    432             break;
    433     }
    434 
    435     if (!strPtr) {
    436         return NULL;
    437     }
    438 
    439     if (*strPtr != NULL) {
    440         //
    441         // string is already cached
    442         //
    443         return *strPtr;
    444     }
    445 
    446     //
    447     // first query of that string - need to query host
    448     //
    449     DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
    450     char *hostStr = NULL;
    451     int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
    452     if (n < 0) {
    453         hostStr = new char[-n+1];
    454         n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
    455         if (n <= 0) {
    456             delete [] hostStr;
    457             hostStr = NULL;
    458         }
    459     }
    460 
    461     //
    462     // keep the string in the context and return its value
    463     //
    464     *strPtr = hostStr;
    465     return hostStr;
    466 }
    467 
    468 // ----------------------------------------------------------------------------
    469 
    470 // The one and only supported display object.
    471 static eglDisplay s_display;
    472 
    473 static EGLClient_eglInterface s_eglIface = {
    474     getThreadInfo: getEGLThreadInfo,
    475     getGLString: getGLString
    476 };
    477 
    478 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
    479 EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
    480 {
    481     //
    482     // we support only EGL_DEFAULT_DISPLAY.
    483     //
    484     if (display_id != EGL_DEFAULT_DISPLAY) {
    485         return EGL_NO_DISPLAY;
    486     }
    487 
    488     return (EGLDisplay)&s_display;
    489 }
    490 
    491 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
    492 {
    493     VALIDATE_DISPLAY(dpy,EGL_FALSE);
    494 
    495     if (!s_display.initialize(&s_eglIface)) {
    496         return EGL_FALSE;
    497     }
    498     if (major!=NULL)
    499         *major = s_display.getVersionMajor();
    500     if (minor!=NULL)
    501         *minor = s_display.getVersionMinor();
    502     return EGL_TRUE;
    503 }
    504 
    505 EGLBoolean eglTerminate(EGLDisplay dpy)
    506 {
    507     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    508 
    509     s_display.terminate();
    510     return EGL_TRUE;
    511 }
    512 
    513 EGLint eglGetError()
    514 {
    515     EGLint error = getEGLThreadInfo()->eglError;
    516     getEGLThreadInfo()->eglError = EGL_SUCCESS;
    517     return error;
    518 }
    519 
    520 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
    521 {
    522     // search in EGL function table
    523     for (int i=0; i<egl_num_funcs; i++) {
    524         if (!strcmp(egl_funcs_by_name[i].name, procname)) {
    525             return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
    526         }
    527     }
    528 
    529     //
    530     // Make sure display is initialized before searching in client APIs
    531     //
    532     if (!s_display.initialized()) {
    533         if (!s_display.initialize(&s_eglIface)) {
    534             return NULL;
    535         }
    536     }
    537 
    538     // look in gles client api's extensions table
    539     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
    540 
    541     // Fail - function not found.
    542     return NULL;
    543 }
    544 
    545 const char* eglQueryString(EGLDisplay dpy, EGLint name)
    546 {
    547     VALIDATE_DISPLAY_INIT(dpy, NULL);
    548 
    549     return s_display.queryString(name);
    550 }
    551 
    552 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    553 {
    554     VALIDATE_DISPLAY_INIT(dpy, NULL);
    555 
    556     if(!num_config) {
    557         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
    558     }
    559 
    560     GLint numConfigs = s_display.getNumConfigs();
    561     if (!configs) {
    562         *num_config = numConfigs;
    563         return EGL_TRUE;
    564     }
    565 
    566     int i=0;
    567     for (i=0 ; i<numConfigs && i<config_size ; i++) {
    568         *configs++ = (EGLConfig)i;
    569     }
    570     *num_config = i;
    571     return EGL_TRUE;
    572 }
    573 
    574 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    575 {
    576     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    577 
    578     int attribs_size = 0;
    579     if (attrib_list) {
    580         const EGLint * attrib_p = attrib_list;
    581         while (attrib_p[0] != EGL_NONE) {
    582             attribs_size += 2;
    583             attrib_p += 2;
    584         }
    585         attribs_size++; //for the terminating EGL_NONE
    586     }
    587 
    588     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    589     *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)configs, config_size);
    590 
    591     return EGL_TRUE;
    592 }
    593 
    594 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
    595 {
    596     VALIDATE_DISPLAY_INIT(dpy, NULL);
    597     VALIDATE_CONFIG(config, EGL_FALSE);
    598 
    599     if (s_display.getConfigAttrib(config, attribute, value))
    600     {
    601         return EGL_TRUE;
    602     }
    603     else
    604     {
    605         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
    606     }
    607 }
    608 
    609 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
    610 {
    611     VALIDATE_DISPLAY_INIT(dpy, NULL);
    612     VALIDATE_CONFIG(config, EGL_FALSE);
    613     if (win == 0) {
    614         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    615     }
    616 
    617     EGLint surfaceType;
    618     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
    619 
    620     if (!(surfaceType & EGL_WINDOW_BIT)) {
    621         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    622     }
    623 
    624     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
    625         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    626     }
    627 
    628     egl_surface_t* surface = egl_window_surface_t::create(
    629             &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
    630     if (!surface) {
    631         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    632     }
    633 
    634     return surface;
    635 }
    636 
    637 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
    638 {
    639     VALIDATE_DISPLAY_INIT(dpy, NULL);
    640     VALIDATE_CONFIG(config, EGL_FALSE);
    641 
    642     EGLint surfaceType;
    643     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
    644 
    645     if (!(surfaceType & EGL_PBUFFER_BIT)) {
    646         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    647     }
    648 
    649     int32_t w = 0;
    650     int32_t h = 0;
    651     EGLint texFormat = EGL_NO_TEXTURE;
    652     EGLint texTarget = EGL_NO_TEXTURE;
    653     while (attrib_list[0]) {
    654         switch (attrib_list[0]) {
    655             case EGL_WIDTH:
    656                 w = attrib_list[1];
    657                 break;
    658             case EGL_HEIGHT:
    659                 h = attrib_list[1];
    660                 break;
    661             case EGL_TEXTURE_FORMAT:
    662                 texFormat = attrib_list[1];
    663                 break;
    664             case EGL_TEXTURE_TARGET:
    665                 texTarget = attrib_list[1];
    666                 break;
    667             default:
    668                 break;
    669         };
    670         attrib_list+=2;
    671     }
    672     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
    673         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
    674         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    675     }
    676     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
    677 
    678     GLenum pixelFormat;
    679     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
    680         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    681 
    682     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
    683             surfaceType, w, h, pixelFormat);
    684     if (!surface) {
    685         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    686     }
    687 
    688     //setup attributes
    689     surface->setTextureFormat(texFormat);
    690     surface->setTextureTarget(texTarget);
    691 
    692     return surface;
    693 }
    694 
    695 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
    696 {
    697     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
    698     //     located on host. In order to support Pixmaps we should either punt
    699     //     to s/w rendering -or- let the host render to a buffer that will be
    700     //     copied back to guest at some sync point. None of those methods not
    701     //     implemented and pixmaps are not used with OpenGL anyway ...
    702     return EGL_NO_SURFACE;
    703 }
    704 
    705 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
    706 {
    707     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    708     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    709 
    710     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
    711     delete surface;
    712 
    713     return EGL_TRUE;
    714 }
    715 
    716 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
    717 {
    718     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    719     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    720 
    721     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
    722     EGLBoolean ret = EGL_TRUE;
    723     switch (attribute) {
    724         case EGL_CONFIG_ID:
    725             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
    726             break;
    727         case EGL_WIDTH:
    728             *value = surface->getWidth();
    729             break;
    730         case EGL_HEIGHT:
    731             *value = surface->getHeight();
    732             break;
    733         case EGL_TEXTURE_FORMAT:
    734             *value = surface->getTextureFormat();
    735             break;
    736         case EGL_TEXTURE_TARGET:
    737             *value = surface->getTextureTarget();
    738             break;
    739         case EGL_SWAP_BEHAVIOR:
    740             *value = surface->getSwapBehavior();
    741             break;
    742         case EGL_LARGEST_PBUFFER:
    743             // not modified for a window or pixmap surface
    744             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
    745             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
    746             break;
    747         //TODO: complete other attributes
    748         default:
    749             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
    750             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    751             break;
    752     }
    753 
    754     return ret;
    755 }
    756 
    757 EGLBoolean eglBindAPI(EGLenum api)
    758 {
    759     if (api != EGL_OPENGL_ES_API)
    760         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    761     return EGL_TRUE;
    762 }
    763 
    764 EGLenum eglQueryAPI()
    765 {
    766     return EGL_OPENGL_ES_API;
    767 }
    768 
    769 EGLBoolean eglWaitClient()
    770 {
    771     return eglWaitGL();
    772 }
    773 
    774 EGLBoolean eglReleaseThread()
    775 {
    776     EGLThreadInfo *tInfo = getEGLThreadInfo();
    777     if (tInfo && tInfo->currentContext) {
    778         return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
    779     }
    780     return EGL_TRUE;
    781 }
    782 
    783 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
    784 {
    785     //TODO
    786     ALOGW("%s not implemented", __FUNCTION__);
    787     return 0;
    788 }
    789 
    790 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
    791 {
    792     //TODO
    793     ALOGW("%s not implemented", __FUNCTION__);
    794     return 0;
    795 }
    796 
    797 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
    798 {
    799     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    800     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    801     if (eglSurface == EGL_NO_SURFACE) {
    802         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    803     }
    804 
    805     if (buffer != EGL_BACK_BUFFER) {
    806         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    807     }
    808 
    809     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
    810 
    811     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
    812         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    813     }
    814 
    815     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
    816         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    817     }
    818 
    819     //It's now safe to cast to pbuffer surface
    820     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
    821 
    822     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    823     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
    824 
    825     return GL_TRUE;
    826 }
    827 
    828 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    829 {
    830     //TODO
    831     ALOGW("%s not implemented", __FUNCTION__);
    832     return 0;
    833 }
    834 
    835 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
    836 {
    837     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    838     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    839 
    840     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
    841     if (!ctx) {
    842         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
    843     }
    844     if (!ctx->draw) {
    845         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    846     }
    847     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
    848     draw->setSwapInterval(interval);
    849 
    850     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
    851 
    852     return EGL_TRUE;
    853 }
    854 
    855 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
    856 {
    857     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
    858     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
    859 
    860     EGLint version = 1; //default
    861     while (attrib_list && attrib_list[0]) {
    862         if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
    863         attrib_list+=2;
    864     }
    865 
    866     uint32_t rcShareCtx = 0;
    867     EGLContext_t * shareCtx = NULL;
    868     if (share_context) {
    869         shareCtx = static_cast<EGLContext_t*>(share_context);
    870         rcShareCtx = shareCtx->rcContext;
    871         if (shareCtx->dpy != dpy)
    872             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
    873     }
    874 
    875     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
    876     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uint32_t)config, rcShareCtx, version);
    877     if (!rcContext) {
    878         ALOGE("rcCreateContext returned 0");
    879         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
    880     }
    881 
    882     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
    883     if (!context)
    884         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
    885 
    886     context->version = version;
    887     context->rcContext = rcContext;
    888 
    889 
    890     return context;
    891 }
    892 
    893 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    894 {
    895     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    896     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
    897 
    898     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
    899 
    900     if (getEGLThreadInfo()->currentContext == context)
    901     {
    902         eglMakeCurrent(dpy, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
    903     }
    904 
    905     if (context->rcContext) {
    906         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    907         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
    908         context->rcContext = 0;
    909     }
    910 
    911     delete context;
    912     return EGL_TRUE;
    913 }
    914 
    915 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
    916 {
    917     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    918     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
    919     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
    920 
    921     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
    922         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    923     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
    924         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    925 
    926     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
    927     uint32_t ctxHandle = (context) ? context->rcContext : 0;
    928     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
    929     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
    930     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
    931     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
    932 
    933     //
    934     // Nothing to do if no binding change has made
    935     //
    936     EGLThreadInfo *tInfo = getEGLThreadInfo();
    937     if (tInfo->currentContext == context &&
    938         (context == NULL ||
    939         (context && context->draw == draw && context->read == read))) {
    940         return EGL_TRUE;
    941     }
    942 
    943     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
    944         //context is current to another thread
    945         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
    946     }
    947 
    948     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    949     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
    950         ALOGE("rcMakeCurrent returned EGL_FALSE");
    951         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
    952     }
    953 
    954     //Now make the local bind
    955     if (context) {
    956         context->draw = draw;
    957         context->read = read;
    958         context->flags |= EGLContext_t::IS_CURRENT;
    959         //set the client state
    960         if (context->version == 2) {
    961             hostCon->gl2Encoder()->setClientState(context->getClientState());
    962             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
    963         }
    964         else {
    965             hostCon->glEncoder()->setClientState(context->getClientState());
    966             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
    967         }
    968     }
    969     else {
    970         //release ClientState & SharedGroup
    971         if (tInfo->currentContext->version == 2) {
    972             hostCon->gl2Encoder()->setClientState(NULL);
    973             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
    974         }
    975         else {
    976             hostCon->glEncoder()->setClientState(NULL);
    977             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
    978         }
    979 
    980     }
    981 
    982     if (tInfo->currentContext)
    983         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
    984 
    985     //Now make current
    986     tInfo->currentContext = context;
    987 
    988     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
    989     if (tInfo->currentContext) {
    990         if (tInfo->currentContext->version == 2) {
    991             if (!hostCon->gl2Encoder()->isInitialized()) {
    992                 s_display.gles2_iface()->init();
    993                 hostCon->gl2Encoder()->setInitialized();
    994                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
    995             }
    996         }
    997         else {
    998             if (!hostCon->glEncoder()->isInitialized()) {
    999                 s_display.gles_iface()->init();
   1000                 hostCon->glEncoder()->setInitialized();
   1001                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
   1002             }
   1003         }
   1004     }
   1005 
   1006     return EGL_TRUE;
   1007 }
   1008 
   1009 EGLContext eglGetCurrentContext()
   1010 {
   1011     return getEGLThreadInfo()->currentContext;
   1012 }
   1013 
   1014 EGLSurface eglGetCurrentSurface(EGLint readdraw)
   1015 {
   1016     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1017     if (!context)
   1018         return EGL_NO_SURFACE; //not an error
   1019 
   1020     switch (readdraw) {
   1021         case EGL_READ:
   1022             return context->read;
   1023         case EGL_DRAW:
   1024             return context->draw;
   1025         default:
   1026             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1027     }
   1028 }
   1029 
   1030 EGLDisplay eglGetCurrentDisplay()
   1031 {
   1032     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1033     if (!context)
   1034         return EGL_NO_DISPLAY; //not an error
   1035 
   1036     return context->dpy;
   1037 }
   1038 
   1039 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
   1040 {
   1041     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1042     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
   1043 
   1044     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
   1045 
   1046     EGLBoolean ret = EGL_TRUE;
   1047     switch (attribute) {
   1048         case EGL_CONFIG_ID:
   1049             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
   1050             break;
   1051         case EGL_CONTEXT_CLIENT_TYPE:
   1052             *value = EGL_OPENGL_ES_API;
   1053             break;
   1054         case EGL_CONTEXT_CLIENT_VERSION:
   1055             *value = context->version;
   1056             break;
   1057         case EGL_RENDER_BUFFER:
   1058             if (!context->draw)
   1059                 *value = EGL_NONE;
   1060             else
   1061                 *value = EGL_BACK_BUFFER; //single buffer not supported
   1062             break;
   1063         default:
   1064             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
   1065             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1066             break;
   1067     }
   1068 
   1069     return ret;
   1070 }
   1071 
   1072 EGLBoolean eglWaitGL()
   1073 {
   1074     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1075     if (!tInfo || !tInfo->currentContext) {
   1076         return EGL_FALSE;
   1077     }
   1078 
   1079     if (tInfo->currentContext->version == 2) {
   1080         s_display.gles2_iface()->finish();
   1081     }
   1082     else {
   1083         s_display.gles_iface()->finish();
   1084     }
   1085 
   1086     return EGL_TRUE;
   1087 }
   1088 
   1089 EGLBoolean eglWaitNative(EGLint engine)
   1090 {
   1091     return EGL_TRUE;
   1092 }
   1093 
   1094 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
   1095 {
   1096     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1097     if (eglSurface == EGL_NO_SURFACE)
   1098         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1099 
   1100     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1101 
   1102     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
   1103     if (d->dpy != dpy)
   1104         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
   1105 
   1106     // post the surface
   1107     d->swapBuffers();
   1108 
   1109     hostCon->flush();
   1110     return EGL_TRUE;
   1111 }
   1112 
   1113 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
   1114 {
   1115     //TODO :later
   1116     return 0;
   1117 }
   1118 
   1119 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
   1120 {
   1121     //TODO later
   1122     return 0;
   1123 }
   1124 
   1125 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
   1126 {
   1127     //TODO later
   1128     return 0;
   1129 }
   1130 
   1131 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
   1132 {
   1133     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
   1134     if (ctx != EGL_NO_CONTEXT) {
   1135         setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   1136     }
   1137     if (target != EGL_NATIVE_BUFFER_ANDROID) {
   1138         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1139     }
   1140 
   1141     android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
   1142 
   1143     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   1144         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1145 
   1146     if (native_buffer->common.version != sizeof(android_native_buffer_t))
   1147         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1148 
   1149     cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
   1150 
   1151     switch (cb->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