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