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