Home | History | Annotate | Download | only in egl
      1 /*
      2 * Copyright (C) 2011 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #include "HostConnection.h"
     18 #include "ThreadInfo.h"
     19 #include "eglDisplay.h"
     20 #include "egl_ftable.h"
     21 #include <cutils/log.h>
     22 #include "gralloc_cb.h"
     23 #include "GLClientState.h"
     24 #include "GLSharedGroup.h"
     25 #include "eglContext.h"
     26 #include "ClientAPIExts.h"
     27 
     28 #include "GLEncoder.h"
     29 #ifdef WITH_GLES2
     30 #include "GL2Encoder.h"
     31 #endif
     32 
     33 #include <system/window.h>
     34 
     35 template<typename T>
     36 static T setErrorFunc(GLint error, T returnValue) {
     37     getEGLThreadInfo()->eglError = error;
     38     return returnValue;
     39 }
     40 
     41 const char *  eglStrError(EGLint err)
     42 {
     43     switch (err){
     44         case EGL_SUCCESS:           return "EGL_SUCCESS";
     45         case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
     46         case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
     47         case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
     48         case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
     49         case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
     50         case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
     51         case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
     52         case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
     53         case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
     54         case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
     55         case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
     56         case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
     57         case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
     58         case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
     59         default: return "UNKNOWN";
     60     }
     61 }
     62 
     63 #define LOG_EGL_ERRORS 1
     64 
     65 #ifdef LOG_EGL_ERRORS
     66 
     67 #define setErrorReturn(error, retVal)     \
     68     {                                                \
     69         ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error));     \
     70         return setErrorFunc(error, retVal);            \
     71     }
     72 
     73 #define RETURN_ERROR(ret,err)           \
     74     ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err));    \
     75     getEGLThreadInfo()->eglError = err;    \
     76     return ret;
     77 
     78 #else //!LOG_EGL_ERRORS
     79 
     80 #define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
     81 
     82 #define RETURN_ERROR(ret,err)           \
     83     getEGLThreadInfo()->eglError = err; \
     84     return ret;
     85 
     86 #endif //LOG_EGL_ERRORS
     87 
     88 #define VALIDATE_CONFIG(cfg,ret) \
     89     if(((intptr_t)cfg<0)||((intptr_t)cfg>s_display.getNumConfigs())) { \
     90         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
     91     }
     92 
     93 #define VALIDATE_DISPLAY(dpy,ret) \
     94     if ((dpy) != (EGLDisplay)&s_display) { \
     95         RETURN_ERROR(ret, EGL_BAD_DISPLAY);    \
     96     }
     97 
     98 #define VALIDATE_DISPLAY_INIT(dpy,ret) \
     99     VALIDATE_DISPLAY(dpy, ret)    \
    100     if (!s_display.initialized()) {        \
    101         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);    \
    102     }
    103 
    104 #define DEFINE_HOST_CONNECTION \
    105     HostConnection *hostCon = HostConnection::get(); \
    106     renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
    107 
    108 #define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
    109     HostConnection *hostCon = HostConnection::get(); \
    110     if (!hostCon) { \
    111         ALOGE("egl: Failed to get host connection\n"); \
    112         return ret; \
    113     } \
    114     renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
    115     if (!rcEnc) { \
    116         ALOGE("egl: Failed to get renderControl encoder context\n"); \
    117         return ret; \
    118     }
    119 
    120 #define VALIDATE_CONTEXT_RETURN(context,ret)        \
    121     if (!context) {                                    \
    122         RETURN_ERROR(ret,EGL_BAD_CONTEXT);    \
    123     }
    124 
    125 #define VALIDATE_SURFACE_RETURN(surface, ret)    \
    126     if (surface != EGL_NO_SURFACE) {    \
    127         egl_surface_t* s( static_cast<egl_surface_t*>(surface) );    \
    128         if (s->dpy != (EGLDisplay)&s_display)    \
    129             setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);    \
    130     }
    131 
    132 
    133 EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
    134     dpy(dpy),
    135     config(config),
    136     read(EGL_NO_SURFACE),
    137     draw(EGL_NO_SURFACE),
    138     shareCtx(shareCtx),
    139     rcContext(0),
    140     versionString(NULL),
    141     vendorString(NULL),
    142     rendererString(NULL),
    143     extensionString(NULL),
    144     deletePending(0)
    145 {
    146     flags = 0;
    147     version = 1;
    148     clientState = new GLClientState();
    149     if (shareCtx)
    150         sharedGroup = shareCtx->getSharedGroup();
    151     else
    152         sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
    153 };
    154 
    155 EGLContext_t::~EGLContext_t()
    156 {
    157     delete clientState;
    158     delete [] versionString;
    159     delete [] vendorString;
    160     delete [] rendererString;
    161     delete [] extensionString;
    162 }
    163 
    164 // ----------------------------------------------------------------------------
    165 //egl_surface_t
    166 
    167 //we don't need to handle depth since it's handled when window created on the host
    168 
    169 struct egl_surface_t {
    170 
    171     EGLDisplay          dpy;
    172     EGLConfig           config;
    173 
    174 
    175     egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
    176     virtual     ~egl_surface_t();
    177 
    178     virtual     void        setSwapInterval(int interval) = 0;
    179     virtual     EGLBoolean  swapBuffers() = 0;
    180 
    181     EGLint      getSwapBehavior() const;
    182     uint32_t    getRcSurface()   { return rcSurface; }
    183     EGLint      getSurfaceType() { return surfaceType; }
    184 
    185     EGLint      getWidth(){ return width; }
    186     EGLint      getHeight(){ return height; }
    187     void        setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
    188     EGLint      getTextureFormat() { return texFormat; }
    189     void        setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
    190     EGLint      getTextureTarget() { return texTarget; }
    191 
    192 private:
    193     //
    194     //Surface attributes
    195     //
    196     EGLint      width;
    197     EGLint      height;
    198     EGLint      texFormat;
    199     EGLint      texTarget;
    200 
    201 protected:
    202     void        setWidth(EGLint w)  { width = w;  }
    203     void        setHeight(EGLint h) { height = h; }
    204 
    205     EGLint      surfaceType;
    206     uint32_t    rcSurface; //handle to surface created via remote control
    207 };
    208 
    209 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
    210     : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
    211 {
    212     width = 0;
    213     height = 0;
    214     texFormat = EGL_NO_TEXTURE;
    215     texTarget = EGL_NO_TEXTURE;
    216 }
    217 
    218 EGLint egl_surface_t::getSwapBehavior() const {
    219     return EGL_BUFFER_PRESERVED;
    220 }
    221 
    222 egl_surface_t::~egl_surface_t()
    223 {
    224 }
    225 
    226 // ----------------------------------------------------------------------------
    227 // egl_window_surface_t
    228 
    229 struct egl_window_surface_t : public egl_surface_t {
    230     static egl_window_surface_t* create(
    231             EGLDisplay dpy, EGLConfig config, EGLint surfType,
    232             ANativeWindow* window);
    233 
    234     virtual ~egl_window_surface_t();
    235 
    236     virtual void       setSwapInterval(int interval);
    237     virtual EGLBoolean swapBuffers();
    238 
    239 private:
    240     egl_window_surface_t(
    241             EGLDisplay dpy, EGLConfig config, EGLint surfType,
    242             ANativeWindow* window);
    243     EGLBoolean init();
    244 
    245     ANativeWindow*              nativeWindow;
    246     android_native_buffer_t*    buffer;
    247 };
    248 
    249 egl_window_surface_t::egl_window_surface_t (
    250         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    251         ANativeWindow* window)
    252 :   egl_surface_t(dpy, config, surfType),
    253     nativeWindow(window),
    254     buffer(NULL)
    255 {
    256     // keep a reference on the window
    257     nativeWindow->common.incRef(&nativeWindow->common);
    258     EGLint w,h;
    259     nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w);
    260     setWidth(w);
    261     nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h);
    262     setHeight(h);
    263 }
    264 
    265 EGLBoolean egl_window_surface_t::init()
    266 {
    267     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
    268         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    269     }
    270 
    271     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    272     rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
    273             getWidth(), getHeight());
    274     if (!rcSurface) {
    275         ALOGE("rcCreateWindowSurface returned 0");
    276         return EGL_FALSE;
    277     }
    278     rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
    279             ((cb_handle_t*)(buffer->handle))->hostHandle);
    280 
    281     return EGL_TRUE;
    282 }
    283 
    284 egl_window_surface_t* egl_window_surface_t::create(
    285         EGLDisplay dpy, EGLConfig config, EGLint surfType,
    286         ANativeWindow* window)
    287 {
    288     egl_window_surface_t* wnd = new egl_window_surface_t(
    289             dpy, config, surfType, window);
    290     if (wnd && !wnd->init()) {
    291         delete wnd;
    292         wnd = NULL;
    293     }
    294     return wnd;
    295 }
    296 
    297 egl_window_surface_t::~egl_window_surface_t() {
    298     DEFINE_HOST_CONNECTION;
    299     if (rcSurface && rcEnc) {
    300         rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
    301     }
    302     if (buffer) {
    303         nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
    304     }
    305     nativeWindow->common.decRef(&nativeWindow->common);
    306 }
    307 
    308 void egl_window_surface_t::setSwapInterval(int interval)
    309 {
    310     nativeWindow->setSwapInterval(nativeWindow, interval);
    311 }
    312 
    313 EGLBoolean egl_window_surface_t::swapBuffers()
    314 {
    315     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    316 
    317     rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
    318 
    319     nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
    320     if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
    321         buffer = NULL;
    322         setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
    323     }
    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) { (void)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, (uintptr_t)config,
    376             getWidth(), getHeight());
    377     if (!rcSurface) {
    378         ALOGE("rcCreateWindowSurface returned 0");
    379         return EGL_FALSE;
    380     }
    381 
    382     rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
    383             pixelFormat);
    384     if (!rcColorBuffer) {
    385         ALOGE("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     // look in gles client api's extensions table
    531     return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
    532 
    533     // Fail - function not found.
    534     return NULL;
    535 }
    536 
    537 const char* eglQueryString(EGLDisplay dpy, EGLint name)
    538 {
    539     VALIDATE_DISPLAY_INIT(dpy, NULL);
    540 
    541     return s_display.queryString(name);
    542 }
    543 
    544 EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    545 {
    546     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    547 
    548     if(!num_config) {
    549         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
    550     }
    551 
    552     GLint numConfigs = s_display.getNumConfigs();
    553     if (!configs) {
    554         *num_config = numConfigs;
    555         return EGL_TRUE;
    556     }
    557 
    558     EGLint i;
    559     for (i = 0 ; i < numConfigs && i < config_size ; i++) {
    560         *configs++ = (EGLConfig)(uintptr_t)i;
    561     }
    562     *num_config = i;
    563     return EGL_TRUE;
    564 }
    565 
    566 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    567 {
    568     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    569 
    570     int attribs_size = 0;
    571     if (attrib_list) {
    572         const EGLint * attrib_p = attrib_list;
    573         while (attrib_p[0] != EGL_NONE) {
    574             attribs_size += 2;
    575             attrib_p += 2;
    576         }
    577         attribs_size++; //for the terminating EGL_NONE
    578     }
    579 
    580     uint32_t* tempConfigs[config_size];
    581     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    582     *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
    583     if (configs!=NULL) {
    584         EGLint i=0;
    585         for (i=0;i<(*num_config);i++) {
    586              *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
    587         }
    588     }
    589 
    590     if (*num_config <= 0)
    591         return EGL_FALSE;
    592     return EGL_TRUE;
    593 }
    594 
    595 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
    596 {
    597     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    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     (void)attrib_list;
    613 
    614     VALIDATE_DISPLAY_INIT(dpy, NULL);
    615     VALIDATE_CONFIG(config, EGL_FALSE);
    616     if (win == 0) {
    617         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    618     }
    619 
    620     EGLint surfaceType;
    621     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
    622 
    623     if (!(surfaceType & EGL_WINDOW_BIT)) {
    624         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    625     }
    626 
    627     if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
    628         setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    629     }
    630 
    631     egl_surface_t* surface = egl_window_surface_t::create(
    632             &s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
    633     if (!surface) {
    634         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    635     }
    636 
    637     return surface;
    638 }
    639 
    640 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
    641 {
    642     VALIDATE_DISPLAY_INIT(dpy, NULL);
    643     VALIDATE_CONFIG(config, EGL_FALSE);
    644 
    645     EGLint surfaceType;
    646     if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)    return EGL_FALSE;
    647 
    648     if (!(surfaceType & EGL_PBUFFER_BIT)) {
    649         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    650     }
    651 
    652     int32_t w = 0;
    653     int32_t h = 0;
    654     EGLint texFormat = EGL_NO_TEXTURE;
    655     EGLint texTarget = EGL_NO_TEXTURE;
    656     while (attrib_list[0]) {
    657         switch (attrib_list[0]) {
    658             case EGL_WIDTH:
    659                 w = attrib_list[1];
    660                 break;
    661             case EGL_HEIGHT:
    662                 h = attrib_list[1];
    663                 break;
    664             case EGL_TEXTURE_FORMAT:
    665                 texFormat = attrib_list[1];
    666                 break;
    667             case EGL_TEXTURE_TARGET:
    668                 texTarget = attrib_list[1];
    669                 break;
    670             default:
    671                 break;
    672         };
    673         attrib_list+=2;
    674     }
    675     if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
    676         ((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
    677         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    678     }
    679     // TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
    680 
    681     GLenum pixelFormat;
    682     if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
    683         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
    684 
    685     egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
    686             surfaceType, w, h, pixelFormat);
    687     if (!surface) {
    688         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    689     }
    690 
    691     //setup attributes
    692     surface->setTextureFormat(texFormat);
    693     surface->setTextureTarget(texTarget);
    694 
    695     return surface;
    696 }
    697 
    698 EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
    699 {
    700     //XXX: Pixmap not supported. The host cannot render to a pixmap resource
    701     //     located on host. In order to support Pixmaps we should either punt
    702     //     to s/w rendering -or- let the host render to a buffer that will be
    703     //     copied back to guest at some sync point. None of those methods not
    704     //     implemented and pixmaps are not used with OpenGL anyway ...
    705     (void)dpy;
    706     (void)config;
    707     (void)pixmap;
    708     (void)attrib_list;
    709     return EGL_NO_SURFACE;
    710 }
    711 
    712 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
    713 {
    714     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    715     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    716 
    717     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
    718     delete surface;
    719 
    720     return EGL_TRUE;
    721 }
    722 
    723 EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
    724 {
    725     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    726     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    727 
    728     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
    729     EGLBoolean ret = EGL_TRUE;
    730     switch (attribute) {
    731         case EGL_CONFIG_ID:
    732             ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value);
    733             break;
    734         case EGL_WIDTH:
    735             *value = surface->getWidth();
    736             break;
    737         case EGL_HEIGHT:
    738             *value = surface->getHeight();
    739             break;
    740         case EGL_TEXTURE_FORMAT:
    741             *value = surface->getTextureFormat();
    742             break;
    743         case EGL_TEXTURE_TARGET:
    744             *value = surface->getTextureTarget();
    745             break;
    746         case EGL_SWAP_BEHAVIOR:
    747             *value = surface->getSwapBehavior();
    748             break;
    749         case EGL_LARGEST_PBUFFER:
    750             // not modified for a window or pixmap surface
    751             // and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
    752             if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
    753             break;
    754         //TODO: complete other attributes
    755         default:
    756             ALOGE("eglQuerySurface %x  EGL_BAD_ATTRIBUTE", attribute);
    757             ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    758             break;
    759     }
    760 
    761     return ret;
    762 }
    763 
    764 EGLBoolean eglBindAPI(EGLenum api)
    765 {
    766     if (api != EGL_OPENGL_ES_API)
    767         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    768     return EGL_TRUE;
    769 }
    770 
    771 EGLenum eglQueryAPI()
    772 {
    773     return EGL_OPENGL_ES_API;
    774 }
    775 
    776 EGLBoolean eglWaitClient()
    777 {
    778     return eglWaitGL();
    779 }
    780 
    781 EGLBoolean eglReleaseThread()
    782 {
    783     EGLThreadInfo *tInfo = getEGLThreadInfo();
    784     if (tInfo && tInfo->currentContext) {
    785         return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
    786     }
    787     return EGL_TRUE;
    788 }
    789 
    790 EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
    791 {
    792     //TODO
    793     (void)dpy;
    794     (void)buftype;
    795     (void)buffer;
    796     (void)config;
    797     (void)attrib_list;
    798     ALOGW("%s not implemented", __FUNCTION__);
    799     return 0;
    800 }
    801 
    802 EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
    803 {
    804     //TODO
    805     (void)dpy;
    806     (void)surface;
    807     (void)attribute;
    808     (void)value;
    809     ALOGW("%s not implemented", __FUNCTION__);
    810     return 0;
    811 }
    812 
    813 EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
    814 {
    815     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    816     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
    817     if (eglSurface == EGL_NO_SURFACE) {
    818         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    819     }
    820 
    821     if (buffer != EGL_BACK_BUFFER) {
    822         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
    823     }
    824 
    825     egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
    826 
    827     if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
    828         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    829     }
    830 
    831     if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
    832         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    833     }
    834 
    835     //It's now safe to cast to pbuffer surface
    836     egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
    837 
    838     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    839     rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
    840 
    841     return GL_TRUE;
    842 }
    843 
    844 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    845 {
    846     //TODO
    847     (void)dpy;
    848     (void)surface;
    849     (void)buffer;
    850     ALOGW("%s not implemented", __FUNCTION__);
    851     return 0;
    852 }
    853 
    854 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
    855 {
    856     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    857     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    858 
    859     EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
    860     if (!ctx) {
    861         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
    862     }
    863     if (!ctx->draw) {
    864         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
    865     }
    866     egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
    867     draw->setSwapInterval(interval);
    868 
    869     rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
    870 
    871     return EGL_TRUE;
    872 }
    873 
    874 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
    875 {
    876     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
    877     VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
    878 
    879     EGLint version = 1; //default
    880     while (attrib_list && attrib_list[0]) {
    881         if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
    882         attrib_list+=2;
    883     }
    884 
    885     uint32_t rcShareCtx = 0;
    886     EGLContext_t * shareCtx = NULL;
    887     if (share_context) {
    888         shareCtx = static_cast<EGLContext_t*>(share_context);
    889         rcShareCtx = shareCtx->rcContext;
    890         if (shareCtx->dpy != dpy)
    891             setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
    892     }
    893 
    894     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
    895     uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
    896     if (!rcContext) {
    897         ALOGE("rcCreateContext returned 0");
    898         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
    899     }
    900 
    901     EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
    902     if (!context)
    903         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
    904 
    905     context->version = version;
    906     context->rcContext = rcContext;
    907 
    908 
    909     return context;
    910 }
    911 
    912 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    913 {
    914     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    915     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
    916 
    917     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
    918 
    919     if (!context) return EGL_TRUE;
    920 
    921     if (getEGLThreadInfo()->currentContext == context) {
    922         getEGLThreadInfo()->currentContext->deletePending = 1;
    923         return EGL_TRUE;
    924     }
    925 
    926     if (context->rcContext) {
    927         DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    928         rcEnc->rcDestroyContext(rcEnc, context->rcContext);
    929         context->rcContext = 0;
    930     }
    931 
    932     delete context;
    933     return EGL_TRUE;
    934 }
    935 
    936 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
    937 {
    938     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
    939     VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
    940     VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
    941 
    942     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
    943         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    944     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
    945         setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
    946 
    947     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
    948     uint32_t ctxHandle = (context) ? context->rcContext : 0;
    949     egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
    950     uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
    951     egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
    952     uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
    953 
    954     //
    955     // Nothing to do if no binding change has made
    956     //
    957     EGLThreadInfo *tInfo = getEGLThreadInfo();
    958 
    959     if (tInfo->currentContext == context &&
    960         (context == NULL ||
    961         (context && context->draw == draw && context->read == read))) {
    962         return EGL_TRUE;
    963     }
    964 
    965     if (tInfo->currentContext && tInfo->currentContext->deletePending) {
    966         if (tInfo->currentContext != context) {
    967             EGLContext_t * contextToDelete = tInfo->currentContext;
    968             tInfo->currentContext = 0;
    969             eglDestroyContext(dpy, contextToDelete);
    970         }
    971     }
    972 
    973     if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
    974         //context is current to another thread
    975         setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
    976     }
    977 
    978     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
    979     if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
    980         ALOGE("rcMakeCurrent returned EGL_FALSE");
    981         setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
    982     }
    983 
    984     //Now make the local bind
    985     if (context) {
    986         context->draw = draw;
    987         context->read = read;
    988         context->flags |= EGLContext_t::IS_CURRENT;
    989         //set the client state
    990         if (context->version == 2) {
    991             hostCon->gl2Encoder()->setClientState(context->getClientState());
    992             hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
    993         }
    994         else {
    995             hostCon->glEncoder()->setClientState(context->getClientState());
    996             hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
    997         }
    998     }
    999     else if (tInfo->currentContext) {
   1000         //release ClientState & SharedGroup
   1001         if (tInfo->currentContext->version == 2) {
   1002             hostCon->gl2Encoder()->setClientState(NULL);
   1003             hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
   1004         }
   1005         else {
   1006             hostCon->glEncoder()->setClientState(NULL);
   1007             hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
   1008         }
   1009 
   1010     }
   1011 
   1012     if (tInfo->currentContext)
   1013         tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
   1014 
   1015     //Now make current
   1016     tInfo->currentContext = context;
   1017 
   1018     //Check maybe we need to init the encoder, if it's first eglMakeCurrent
   1019     if (tInfo->currentContext) {
   1020         if (tInfo->currentContext->version == 2) {
   1021             if (!hostCon->gl2Encoder()->isInitialized()) {
   1022                 s_display.gles2_iface()->init();
   1023                 hostCon->gl2Encoder()->setInitialized();
   1024                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
   1025             }
   1026         }
   1027         else {
   1028             if (!hostCon->glEncoder()->isInitialized()) {
   1029                 s_display.gles_iface()->init();
   1030                 hostCon->glEncoder()->setInitialized();
   1031                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
   1032             }
   1033         }
   1034     }
   1035 
   1036     return EGL_TRUE;
   1037 }
   1038 
   1039 EGLContext eglGetCurrentContext()
   1040 {
   1041     return getEGLThreadInfo()->currentContext;
   1042 }
   1043 
   1044 EGLSurface eglGetCurrentSurface(EGLint readdraw)
   1045 {
   1046     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1047     if (!context)
   1048         return EGL_NO_SURFACE; //not an error
   1049 
   1050     switch (readdraw) {
   1051         case EGL_READ:
   1052             return context->read;
   1053         case EGL_DRAW:
   1054             return context->draw;
   1055         default:
   1056             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1057     }
   1058 }
   1059 
   1060 EGLDisplay eglGetCurrentDisplay()
   1061 {
   1062     EGLContext_t * context = getEGLThreadInfo()->currentContext;
   1063     if (!context)
   1064         return EGL_NO_DISPLAY; //not an error
   1065 
   1066     return context->dpy;
   1067 }
   1068 
   1069 EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
   1070 {
   1071     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1072     VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
   1073 
   1074     EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
   1075 
   1076     EGLBoolean ret = EGL_TRUE;
   1077     switch (attribute) {
   1078         case EGL_CONFIG_ID:
   1079             ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value);
   1080             break;
   1081         case EGL_CONTEXT_CLIENT_TYPE:
   1082             *value = EGL_OPENGL_ES_API;
   1083             break;
   1084         case EGL_CONTEXT_CLIENT_VERSION:
   1085             *value = context->version;
   1086             break;
   1087         case EGL_RENDER_BUFFER:
   1088             if (!context->draw)
   1089                 *value = EGL_NONE;
   1090             else
   1091                 *value = EGL_BACK_BUFFER; //single buffer not supported
   1092             break;
   1093         default:
   1094             ALOGE("eglQueryContext %x  EGL_BAD_ATTRIBUTE", attribute);
   1095             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1096             break;
   1097     }
   1098 
   1099     return ret;
   1100 }
   1101 
   1102 EGLBoolean eglWaitGL()
   1103 {
   1104     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1105     if (!tInfo || !tInfo->currentContext) {
   1106         return EGL_FALSE;
   1107     }
   1108 
   1109     if (tInfo->currentContext->version == 2) {
   1110         s_display.gles2_iface()->finish();
   1111     }
   1112     else {
   1113         s_display.gles_iface()->finish();
   1114     }
   1115 
   1116     return EGL_TRUE;
   1117 }
   1118 
   1119 EGLBoolean eglWaitNative(EGLint engine)
   1120 {
   1121     (void)engine;
   1122     return EGL_TRUE;
   1123 }
   1124 
   1125 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
   1126 {
   1127     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1128     if (eglSurface == EGL_NO_SURFACE)
   1129         setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
   1130 
   1131     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
   1132 
   1133     egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
   1134     if (d->dpy != dpy)
   1135         setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
   1136 
   1137     // post the surface
   1138     d->swapBuffers();
   1139 
   1140     hostCon->flush();
   1141     return EGL_TRUE;
   1142 }
   1143 
   1144 EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
   1145 {
   1146     //TODO :later
   1147     (void)dpy;
   1148     (void)surface;
   1149     (void)target;
   1150     return 0;
   1151 }
   1152 
   1153 EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
   1154 {
   1155     //TODO later
   1156     (void)display;
   1157     (void)surface;
   1158     (void)attrib_list;
   1159     return 0;
   1160 }
   1161 
   1162 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
   1163 {
   1164     //TODO later
   1165     (void)display;
   1166     (void)surface;
   1167     return 0;
   1168 }
   1169 
   1170 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
   1171 {
   1172     (void)attrib_list;
   1173 
   1174     VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
   1175     if (ctx != EGL_NO_CONTEXT) {
   1176         setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   1177     }
   1178     if (target != EGL_NATIVE_BUFFER_ANDROID) {
   1179         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1180     }
   1181 
   1182     android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
   1183 
   1184     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   1185         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1186 
   1187     if (native_buffer->common.version != sizeof(android_native_buffer_t))
   1188         setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1189 
   1190     cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
   1191 
   1192     switch (cb->format) {
   1193         case HAL_PIXEL_FORMAT_RGBA_8888:
   1194         case HAL_PIXEL_FORMAT_RGBX_8888:
   1195         case HAL_PIXEL_FORMAT_RGB_888:
   1196         case HAL_PIXEL_FORMAT_RGB_565:
   1197         case HAL_PIXEL_FORMAT_BGRA_8888:
   1198             break;
   1199         default:
   1200             setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   1201     }
   1202 
   1203     native_buffer->common.incRef(&native_buffer->common);
   1204     return (EGLImageKHR)native_buffer;
   1205 }
   1206 
   1207 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
   1208 {
   1209     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
   1210     android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
   1211 
   1212     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   1213         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1214 
   1215     if (native_buffer->common.version != sizeof(android_native_buffer_t))
   1216         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1217 
   1218     native_buffer->common.decRef(&native_buffer->common);
   1219 
   1220     return EGL_TRUE;
   1221 }
   1222 
   1223 #define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
   1224 
   1225 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
   1226         const EGLint *attrib_list)
   1227 {
   1228     // TODO: This implementation could be faster. We should require the host EGL
   1229     // to support KHR_fence_sync, or at least pipe the fence command to the host
   1230     // and wait for it (probably involving a glFinish on the host) in
   1231     // eglClientWaitSyncKHR.
   1232 
   1233     VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
   1234 
   1235     if (type != EGL_SYNC_FENCE_KHR ||
   1236             (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
   1237         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
   1238     }
   1239 
   1240     EGLThreadInfo *tInfo = getEGLThreadInfo();
   1241     if (!tInfo || !tInfo->currentContext) {
   1242         setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   1243     }
   1244 
   1245     if (tInfo->currentContext->version == 2) {
   1246         s_display.gles2_iface()->finish();
   1247     } else {
   1248         s_display.gles_iface()->finish();
   1249     }
   1250 
   1251     return FENCE_SYNC_HANDLE;
   1252 }
   1253 
   1254 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
   1255 {
   1256     (void)dpy;
   1257 
   1258     if (sync != FENCE_SYNC_HANDLE) {
   1259         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1260     }
   1261 
   1262     return EGL_TRUE;
   1263 }
   1264 
   1265 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
   1266         EGLTimeKHR timeout)
   1267 {
   1268     (void)dpy;
   1269     (void)flags;
   1270     (void)timeout;
   1271 
   1272     if (sync != FENCE_SYNC_HANDLE) {
   1273         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1274     }
   1275 
   1276     return EGL_CONDITION_SATISFIED_KHR;
   1277 }
   1278 
   1279 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
   1280         EGLint attribute, EGLint *value)
   1281 {
   1282     (void)dpy;
   1283 
   1284     if (sync != FENCE_SYNC_HANDLE) {
   1285         setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
   1286     }
   1287 
   1288     switch (attribute) {
   1289     case EGL_SYNC_TYPE_KHR:
   1290         *value = EGL_SYNC_FENCE_KHR;
   1291         return EGL_TRUE;
   1292     case EGL_SYNC_STATUS_KHR:
   1293         *value = EGL_SIGNALED_KHR;
   1294         return EGL_TRUE;
   1295     case EGL_SYNC_CONDITION_KHR:
   1296         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
   1297         return EGL_TRUE;
   1298     default:
   1299         setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1300     }
   1301 }
   1302