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