Home | History | Annotate | Download | only in libagl
      1 /*
      2 **
      3 ** Copyright 2007 The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License Version 2.0(the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing software
     12 ** distributed under the License is distributed on an "AS IS" BASIS
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include <assert.h>
     19 #include <atomic>
     20 #include <errno.h>
     21 #include <fcntl.h>
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <sys/ioctl.h>
     26 #include <sys/types.h>
     27 #include <sys/mman.h>
     28 #include <unistd.h>
     29 
     30 #include <log/log.h>
     31 
     32 #include <utils/threads.h>
     33 #include <ui/ANativeObjectBase.h>
     34 #include <ui/Fence.h>
     35 #include <ui/GraphicBufferMapper.h>
     36 #include <ui/Rect.h>
     37 
     38 #include <EGL/egl.h>
     39 #include <EGL/eglext.h>
     40 #include <GLES/gl.h>
     41 #include <GLES/glext.h>
     42 
     43 #include <pixelflinger/format.h>
     44 #include <pixelflinger/pixelflinger.h>
     45 
     46 #include "context.h"
     47 #include "state.h"
     48 #include "texture.h"
     49 #include "matrix.h"
     50 
     51 #undef NELEM
     52 #define NELEM(x) (sizeof(x)/sizeof(*(x)))
     53 
     54 // ----------------------------------------------------------------------------
     55 
     56 EGLBoolean EGLAPI eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
     57         EGLint left, EGLint top, EGLint width, EGLint height);
     58 
     59 
     60 typedef struct egl_native_pixmap_t
     61 {
     62     int32_t     version;    /* must be 32 */
     63     int32_t     width;
     64     int32_t     height;
     65     int32_t     stride;
     66     uint8_t*    data;
     67     uint8_t     format;
     68     uint8_t     rfu[3];
     69     union {
     70         uint32_t    compressedFormat;
     71         int32_t     vstride;
     72     };
     73     int32_t     reserved;
     74 } egl_native_pixmap_t;
     75 
     76 
     77 // ----------------------------------------------------------------------------
     78 namespace android {
     79 
     80 // ----------------------------------------------------------------------------
     81 
     82 const unsigned int NUM_DISPLAYS = 1;
     83 
     84 static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
     85 static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
     86 static pthread_key_t gEGLErrorKey = -1;
     87 #ifndef __ANDROID__
     88 namespace gl {
     89 pthread_key_t gGLKey = -1;
     90 }; // namespace gl
     91 #endif
     92 
     93 template<typename T>
     94 static T setError(GLint error, T returnValue) {
     95     if (ggl_unlikely(gEGLErrorKey == -1)) {
     96         pthread_mutex_lock(&gErrorKeyMutex);
     97         if (gEGLErrorKey == -1)
     98             pthread_key_create(&gEGLErrorKey, NULL);
     99         pthread_mutex_unlock(&gErrorKeyMutex);
    100     }
    101     pthread_setspecific(gEGLErrorKey, (void*)(uintptr_t)error);
    102     return returnValue;
    103 }
    104 
    105 static GLint getError() {
    106     if (ggl_unlikely(gEGLErrorKey == -1))
    107         return EGL_SUCCESS;
    108     GLint error = (GLint)(uintptr_t)pthread_getspecific(gEGLErrorKey);
    109     if (error == 0) {
    110         // The TLS key has been created by another thread, but the value for
    111         // this thread has not been initialized.
    112         return EGL_SUCCESS;
    113     }
    114     pthread_setspecific(gEGLErrorKey, (void*)(uintptr_t)EGL_SUCCESS);
    115     return error;
    116 }
    117 
    118 // ----------------------------------------------------------------------------
    119 
    120 struct egl_display_t
    121 {
    122     egl_display_t() : type(0), initialized(0) { }
    123 
    124     static egl_display_t& get_display(EGLDisplay dpy);
    125 
    126     static EGLBoolean is_valid(EGLDisplay dpy) {
    127         return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
    128     }
    129 
    130     NativeDisplayType  type;
    131     std::atomic_size_t initialized;
    132 };
    133 
    134 static egl_display_t gDisplays[NUM_DISPLAYS];
    135 
    136 egl_display_t& egl_display_t::get_display(EGLDisplay dpy) {
    137     return gDisplays[uintptr_t(dpy)-1U];
    138 }
    139 
    140 struct egl_context_t {
    141     enum {
    142         IS_CURRENT      =   0x00010000,
    143         NEVER_CURRENT   =   0x00020000
    144     };
    145     uint32_t            flags;
    146     EGLDisplay          dpy;
    147     EGLConfig           config;
    148     EGLSurface          read;
    149     EGLSurface          draw;
    150 
    151     static inline egl_context_t* context(EGLContext ctx) {
    152         ogles_context_t* const gl = static_cast<ogles_context_t*>(ctx);
    153         return static_cast<egl_context_t*>(gl->rasterizer.base);
    154     }
    155 };
    156 
    157 // ----------------------------------------------------------------------------
    158 
    159 struct egl_surface_t
    160 {
    161     enum {
    162         PAGE_FLIP = 0x00000001,
    163         MAGIC     = 0x31415265
    164     };
    165 
    166     uint32_t            magic;
    167     EGLDisplay          dpy;
    168     EGLConfig           config;
    169     EGLContext          ctx;
    170     bool                zombie;
    171 
    172                 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
    173     virtual     ~egl_surface_t();
    174                 bool    isValid() const;
    175     virtual     bool    initCheck() const = 0;
    176 
    177     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl) = 0;
    178     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl) = 0;
    179     virtual     EGLBoolean  connect() { return EGL_TRUE; }
    180     virtual     void        disconnect() {}
    181     virtual     EGLint      getWidth() const = 0;
    182     virtual     EGLint      getHeight() const = 0;
    183 
    184     virtual     EGLint      getHorizontalResolution() const;
    185     virtual     EGLint      getVerticalResolution() const;
    186     virtual     EGLint      getRefreshRate() const;
    187     virtual     EGLint      getSwapBehavior() const;
    188     virtual     EGLBoolean  swapBuffers();
    189     virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
    190 protected:
    191     GGLSurface              depth;
    192 };
    193 
    194 egl_surface_t::egl_surface_t(EGLDisplay dpy,
    195         EGLConfig config,
    196         int32_t depthFormat)
    197     : magic(MAGIC), dpy(dpy), config(config), ctx(0), zombie(false)
    198 {
    199     depth.version = sizeof(GGLSurface);
    200     depth.data = 0;
    201     depth.format = depthFormat;
    202 }
    203 egl_surface_t::~egl_surface_t()
    204 {
    205     magic = 0;
    206     free(depth.data);
    207 }
    208 bool egl_surface_t::isValid() const {
    209     ALOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
    210     return magic == MAGIC;
    211 }
    212 
    213 EGLBoolean egl_surface_t::swapBuffers() {
    214     return EGL_FALSE;
    215 }
    216 EGLint egl_surface_t::getHorizontalResolution() const {
    217     return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
    218 }
    219 EGLint egl_surface_t::getVerticalResolution() const {
    220     return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
    221 }
    222 EGLint egl_surface_t::getRefreshRate() const {
    223     return (60 * EGL_DISPLAY_SCALING);
    224 }
    225 EGLint egl_surface_t::getSwapBehavior() const {
    226     return EGL_BUFFER_PRESERVED;
    227 }
    228 EGLBoolean egl_surface_t::setSwapRectangle(
    229         EGLint /*l*/, EGLint /*t*/, EGLint /*w*/, EGLint /*h*/)
    230 {
    231     return EGL_FALSE;
    232 }
    233 
    234 // ----------------------------------------------------------------------------
    235 
    236 struct egl_window_surface_v2_t : public egl_surface_t
    237 {
    238     egl_window_surface_v2_t(
    239             EGLDisplay dpy, EGLConfig config,
    240             int32_t depthFormat,
    241             ANativeWindow* window);
    242 
    243     ~egl_window_surface_v2_t();
    244 
    245     virtual     bool        initCheck() const { return true; } // TODO: report failure if ctor fails
    246     virtual     EGLBoolean  swapBuffers();
    247     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
    248     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
    249     virtual     EGLBoolean  connect();
    250     virtual     void        disconnect();
    251     virtual     EGLint      getWidth() const    { return width;  }
    252     virtual     EGLint      getHeight() const   { return height; }
    253     virtual     EGLint      getHorizontalResolution() const;
    254     virtual     EGLint      getVerticalResolution() const;
    255     virtual     EGLint      getRefreshRate() const;
    256     virtual     EGLint      getSwapBehavior() const;
    257     virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
    258 
    259 private:
    260     status_t lock(ANativeWindowBuffer* buf, int usage, void** vaddr);
    261     status_t unlock(ANativeWindowBuffer* buf);
    262     ANativeWindow*   nativeWindow;
    263     ANativeWindowBuffer*   buffer;
    264     ANativeWindowBuffer*   previousBuffer;
    265     int width;
    266     int height;
    267     void* bits;
    268     GGLFormat const* pixelFormatTable;
    269 
    270     struct Rect {
    271         inline Rect() { };
    272         inline Rect(int32_t w, int32_t h)
    273             : left(0), top(0), right(w), bottom(h) { }
    274         inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
    275             : left(l), top(t), right(r), bottom(b) { }
    276         Rect& andSelf(const Rect& r) {
    277             left   = max(left, r.left);
    278             top    = max(top, r.top);
    279             right  = min(right, r.right);
    280             bottom = min(bottom, r.bottom);
    281             return *this;
    282         }
    283         bool isEmpty() const {
    284             return (left>=right || top>=bottom);
    285         }
    286         void dump(char const* what) {
    287             ALOGD("%s { %5d, %5d, w=%5d, h=%5d }",
    288                     what, left, top, right-left, bottom-top);
    289         }
    290 
    291         int32_t left;
    292         int32_t top;
    293         int32_t right;
    294         int32_t bottom;
    295     };
    296 
    297     struct Region {
    298         inline Region() : count(0) { }
    299         typedef Rect const* const_iterator;
    300         const_iterator begin() const { return storage; }
    301         const_iterator end() const { return storage+count; }
    302         static Region subtract(const Rect& lhs, const Rect& rhs) {
    303             Region reg;
    304             Rect* storage = reg.storage;
    305             if (!lhs.isEmpty()) {
    306                 if (lhs.top < rhs.top) { // top rect
    307                     storage->left   = lhs.left;
    308                     storage->top    = lhs.top;
    309                     storage->right  = lhs.right;
    310                     storage->bottom = rhs.top;
    311                     storage++;
    312                 }
    313                 const int32_t top = max(lhs.top, rhs.top);
    314                 const int32_t bot = min(lhs.bottom, rhs.bottom);
    315                 if (top < bot) {
    316                     if (lhs.left < rhs.left) { // left-side rect
    317                         storage->left   = lhs.left;
    318                         storage->top    = top;
    319                         storage->right  = rhs.left;
    320                         storage->bottom = bot;
    321                         storage++;
    322                     }
    323                     if (lhs.right > rhs.right) { // right-side rect
    324                         storage->left   = rhs.right;
    325                         storage->top    = top;
    326                         storage->right  = lhs.right;
    327                         storage->bottom = bot;
    328                         storage++;
    329                     }
    330                 }
    331                 if (lhs.bottom > rhs.bottom) { // bottom rect
    332                     storage->left   = lhs.left;
    333                     storage->top    = rhs.bottom;
    334                     storage->right  = lhs.right;
    335                     storage->bottom = lhs.bottom;
    336                     storage++;
    337                 }
    338                 reg.count = storage - reg.storage;
    339             }
    340             return reg;
    341         }
    342         bool isEmpty() const {
    343             return count<=0;
    344         }
    345     private:
    346         Rect storage[4];
    347         ssize_t count;
    348     };
    349 
    350     void copyBlt(
    351             ANativeWindowBuffer* dst, void* dst_vaddr,
    352             ANativeWindowBuffer* src, void const* src_vaddr,
    353             const Region& clip);
    354 
    355     Rect dirtyRegion;
    356     Rect oldDirtyRegion;
    357 };
    358 
    359 egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
    360         EGLConfig config,
    361         int32_t depthFormat,
    362         ANativeWindow* window)
    363     : egl_surface_t(dpy, config, depthFormat),
    364     nativeWindow(window), buffer(0), previousBuffer(0), bits(NULL)
    365 {
    366 
    367     pixelFormatTable = gglGetPixelFormatTable();
    368 
    369     // keep a reference on the window
    370     nativeWindow->common.incRef(&nativeWindow->common);
    371     nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
    372     nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
    373 }
    374 
    375 egl_window_surface_v2_t::~egl_window_surface_v2_t() {
    376     if (buffer) {
    377         buffer->common.decRef(&buffer->common);
    378     }
    379     if (previousBuffer) {
    380         previousBuffer->common.decRef(&previousBuffer->common);
    381     }
    382     nativeWindow->common.decRef(&nativeWindow->common);
    383 }
    384 
    385 EGLBoolean egl_window_surface_v2_t::connect()
    386 {
    387     // we're intending to do software rendering
    388     native_window_set_usage(nativeWindow,
    389             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
    390 
    391     // dequeue a buffer
    392     int fenceFd = -1;
    393     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer,
    394             &fenceFd) != NO_ERROR) {
    395         return setError(EGL_BAD_ALLOC, EGL_FALSE);
    396     }
    397 
    398     // wait for the buffer
    399     sp<Fence> fence(new Fence(fenceFd));
    400     if (fence->wait(Fence::TIMEOUT_NEVER) != NO_ERROR) {
    401         nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd);
    402         return setError(EGL_BAD_ALLOC, EGL_FALSE);
    403     }
    404 
    405     // allocate a corresponding depth-buffer
    406     width = buffer->width;
    407     height = buffer->height;
    408     if (depth.format) {
    409         depth.width   = width;
    410         depth.height  = height;
    411         depth.stride  = depth.width; // use the width here
    412         uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
    413                 static_cast<uint64_t>(depth.height) * 2;
    414         if (depth.stride < 0 || depth.height > INT_MAX ||
    415                 allocSize > UINT32_MAX) {
    416             return setError(EGL_BAD_ALLOC, EGL_FALSE);
    417         }
    418         depth.data    = (GGLubyte*)malloc(allocSize);
    419         if (depth.data == 0) {
    420             return setError(EGL_BAD_ALLOC, EGL_FALSE);
    421         }
    422     }
    423 
    424     // keep a reference on the buffer
    425     buffer->common.incRef(&buffer->common);
    426 
    427     // pin the buffer down
    428     if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
    429             GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
    430         ALOGE("connect() failed to lock buffer %p (%ux%u)",
    431                 buffer, buffer->width, buffer->height);
    432         return setError(EGL_BAD_ACCESS, EGL_FALSE);
    433         // FIXME: we should make sure we're not accessing the buffer anymore
    434     }
    435     return EGL_TRUE;
    436 }
    437 
    438 void egl_window_surface_v2_t::disconnect()
    439 {
    440     if (buffer && bits) {
    441         bits = NULL;
    442         unlock(buffer);
    443     }
    444     if (buffer) {
    445         nativeWindow->cancelBuffer(nativeWindow, buffer, -1);
    446         buffer->common.decRef(&buffer->common);
    447         buffer = 0;
    448     }
    449     if (previousBuffer) {
    450         previousBuffer->common.decRef(&previousBuffer->common);
    451         previousBuffer = 0;
    452     }
    453 }
    454 
    455 status_t egl_window_surface_v2_t::lock(
    456         ANativeWindowBuffer* buf, int usage, void** vaddr)
    457 {
    458     auto& mapper = GraphicBufferMapper::get();
    459     return mapper.lock(buf->handle, usage,
    460             android::Rect(buf->width, buf->height), vaddr);
    461 }
    462 
    463 status_t egl_window_surface_v2_t::unlock(ANativeWindowBuffer* buf)
    464 {
    465     if (!buf) return BAD_VALUE;
    466     auto& mapper = GraphicBufferMapper::get();
    467     return mapper.unlock(buf->handle);
    468 }
    469 
    470 void egl_window_surface_v2_t::copyBlt(
    471         ANativeWindowBuffer* dst, void* dst_vaddr,
    472         ANativeWindowBuffer* src, void const* src_vaddr,
    473         const Region& clip)
    474 {
    475     // NOTE: dst and src must be the same format
    476 
    477     Region::const_iterator cur = clip.begin();
    478     Region::const_iterator end = clip.end();
    479 
    480     const size_t bpp = pixelFormatTable[src->format].size;
    481     const size_t dbpr = dst->stride * bpp;
    482     const size_t sbpr = src->stride * bpp;
    483 
    484     uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
    485     uint8_t       * const dst_bits = (uint8_t       *)dst_vaddr;
    486 
    487     while (cur != end) {
    488         const Rect& r(*cur++);
    489         ssize_t w = r.right - r.left;
    490         ssize_t h = r.bottom - r.top;
    491         if (w <= 0 || h<=0) continue;
    492         size_t size = w * bpp;
    493         uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
    494         uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
    495         if (dbpr==sbpr && size==sbpr) {
    496             size *= h;
    497             h = 1;
    498         }
    499         do {
    500             memcpy(d, s, size);
    501             d += dbpr;
    502             s += sbpr;
    503         } while (--h > 0);
    504     }
    505 }
    506 
    507 EGLBoolean egl_window_surface_v2_t::swapBuffers()
    508 {
    509     if (!buffer) {
    510         return setError(EGL_BAD_ACCESS, EGL_FALSE);
    511     }
    512 
    513     /*
    514      * Handle eglSetSwapRectangleANDROID()
    515      * We copyback from the front buffer
    516      */
    517     if (!dirtyRegion.isEmpty()) {
    518         dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
    519         if (previousBuffer) {
    520             // This was const Region copyBack, but that causes an
    521             // internal compile error on simulator builds
    522             /*const*/ Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
    523             if (!copyBack.isEmpty()) {
    524                 void* prevBits;
    525                 if (lock(previousBuffer,
    526                         GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
    527                     // copy from previousBuffer to buffer
    528                     copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
    529                     unlock(previousBuffer);
    530                 }
    531             }
    532         }
    533         oldDirtyRegion = dirtyRegion;
    534     }
    535 
    536     if (previousBuffer) {
    537         previousBuffer->common.decRef(&previousBuffer->common);
    538         previousBuffer = 0;
    539     }
    540 
    541     unlock(buffer);
    542     previousBuffer = buffer;
    543     nativeWindow->queueBuffer(nativeWindow, buffer, -1);
    544     buffer = 0;
    545 
    546     // dequeue a new buffer
    547     int fenceFd = -1;
    548     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &fenceFd) == NO_ERROR) {
    549         sp<Fence> fence(new Fence(fenceFd));
    550         if (fence->wait(Fence::TIMEOUT_NEVER)) {
    551             nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd);
    552             return setError(EGL_BAD_ALLOC, EGL_FALSE);
    553         }
    554 
    555         // reallocate the depth-buffer if needed
    556         if ((width != buffer->width) || (height != buffer->height)) {
    557             // TODO: we probably should reset the swap rect here
    558             // if the window size has changed
    559             width = buffer->width;
    560             height = buffer->height;
    561             if (depth.data) {
    562                 free(depth.data);
    563                 depth.width   = width;
    564                 depth.height  = height;
    565                 depth.stride  = buffer->stride;
    566                 uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
    567                         static_cast<uint64_t>(depth.height) * 2;
    568                 if (depth.stride < 0 || depth.height > INT_MAX ||
    569                         allocSize > UINT32_MAX) {
    570                     setError(EGL_BAD_ALLOC, EGL_FALSE);
    571                     return EGL_FALSE;
    572                 }
    573                 depth.data    = (GGLubyte*)malloc(allocSize);
    574                 if (depth.data == 0) {
    575                     setError(EGL_BAD_ALLOC, EGL_FALSE);
    576                     return EGL_FALSE;
    577                 }
    578             }
    579         }
    580 
    581         // keep a reference on the buffer
    582         buffer->common.incRef(&buffer->common);
    583 
    584         // finally pin the buffer down
    585         if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
    586                 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
    587             ALOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
    588                     buffer, buffer->width, buffer->height);
    589             return setError(EGL_BAD_ACCESS, EGL_FALSE);
    590             // FIXME: we should make sure we're not accessing the buffer anymore
    591         }
    592     } else {
    593         return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
    594     }
    595 
    596     return EGL_TRUE;
    597 }
    598 
    599 EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
    600         EGLint l, EGLint t, EGLint w, EGLint h)
    601 {
    602     dirtyRegion = Rect(l, t, l+w, t+h);
    603     return EGL_TRUE;
    604 }
    605 
    606 EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
    607 {
    608     GGLSurface buffer;
    609     buffer.version = sizeof(GGLSurface);
    610     buffer.width   = this->buffer->width;
    611     buffer.height  = this->buffer->height;
    612     buffer.stride  = this->buffer->stride;
    613     buffer.data    = (GGLubyte*)bits;
    614     buffer.format  = this->buffer->format;
    615     gl->rasterizer.procs.colorBuffer(gl, &buffer);
    616     if (depth.data != gl->rasterizer.state.buffers.depth.data)
    617         gl->rasterizer.procs.depthBuffer(gl, &depth);
    618 
    619     return EGL_TRUE;
    620 }
    621 EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
    622 {
    623     GGLSurface buffer;
    624     buffer.version = sizeof(GGLSurface);
    625     buffer.width   = this->buffer->width;
    626     buffer.height  = this->buffer->height;
    627     buffer.stride  = this->buffer->stride;
    628     buffer.data    = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
    629     buffer.format  = this->buffer->format;
    630     gl->rasterizer.procs.readBuffer(gl, &buffer);
    631     return EGL_TRUE;
    632 }
    633 EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
    634     return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
    635 }
    636 EGLint egl_window_surface_v2_t::getVerticalResolution() const {
    637     return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
    638 }
    639 EGLint egl_window_surface_v2_t::getRefreshRate() const {
    640     return (60 * EGL_DISPLAY_SCALING); // FIXME
    641 }
    642 EGLint egl_window_surface_v2_t::getSwapBehavior() const
    643 {
    644     /*
    645      * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
    646      * the content of the swapped buffer.
    647      *
    648      * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
    649      *
    650      * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
    651      * only applies to the area specified by eglSetSwapRectangleANDROID(), that
    652      * is, everything outside of this area is preserved.
    653      *
    654      * This implementation of EGL assumes the later case.
    655      *
    656      */
    657 
    658     return EGL_BUFFER_DESTROYED;
    659 }
    660 
    661 // ----------------------------------------------------------------------------
    662 
    663 struct egl_pixmap_surface_t : public egl_surface_t
    664 {
    665     egl_pixmap_surface_t(
    666             EGLDisplay dpy, EGLConfig config,
    667             int32_t depthFormat,
    668             egl_native_pixmap_t const * pixmap);
    669 
    670     virtual ~egl_pixmap_surface_t() { }
    671 
    672     virtual     bool        initCheck() const { return !depth.format || depth.data!=0; }
    673     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
    674     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
    675     virtual     EGLint      getWidth() const    { return nativePixmap.width;  }
    676     virtual     EGLint      getHeight() const   { return nativePixmap.height; }
    677 private:
    678     egl_native_pixmap_t     nativePixmap;
    679 };
    680 
    681 egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
    682         EGLConfig config,
    683         int32_t depthFormat,
    684         egl_native_pixmap_t const * pixmap)
    685     : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
    686 {
    687     if (depthFormat) {
    688         depth.width   = pixmap->width;
    689         depth.height  = pixmap->height;
    690         depth.stride  = depth.width; // use the width here
    691         uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
    692                 static_cast<uint64_t>(depth.height) * 2;
    693         if (depth.stride < 0 || depth.height > INT_MAX ||
    694                 allocSize > UINT32_MAX) {
    695             setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    696             return;
    697         }
    698         depth.data    = (GGLubyte*)malloc(allocSize);
    699         if (depth.data == 0) {
    700             setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    701         }
    702     }
    703 }
    704 EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl)
    705 {
    706     GGLSurface buffer;
    707     buffer.version = sizeof(GGLSurface);
    708     buffer.width   = nativePixmap.width;
    709     buffer.height  = nativePixmap.height;
    710     buffer.stride  = nativePixmap.stride;
    711     buffer.data    = nativePixmap.data;
    712     buffer.format  = nativePixmap.format;
    713 
    714     gl->rasterizer.procs.colorBuffer(gl, &buffer);
    715     if (depth.data != gl->rasterizer.state.buffers.depth.data)
    716         gl->rasterizer.procs.depthBuffer(gl, &depth);
    717     return EGL_TRUE;
    718 }
    719 EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl)
    720 {
    721     GGLSurface buffer;
    722     buffer.version = sizeof(GGLSurface);
    723     buffer.width   = nativePixmap.width;
    724     buffer.height  = nativePixmap.height;
    725     buffer.stride  = nativePixmap.stride;
    726     buffer.data    = nativePixmap.data;
    727     buffer.format  = nativePixmap.format;
    728     gl->rasterizer.procs.readBuffer(gl, &buffer);
    729     return EGL_TRUE;
    730 }
    731 
    732 // ----------------------------------------------------------------------------
    733 
    734 struct egl_pbuffer_surface_t : public egl_surface_t
    735 {
    736     egl_pbuffer_surface_t(
    737             EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
    738             int32_t w, int32_t h, int32_t f);
    739 
    740     virtual ~egl_pbuffer_surface_t();
    741 
    742     virtual     bool        initCheck() const   { return pbuffer.data != 0; }
    743     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
    744     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
    745     virtual     EGLint      getWidth() const    { return pbuffer.width;  }
    746     virtual     EGLint      getHeight() const   { return pbuffer.height; }
    747 private:
    748     GGLSurface  pbuffer;
    749 };
    750 
    751 egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
    752         EGLConfig config, int32_t depthFormat,
    753         int32_t w, int32_t h, int32_t f)
    754     : egl_surface_t(dpy, config, depthFormat)
    755 {
    756     size_t size = w*h;
    757     switch (f) {
    758         case GGL_PIXEL_FORMAT_A_8:          size *= 1; break;
    759         case GGL_PIXEL_FORMAT_RGB_565:      size *= 2; break;
    760         case GGL_PIXEL_FORMAT_RGBA_8888:    size *= 4; break;
    761         case GGL_PIXEL_FORMAT_RGBX_8888:    size *= 4; break;
    762         case GGL_PIXEL_FORMAT_BGRA_8888:    size *= 4; break;
    763         default:
    764             ALOGE("incompatible pixel format for pbuffer (format=%d)", f);
    765             pbuffer.data = 0;
    766             break;
    767     }
    768     pbuffer.version = sizeof(GGLSurface);
    769     pbuffer.width   = w;
    770     pbuffer.height  = h;
    771     pbuffer.stride  = w;
    772     pbuffer.data    = (GGLubyte*)malloc(size);
    773     pbuffer.format  = f;
    774 
    775     if (depthFormat) {
    776         depth.width   = pbuffer.width;
    777         depth.height  = pbuffer.height;
    778         depth.stride  = depth.width; // use the width here
    779         uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
    780                 static_cast<uint64_t>(depth.height) * 2;
    781         if (depth.stride < 0 || depth.height > INT_MAX ||
    782                 allocSize > UINT32_MAX) {
    783             setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    784             return;
    785         }
    786         depth.data    = (GGLubyte*)malloc(allocSize);
    787         if (depth.data == 0) {
    788             setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
    789             return;
    790         }
    791     }
    792 }
    793 egl_pbuffer_surface_t::~egl_pbuffer_surface_t() {
    794     free(pbuffer.data);
    795 }
    796 EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl)
    797 {
    798     gl->rasterizer.procs.colorBuffer(gl, &pbuffer);
    799     if (depth.data != gl->rasterizer.state.buffers.depth.data)
    800         gl->rasterizer.procs.depthBuffer(gl, &depth);
    801     return EGL_TRUE;
    802 }
    803 EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl)
    804 {
    805     gl->rasterizer.procs.readBuffer(gl, &pbuffer);
    806     return EGL_TRUE;
    807 }
    808 
    809 // ----------------------------------------------------------------------------
    810 
    811 struct config_pair_t {
    812     GLint key;
    813     GLint value;
    814 };
    815 
    816 struct configs_t {
    817     const config_pair_t* array;
    818     int                  size;
    819 };
    820 
    821 struct config_management_t {
    822     GLint key;
    823     bool (*match)(GLint reqValue, GLint confValue);
    824     static bool atLeast(GLint reqValue, GLint confValue) {
    825         return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
    826     }
    827     static bool exact(GLint reqValue, GLint confValue) {
    828         return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
    829     }
    830     static bool mask(GLint reqValue, GLint confValue) {
    831         return (confValue & reqValue) == reqValue;
    832     }
    833     static bool ignore(GLint /*reqValue*/, GLint /*confValue*/) {
    834         return true;
    835     }
    836 };
    837 
    838 // ----------------------------------------------------------------------------
    839 
    840 #define VERSION_MAJOR 1
    841 #define VERSION_MINOR 2
    842 static char const * const gVendorString     = "Google Inc.";
    843 static char const * const gVersionString    = "1.2 Android Driver 1.2.0";
    844 static char const * const gClientApiString  = "OpenGL_ES";
    845 static char const * const gExtensionsString =
    846         "EGL_KHR_fence_sync "
    847         "EGL_KHR_image_base "
    848         // "KHR_image_pixmap "
    849         "EGL_ANDROID_image_native_buffer "
    850         "EGL_ANDROID_swap_rectangle "
    851         ;
    852 
    853 // ----------------------------------------------------------------------------
    854 
    855 struct extention_map_t {
    856     const char * const name;
    857     __eglMustCastToProperFunctionPointerType address;
    858 };
    859 
    860 static const extention_map_t gExtentionMap[] = {
    861     { "glDrawTexsOES",
    862             (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
    863     { "glDrawTexiOES",
    864             (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
    865     { "glDrawTexfOES",
    866             (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
    867     { "glDrawTexxOES",
    868             (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
    869     { "glDrawTexsvOES",
    870             (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
    871     { "glDrawTexivOES",
    872             (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
    873     { "glDrawTexfvOES",
    874             (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
    875     { "glDrawTexxvOES",
    876             (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
    877     { "glQueryMatrixxOES",
    878             (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
    879     { "glEGLImageTargetTexture2DOES",
    880             (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
    881     { "glEGLImageTargetRenderbufferStorageOES",
    882             (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
    883     { "glClipPlanef",
    884             (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
    885     { "glClipPlanex",
    886             (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
    887     { "glBindBuffer",
    888             (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
    889     { "glBufferData",
    890             (__eglMustCastToProperFunctionPointerType)&glBufferData },
    891     { "glBufferSubData",
    892             (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
    893     { "glDeleteBuffers",
    894             (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
    895     { "glGenBuffers",
    896             (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
    897     { "eglCreateImageKHR",
    898             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
    899     { "eglDestroyImageKHR",
    900             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
    901     { "eglCreateSyncKHR",
    902             (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
    903     { "eglDestroySyncKHR",
    904             (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
    905     { "eglClientWaitSyncKHR",
    906             (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
    907     { "eglGetSyncAttribKHR",
    908             (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
    909     { "eglSetSwapRectangleANDROID",
    910             (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
    911 };
    912 
    913 /*
    914  * In the lists below, attributes names MUST be sorted.
    915  * Additionally, all configs must be sorted according to
    916  * the EGL specification.
    917  */
    918 
    919 static config_pair_t const config_base_attribute_list[] = {
    920         { EGL_STENCIL_SIZE,               0                                 },
    921         { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
    922         { EGL_LEVEL,                      0                                 },
    923         { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
    924         { EGL_MAX_PBUFFER_PIXELS,
    925                 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
    926         { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
    927         { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
    928         { EGL_NATIVE_VISUAL_ID,           0                                 },
    929         { EGL_NATIVE_VISUAL_TYPE,         GGL_PIXEL_FORMAT_RGB_565          },
    930         { EGL_SAMPLES,                    0                                 },
    931         { EGL_SAMPLE_BUFFERS,             0                                 },
    932         { EGL_TRANSPARENT_TYPE,           EGL_NONE                          },
    933         { EGL_TRANSPARENT_BLUE_VALUE,     0                                 },
    934         { EGL_TRANSPARENT_GREEN_VALUE,    0                                 },
    935         { EGL_TRANSPARENT_RED_VALUE,      0                                 },
    936         { EGL_BIND_TO_TEXTURE_RGBA,       EGL_FALSE                         },
    937         { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
    938         { EGL_MIN_SWAP_INTERVAL,          1                                 },
    939         { EGL_MAX_SWAP_INTERVAL,          1                                 },
    940         { EGL_LUMINANCE_SIZE,             0                                 },
    941         { EGL_ALPHA_MASK_SIZE,            0                                 },
    942         { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
    943         { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES_BIT                 },
    944         { EGL_CONFORMANT,                 0                                 }
    945 };
    946 
    947 // These configs can override the base attribute list
    948 // NOTE: when adding a config here, don't forget to update eglCreate*Surface()
    949 
    950 // 565 configs
    951 static config_pair_t const config_0_attribute_list[] = {
    952         { EGL_BUFFER_SIZE,     16 },
    953         { EGL_ALPHA_SIZE,       0 },
    954         { EGL_BLUE_SIZE,        5 },
    955         { EGL_GREEN_SIZE,       6 },
    956         { EGL_RED_SIZE,         5 },
    957         { EGL_DEPTH_SIZE,       0 },
    958         { EGL_CONFIG_ID,        0 },
    959         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
    960         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    961 };
    962 
    963 static config_pair_t const config_1_attribute_list[] = {
    964         { EGL_BUFFER_SIZE,     16 },
    965         { EGL_ALPHA_SIZE,       0 },
    966         { EGL_BLUE_SIZE,        5 },
    967         { EGL_GREEN_SIZE,       6 },
    968         { EGL_RED_SIZE,         5 },
    969         { EGL_DEPTH_SIZE,      16 },
    970         { EGL_CONFIG_ID,        1 },
    971         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
    972         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    973 };
    974 
    975 // RGB 888 configs
    976 static config_pair_t const config_2_attribute_list[] = {
    977         { EGL_BUFFER_SIZE,     32 },
    978         { EGL_ALPHA_SIZE,       0 },
    979         { EGL_BLUE_SIZE,        8 },
    980         { EGL_GREEN_SIZE,       8 },
    981         { EGL_RED_SIZE,         8 },
    982         { EGL_DEPTH_SIZE,       0 },
    983         { EGL_CONFIG_ID,        6 },
    984         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
    985         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    986 };
    987 
    988 static config_pair_t const config_3_attribute_list[] = {
    989         { EGL_BUFFER_SIZE,     32 },
    990         { EGL_ALPHA_SIZE,       0 },
    991         { EGL_BLUE_SIZE,        8 },
    992         { EGL_GREEN_SIZE,       8 },
    993         { EGL_RED_SIZE,         8 },
    994         { EGL_DEPTH_SIZE,      16 },
    995         { EGL_CONFIG_ID,        7 },
    996         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
    997         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    998 };
    999 
   1000 // 8888 configs
   1001 static config_pair_t const config_4_attribute_list[] = {
   1002         { EGL_BUFFER_SIZE,     32 },
   1003         { EGL_ALPHA_SIZE,       8 },
   1004         { EGL_BLUE_SIZE,        8 },
   1005         { EGL_GREEN_SIZE,       8 },
   1006         { EGL_RED_SIZE,         8 },
   1007         { EGL_DEPTH_SIZE,       0 },
   1008         { EGL_CONFIG_ID,        2 },
   1009         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
   1010         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
   1011 };
   1012 
   1013 static config_pair_t const config_5_attribute_list[] = {
   1014         { EGL_BUFFER_SIZE,     32 },
   1015         { EGL_ALPHA_SIZE,       8 },
   1016         { EGL_BLUE_SIZE,        8 },
   1017         { EGL_GREEN_SIZE,       8 },
   1018         { EGL_RED_SIZE,         8 },
   1019         { EGL_DEPTH_SIZE,      16 },
   1020         { EGL_CONFIG_ID,        3 },
   1021         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
   1022         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
   1023 };
   1024 
   1025 // A8 configs
   1026 static config_pair_t const config_6_attribute_list[] = {
   1027         { EGL_BUFFER_SIZE,      8 },
   1028         { EGL_ALPHA_SIZE,       8 },
   1029         { EGL_BLUE_SIZE,        0 },
   1030         { EGL_GREEN_SIZE,       0 },
   1031         { EGL_RED_SIZE,         0 },
   1032         { EGL_DEPTH_SIZE,       0 },
   1033         { EGL_CONFIG_ID,        4 },
   1034         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
   1035         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
   1036 };
   1037 
   1038 static config_pair_t const config_7_attribute_list[] = {
   1039         { EGL_BUFFER_SIZE,      8 },
   1040         { EGL_ALPHA_SIZE,       8 },
   1041         { EGL_BLUE_SIZE,        0 },
   1042         { EGL_GREEN_SIZE,       0 },
   1043         { EGL_RED_SIZE,         0 },
   1044         { EGL_DEPTH_SIZE,      16 },
   1045         { EGL_CONFIG_ID,        5 },
   1046         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
   1047         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
   1048 };
   1049 
   1050 // BGRA 8888 config
   1051 static config_pair_t const config_8_attribute_list[] = {
   1052         { EGL_BUFFER_SIZE,     32 },
   1053         { EGL_ALPHA_SIZE,       8 },
   1054         { EGL_BLUE_SIZE,        8 },
   1055         { EGL_GREEN_SIZE,       8 },
   1056         { EGL_RED_SIZE,         8 },
   1057         { EGL_DEPTH_SIZE,       0 },
   1058         { EGL_CONFIG_ID,        8 },
   1059         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_BGRA_8888 },
   1060         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
   1061 };
   1062 
   1063 static configs_t const gConfigs[] = {
   1064         { config_0_attribute_list, NELEM(config_0_attribute_list) },
   1065         { config_1_attribute_list, NELEM(config_1_attribute_list) },
   1066         { config_2_attribute_list, NELEM(config_2_attribute_list) },
   1067         { config_3_attribute_list, NELEM(config_3_attribute_list) },
   1068         { config_4_attribute_list, NELEM(config_4_attribute_list) },
   1069         { config_5_attribute_list, NELEM(config_5_attribute_list) },
   1070         { config_6_attribute_list, NELEM(config_6_attribute_list) },
   1071         { config_7_attribute_list, NELEM(config_7_attribute_list) },
   1072         { config_8_attribute_list, NELEM(config_8_attribute_list) },
   1073 };
   1074 
   1075 static config_management_t const gConfigManagement[] = {
   1076         { EGL_BUFFER_SIZE,                config_management_t::atLeast },
   1077         { EGL_ALPHA_SIZE,                 config_management_t::atLeast },
   1078         { EGL_BLUE_SIZE,                  config_management_t::atLeast },
   1079         { EGL_GREEN_SIZE,                 config_management_t::atLeast },
   1080         { EGL_RED_SIZE,                   config_management_t::atLeast },
   1081         { EGL_DEPTH_SIZE,                 config_management_t::atLeast },
   1082         { EGL_STENCIL_SIZE,               config_management_t::atLeast },
   1083         { EGL_CONFIG_CAVEAT,              config_management_t::exact   },
   1084         { EGL_CONFIG_ID,                  config_management_t::exact   },
   1085         { EGL_LEVEL,                      config_management_t::exact   },
   1086         { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::ignore   },
   1087         { EGL_MAX_PBUFFER_PIXELS,         config_management_t::ignore   },
   1088         { EGL_MAX_PBUFFER_WIDTH,          config_management_t::ignore   },
   1089         { EGL_NATIVE_RENDERABLE,          config_management_t::exact   },
   1090         { EGL_NATIVE_VISUAL_ID,           config_management_t::ignore   },
   1091         { EGL_NATIVE_VISUAL_TYPE,         config_management_t::exact   },
   1092         { EGL_SAMPLES,                    config_management_t::exact   },
   1093         { EGL_SAMPLE_BUFFERS,             config_management_t::exact   },
   1094         { EGL_SURFACE_TYPE,               config_management_t::mask    },
   1095         { EGL_TRANSPARENT_TYPE,           config_management_t::exact   },
   1096         { EGL_TRANSPARENT_BLUE_VALUE,     config_management_t::exact   },
   1097         { EGL_TRANSPARENT_GREEN_VALUE,    config_management_t::exact   },
   1098         { EGL_TRANSPARENT_RED_VALUE,      config_management_t::exact   },
   1099         { EGL_BIND_TO_TEXTURE_RGBA,       config_management_t::exact   },
   1100         { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
   1101         { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
   1102         { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
   1103         { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
   1104         { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
   1105         { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
   1106         { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
   1107         { EGL_CONFORMANT,                 config_management_t::mask    }
   1108 };
   1109 
   1110 
   1111 static config_pair_t const config_defaults[] = {
   1112     // attributes that are not specified are simply ignored, if a particular
   1113     // one needs not be ignored, it must be specified here, eg:
   1114     // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
   1115 };
   1116 
   1117 // ----------------------------------------------------------------------------
   1118 
   1119 static status_t getConfigFormatInfo(EGLint configID,
   1120         int32_t& pixelFormat, int32_t& depthFormat)
   1121 {
   1122     switch(configID) {
   1123     case 0:
   1124         pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
   1125         depthFormat = 0;
   1126         break;
   1127     case 1:
   1128         pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
   1129         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1130         break;
   1131     case 2:
   1132         pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
   1133         depthFormat = 0;
   1134         break;
   1135     case 3:
   1136         pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
   1137         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1138         break;
   1139     case 4:
   1140         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
   1141         depthFormat = 0;
   1142         break;
   1143     case 5:
   1144         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
   1145         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1146         break;
   1147     case 6:
   1148         pixelFormat = GGL_PIXEL_FORMAT_A_8;
   1149         depthFormat = 0;
   1150         break;
   1151     case 7:
   1152         pixelFormat = GGL_PIXEL_FORMAT_A_8;
   1153         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1154         break;
   1155     case 8:
   1156         pixelFormat = GGL_PIXEL_FORMAT_BGRA_8888;
   1157         depthFormat = 0;
   1158         break;
   1159     default:
   1160         return NAME_NOT_FOUND;
   1161     }
   1162     return NO_ERROR;
   1163 }
   1164 
   1165 // ----------------------------------------------------------------------------
   1166 
   1167 template<typename T>
   1168 static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
   1169 {
   1170    while (first <= last) {
   1171        int mid = (first + last) / 2;
   1172        if (key > sortedArray[mid].key) {
   1173            first = mid + 1;
   1174        } else if (key < sortedArray[mid].key) {
   1175            last = mid - 1;
   1176        } else {
   1177            return mid;
   1178        }
   1179    }
   1180    return -1;
   1181 }
   1182 
   1183 static int isAttributeMatching(int i, EGLint attr, EGLint val)
   1184 {
   1185     // look for the attribute in all of our configs
   1186     config_pair_t const* configFound = gConfigs[i].array;
   1187     int index = binarySearch<config_pair_t>(
   1188             gConfigs[i].array,
   1189             0, gConfigs[i].size-1,
   1190             attr);
   1191     if (index < 0) {
   1192         configFound = config_base_attribute_list;
   1193         index = binarySearch<config_pair_t>(
   1194                 config_base_attribute_list,
   1195                 0, NELEM(config_base_attribute_list)-1,
   1196                 attr);
   1197     }
   1198     if (index >= 0) {
   1199         // attribute found, check if this config could match
   1200         int cfgMgtIndex = binarySearch<config_management_t>(
   1201                 gConfigManagement,
   1202                 0, NELEM(gConfigManagement)-1,
   1203                 attr);
   1204         if (cfgMgtIndex >= 0) {
   1205             bool match = gConfigManagement[cfgMgtIndex].match(
   1206                     val, configFound[index].value);
   1207             if (match) {
   1208                 // this config matches
   1209                 return 1;
   1210             }
   1211         } else {
   1212             // attribute not found. this should NEVER happen.
   1213         }
   1214     } else {
   1215         // error, this attribute doesn't exist
   1216     }
   1217     return 0;
   1218 }
   1219 
   1220 static int makeCurrent(ogles_context_t* gl)
   1221 {
   1222     ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific();
   1223     if (gl) {
   1224         egl_context_t* c = egl_context_t::context(gl);
   1225         if (c->flags & egl_context_t::IS_CURRENT) {
   1226             if (current != gl) {
   1227                 // it is an error to set a context current, if it's already
   1228                 // current to another thread
   1229                 return -1;
   1230             }
   1231         } else {
   1232             if (current) {
   1233                 // mark the current context as not current, and flush
   1234                 glFlush();
   1235                 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
   1236             }
   1237         }
   1238         if (!(c->flags & egl_context_t::IS_CURRENT)) {
   1239             // The context is not current, make it current!
   1240             setGlThreadSpecific(gl);
   1241             c->flags |= egl_context_t::IS_CURRENT;
   1242         }
   1243     } else {
   1244         if (current) {
   1245             // mark the current context as not current, and flush
   1246             glFlush();
   1247             egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
   1248         }
   1249         // this thread has no context attached to it
   1250         setGlThreadSpecific(0);
   1251     }
   1252     return 0;
   1253 }
   1254 
   1255 static EGLBoolean getConfigAttrib(EGLDisplay /*dpy*/, EGLConfig config,
   1256         EGLint attribute, EGLint *value)
   1257 {
   1258     size_t numConfigs =  NELEM(gConfigs);
   1259     int index = (int)(uintptr_t)config;
   1260     if (uint32_t(index) >= numConfigs)
   1261         return setError(EGL_BAD_CONFIG, EGL_FALSE);
   1262 
   1263     int attrIndex;
   1264     attrIndex = binarySearch<config_pair_t>(
   1265             gConfigs[index].array,
   1266             0, gConfigs[index].size-1,
   1267             attribute);
   1268     if (attrIndex>=0) {
   1269         *value = gConfigs[index].array[attrIndex].value;
   1270         return EGL_TRUE;
   1271     }
   1272 
   1273     attrIndex = binarySearch<config_pair_t>(
   1274             config_base_attribute_list,
   1275             0, NELEM(config_base_attribute_list)-1,
   1276             attribute);
   1277     if (attrIndex>=0) {
   1278         *value = config_base_attribute_list[attrIndex].value;
   1279         return EGL_TRUE;
   1280     }
   1281     return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1282 }
   1283 
   1284 static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
   1285         NativeWindowType window, const EGLint* /*attrib_list*/)
   1286 {
   1287     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1288         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1289     if (window == 0)
   1290         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1291 
   1292     EGLint surfaceType;
   1293     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
   1294         return EGL_FALSE;
   1295 
   1296     if (!(surfaceType & EGL_WINDOW_BIT))
   1297         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1298 
   1299     if (static_cast<ANativeWindow*>(window)->common.magic !=
   1300             ANDROID_NATIVE_WINDOW_MAGIC) {
   1301         return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
   1302     }
   1303 
   1304     EGLint configID;
   1305     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
   1306         return EGL_FALSE;
   1307 
   1308     int32_t depthFormat;
   1309     int32_t pixelFormat;
   1310     if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
   1311         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1312     }
   1313 
   1314     // FIXME: we don't have access to the pixelFormat here just yet.
   1315     // (it's possible that the surface is not fully initialized)
   1316     // maybe this should be done after the page-flip
   1317     //if (EGLint(info.format) != pixelFormat)
   1318     //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1319 
   1320     egl_surface_t* surface;
   1321     surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
   1322             static_cast<ANativeWindow*>(window));
   1323 
   1324     if (!surface->initCheck()) {
   1325         // there was a problem in the ctor, the error
   1326         // flag has been set.
   1327         delete surface;
   1328         surface = 0;
   1329     }
   1330     return surface;
   1331 }
   1332 
   1333 static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
   1334         NativePixmapType pixmap, const EGLint* /*attrib_list*/)
   1335 {
   1336     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1337         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1338     if (pixmap == 0)
   1339         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1340 
   1341     EGLint surfaceType;
   1342     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
   1343         return EGL_FALSE;
   1344 
   1345     if (!(surfaceType & EGL_PIXMAP_BIT))
   1346         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1347 
   1348     if (static_cast<egl_native_pixmap_t*>(pixmap)->version !=
   1349             sizeof(egl_native_pixmap_t)) {
   1350         return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
   1351     }
   1352 
   1353     EGLint configID;
   1354     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
   1355         return EGL_FALSE;
   1356 
   1357     int32_t depthFormat;
   1358     int32_t pixelFormat;
   1359     if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
   1360         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1361     }
   1362 
   1363     if (pixmap->format != pixelFormat)
   1364         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1365 
   1366     egl_surface_t* surface =
   1367         new egl_pixmap_surface_t(dpy, config, depthFormat,
   1368                 static_cast<egl_native_pixmap_t*>(pixmap));
   1369 
   1370     if (!surface->initCheck()) {
   1371         // there was a problem in the ctor, the error
   1372         // flag has been set.
   1373         delete surface;
   1374         surface = 0;
   1375     }
   1376     return surface;
   1377 }
   1378 
   1379 static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
   1380         const EGLint *attrib_list)
   1381 {
   1382     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1383         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1384 
   1385     EGLint surfaceType;
   1386     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
   1387         return EGL_FALSE;
   1388 
   1389     if (!(surfaceType & EGL_PBUFFER_BIT))
   1390         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1391 
   1392     EGLint configID;
   1393     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
   1394         return EGL_FALSE;
   1395 
   1396     int32_t depthFormat;
   1397     int32_t pixelFormat;
   1398     if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
   1399         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1400     }
   1401 
   1402     int32_t w = 0;
   1403     int32_t h = 0;
   1404     while (attrib_list[0] != EGL_NONE) {
   1405         if (attrib_list[0] == EGL_WIDTH)  w = attrib_list[1];
   1406         if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
   1407         attrib_list+=2;
   1408     }
   1409 
   1410     egl_surface_t* surface =
   1411         new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
   1412 
   1413     if (!surface->initCheck()) {
   1414         // there was a problem in the ctor, the error
   1415         // flag has been set.
   1416         delete surface;
   1417         surface = 0;
   1418     }
   1419     return surface;
   1420 }
   1421 
   1422 // ----------------------------------------------------------------------------
   1423 }; // namespace android
   1424 // ----------------------------------------------------------------------------
   1425 
   1426 using namespace android;
   1427 
   1428 // ----------------------------------------------------------------------------
   1429 // Initialization
   1430 // ----------------------------------------------------------------------------
   1431 
   1432 EGLDisplay eglGetDisplay(NativeDisplayType display)
   1433 {
   1434 #ifndef __ANDROID__
   1435     // this just needs to be done once
   1436     if (gGLKey == -1) {
   1437         pthread_mutex_lock(&gInitMutex);
   1438         if (gGLKey == -1)
   1439             pthread_key_create(&gGLKey, NULL);
   1440         pthread_mutex_unlock(&gInitMutex);
   1441     }
   1442 #endif
   1443     if (display == EGL_DEFAULT_DISPLAY) {
   1444         EGLDisplay dpy = (EGLDisplay)1;
   1445         egl_display_t& d = egl_display_t::get_display(dpy);
   1446         d.type = display;
   1447         return dpy;
   1448     }
   1449     return EGL_NO_DISPLAY;
   1450 }
   1451 
   1452 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
   1453 {
   1454     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1455         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1456 
   1457     EGLBoolean res = EGL_TRUE;
   1458     egl_display_t& d = egl_display_t::get_display(dpy);
   1459 
   1460     if (d.initialized.fetch_add(1, std::memory_order_acquire) == 0) {
   1461         // initialize stuff here if needed
   1462         //pthread_mutex_lock(&gInitMutex);
   1463         //pthread_mutex_unlock(&gInitMutex);
   1464     }
   1465 
   1466     if (res == EGL_TRUE) {
   1467         if (major != NULL) *major = VERSION_MAJOR;
   1468         if (minor != NULL) *minor = VERSION_MINOR;
   1469     }
   1470     return res;
   1471 }
   1472 
   1473 EGLBoolean eglTerminate(EGLDisplay dpy)
   1474 {
   1475     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1476         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1477 
   1478     EGLBoolean res = EGL_TRUE;
   1479     egl_display_t& d = egl_display_t::get_display(dpy);
   1480     if (d.initialized.fetch_sub(1, std::memory_order_release) == 1) {
   1481         std::atomic_thread_fence(std::memory_order_acquire);
   1482         // TODO: destroy all resources (surfaces, contexts, etc...)
   1483         //pthread_mutex_lock(&gInitMutex);
   1484         //pthread_mutex_unlock(&gInitMutex);
   1485     }
   1486     return res;
   1487 }
   1488 
   1489 // ----------------------------------------------------------------------------
   1490 // configuration
   1491 // ----------------------------------------------------------------------------
   1492 
   1493 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
   1494                             EGLConfig *configs,
   1495                             EGLint config_size, EGLint *num_config)
   1496 {
   1497     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1498         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1499 
   1500     if (ggl_unlikely(num_config==NULL))
   1501         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1502 
   1503     GLint numConfigs = NELEM(gConfigs);
   1504     if (!configs) {
   1505         *num_config = numConfigs;
   1506         return EGL_TRUE;
   1507     }
   1508     GLint i;
   1509     for (i=0 ; i<numConfigs && i<config_size ; i++) {
   1510         *configs++ = (EGLConfig)(uintptr_t)i;
   1511     }
   1512     *num_config = i;
   1513     return EGL_TRUE;
   1514 }
   1515 
   1516 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
   1517                             EGLConfig *configs, EGLint config_size,
   1518                             EGLint *num_config)
   1519 {
   1520     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1521         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1522 
   1523     if (ggl_unlikely(num_config==NULL)) {
   1524         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1525     }
   1526 
   1527     if (ggl_unlikely(attrib_list==0)) {
   1528         /*
   1529          * A NULL attrib_list should be treated as though it was an empty
   1530          * one (terminated with EGL_NONE) as defined in
   1531          * section 3.4.1 "Querying Configurations" in the EGL specification.
   1532          */
   1533         static const EGLint dummy = EGL_NONE;
   1534         attrib_list = &dummy;
   1535     }
   1536 
   1537     int numAttributes = 0;
   1538     int numConfigs =  NELEM(gConfigs);
   1539     uint32_t possibleMatch = (1<<numConfigs)-1;
   1540     while(possibleMatch && *attrib_list != EGL_NONE) {
   1541         numAttributes++;
   1542         EGLint attr = *attrib_list++;
   1543         EGLint val  = *attrib_list++;
   1544         for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
   1545             if (!(possibleMatch & (1<<i)))
   1546                 continue;
   1547             if (isAttributeMatching(i, attr, val) == 0) {
   1548                 possibleMatch &= ~(1<<i);
   1549             }
   1550         }
   1551     }
   1552 
   1553     // now, handle the attributes which have a useful default value
   1554     for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
   1555         // see if this attribute was specified, if not, apply its
   1556         // default value
   1557         if (binarySearch<config_pair_t>(
   1558                 (config_pair_t const*)attrib_list,
   1559                 0, numAttributes-1,
   1560                 config_defaults[j].key) < 0)
   1561         {
   1562             for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
   1563                 if (!(possibleMatch & (1<<i)))
   1564                     continue;
   1565                 if (isAttributeMatching(i,
   1566                         config_defaults[j].key,
   1567                         config_defaults[j].value) == 0)
   1568                 {
   1569                     possibleMatch &= ~(1<<i);
   1570                 }
   1571             }
   1572         }
   1573     }
   1574 
   1575     // return the configurations found
   1576     int n=0;
   1577     if (possibleMatch) {
   1578         if (configs) {
   1579             for (int i=0 ; config_size && i<numConfigs ; i++) {
   1580                 if (possibleMatch & (1<<i)) {
   1581                     *configs++ = (EGLConfig)(uintptr_t)i;
   1582                     config_size--;
   1583                     n++;
   1584                 }
   1585             }
   1586         } else {
   1587             for (int i=0 ; i<numConfigs ; i++) {
   1588                 if (possibleMatch & (1<<i)) {
   1589                     n++;
   1590                 }
   1591             }
   1592         }
   1593     }
   1594     *num_config = n;
   1595      return EGL_TRUE;
   1596 }
   1597 
   1598 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
   1599         EGLint attribute, EGLint *value)
   1600 {
   1601     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1602         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1603 
   1604     return getConfigAttrib(dpy, config, attribute, value);
   1605 }
   1606 
   1607 // ----------------------------------------------------------------------------
   1608 // surfaces
   1609 // ----------------------------------------------------------------------------
   1610 
   1611 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
   1612                                     NativeWindowType window,
   1613                                     const EGLint *attrib_list)
   1614 {
   1615     return createWindowSurface(dpy, config, window, attrib_list);
   1616 }
   1617 
   1618 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
   1619                                     NativePixmapType pixmap,
   1620                                     const EGLint *attrib_list)
   1621 {
   1622     return createPixmapSurface(dpy, config, pixmap, attrib_list);
   1623 }
   1624 
   1625 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
   1626                                     const EGLint *attrib_list)
   1627 {
   1628     return createPbufferSurface(dpy, config, attrib_list);
   1629 }
   1630 
   1631 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
   1632 {
   1633     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1634         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1635     if (eglSurface != EGL_NO_SURFACE) {
   1636         egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
   1637         if (!surface->isValid())
   1638             return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1639         if (surface->dpy != dpy)
   1640             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1641         if (surface->ctx) {
   1642             // defer disconnect/delete until no longer current
   1643             surface->zombie = true;
   1644         } else {
   1645             surface->disconnect();
   1646             delete surface;
   1647         }
   1648     }
   1649     return EGL_TRUE;
   1650 }
   1651 
   1652 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
   1653                             EGLint attribute, EGLint *value)
   1654 {
   1655     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1656         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1657     egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
   1658     if (!surface->isValid())
   1659         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1660     if (surface->dpy != dpy)
   1661         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1662 
   1663     EGLBoolean ret = EGL_TRUE;
   1664     switch (attribute) {
   1665         case EGL_CONFIG_ID:
   1666             ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
   1667             break;
   1668         case EGL_WIDTH:
   1669             *value = surface->getWidth();
   1670             break;
   1671         case EGL_HEIGHT:
   1672             *value = surface->getHeight();
   1673             break;
   1674         case EGL_LARGEST_PBUFFER:
   1675             // not modified for a window or pixmap surface
   1676             break;
   1677         case EGL_TEXTURE_FORMAT:
   1678             *value = EGL_NO_TEXTURE;
   1679             break;
   1680         case EGL_TEXTURE_TARGET:
   1681             *value = EGL_NO_TEXTURE;
   1682             break;
   1683         case EGL_MIPMAP_TEXTURE:
   1684             *value = EGL_FALSE;
   1685             break;
   1686         case EGL_MIPMAP_LEVEL:
   1687             *value = 0;
   1688             break;
   1689         case EGL_RENDER_BUFFER:
   1690             // TODO: return the real RENDER_BUFFER here
   1691             *value = EGL_BACK_BUFFER;
   1692             break;
   1693         case EGL_HORIZONTAL_RESOLUTION:
   1694             // pixel/mm * EGL_DISPLAY_SCALING
   1695             *value = surface->getHorizontalResolution();
   1696             break;
   1697         case EGL_VERTICAL_RESOLUTION:
   1698             // pixel/mm * EGL_DISPLAY_SCALING
   1699             *value = surface->getVerticalResolution();
   1700             break;
   1701         case EGL_PIXEL_ASPECT_RATIO: {
   1702             // w/h * EGL_DISPLAY_SCALING
   1703             int wr = surface->getHorizontalResolution();
   1704             int hr = surface->getVerticalResolution();
   1705             *value = (wr * EGL_DISPLAY_SCALING) / hr;
   1706         } break;
   1707         case EGL_SWAP_BEHAVIOR:
   1708             *value = surface->getSwapBehavior();
   1709             break;
   1710         default:
   1711             ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1712     }
   1713     return ret;
   1714 }
   1715 
   1716 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
   1717                             EGLContext /*share_list*/, const EGLint* /*attrib_list*/)
   1718 {
   1719     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1720         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1721 
   1722     ogles_context_t* gl = ogles_init(sizeof(egl_context_t));
   1723     if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
   1724 
   1725     egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
   1726     c->flags = egl_context_t::NEVER_CURRENT;
   1727     c->dpy = dpy;
   1728     c->config = config;
   1729     c->read = 0;
   1730     c->draw = 0;
   1731     return (EGLContext)gl;
   1732 }
   1733 
   1734 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
   1735 {
   1736     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1737         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1738     egl_context_t* c = egl_context_t::context(ctx);
   1739     if (c->flags & egl_context_t::IS_CURRENT)
   1740         setGlThreadSpecific(0);
   1741     ogles_uninit((ogles_context_t*)ctx);
   1742     return EGL_TRUE;
   1743 }
   1744 
   1745 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
   1746                             EGLSurface read, EGLContext ctx)
   1747 {
   1748     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1749         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1750     if (draw) {
   1751         egl_surface_t* s = (egl_surface_t*)draw;
   1752         if (!s->isValid())
   1753             return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1754         if (s->dpy != dpy)
   1755             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1756         // TODO: check that draw is compatible with the context
   1757     }
   1758     if (read && read!=draw) {
   1759         egl_surface_t* s = (egl_surface_t*)read;
   1760         if (!s->isValid())
   1761             return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1762         if (s->dpy != dpy)
   1763             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1764         // TODO: check that read is compatible with the context
   1765     }
   1766 
   1767     EGLContext current_ctx = EGL_NO_CONTEXT;
   1768 
   1769     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
   1770         return setError(EGL_BAD_MATCH, EGL_FALSE);
   1771 
   1772     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
   1773         return setError(EGL_BAD_MATCH, EGL_FALSE);
   1774 
   1775     if (ctx == EGL_NO_CONTEXT) {
   1776         // if we're detaching, we need the current context
   1777         current_ctx = (EGLContext)getGlThreadSpecific();
   1778     } else {
   1779         egl_context_t* c = egl_context_t::context(ctx);
   1780         egl_surface_t* d = (egl_surface_t*)draw;
   1781         egl_surface_t* r = (egl_surface_t*)read;
   1782         if ((d && d->ctx && d->ctx != ctx) ||
   1783             (r && r->ctx && r->ctx != ctx)) {
   1784             // one of the surface is bound to a context in another thread
   1785             return setError(EGL_BAD_ACCESS, EGL_FALSE);
   1786         }
   1787     }
   1788 
   1789     ogles_context_t* gl = (ogles_context_t*)ctx;
   1790     if (makeCurrent(gl) == 0) {
   1791         if (ctx) {
   1792             egl_context_t* c = egl_context_t::context(ctx);
   1793             egl_surface_t* d = (egl_surface_t*)draw;
   1794             egl_surface_t* r = (egl_surface_t*)read;
   1795 
   1796             if (c->draw) {
   1797                 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
   1798                 s->disconnect();
   1799                 s->ctx = EGL_NO_CONTEXT;
   1800                 if (s->zombie)
   1801                     delete s;
   1802             }
   1803             if (c->read) {
   1804                 // FIXME: unlock/disconnect the read surface too
   1805             }
   1806 
   1807             c->draw = draw;
   1808             c->read = read;
   1809 
   1810             if (c->flags & egl_context_t::NEVER_CURRENT) {
   1811                 c->flags &= ~egl_context_t::NEVER_CURRENT;
   1812                 GLint w = 0;
   1813                 GLint h = 0;
   1814                 if (draw) {
   1815                     w = d->getWidth();
   1816                     h = d->getHeight();
   1817                 }
   1818                 ogles_surfaceport(gl, 0, 0);
   1819                 ogles_viewport(gl, 0, 0, w, h);
   1820                 ogles_scissor(gl, 0, 0, w, h);
   1821             }
   1822             if (d) {
   1823                 if (d->connect() == EGL_FALSE) {
   1824                     return EGL_FALSE;
   1825                 }
   1826                 d->ctx = ctx;
   1827                 d->bindDrawSurface(gl);
   1828             }
   1829             if (r) {
   1830                 // FIXME: lock/connect the read surface too
   1831                 r->ctx = ctx;
   1832                 r->bindReadSurface(gl);
   1833             }
   1834         } else {
   1835             // if surfaces were bound to the context bound to this thread
   1836             // mark then as unbound.
   1837             if (current_ctx) {
   1838                 egl_context_t* c = egl_context_t::context(current_ctx);
   1839                 egl_surface_t* d = (egl_surface_t*)c->draw;
   1840                 egl_surface_t* r = (egl_surface_t*)c->read;
   1841                 if (d) {
   1842                     c->draw = 0;
   1843                     d->disconnect();
   1844                     d->ctx = EGL_NO_CONTEXT;
   1845                     if (d->zombie)
   1846                         delete d;
   1847                 }
   1848                 if (r) {
   1849                     c->read = 0;
   1850                     r->ctx = EGL_NO_CONTEXT;
   1851                     // FIXME: unlock/disconnect the read surface too
   1852                 }
   1853             }
   1854         }
   1855         return EGL_TRUE;
   1856     }
   1857     return setError(EGL_BAD_ACCESS, EGL_FALSE);
   1858 }
   1859 
   1860 EGLContext eglGetCurrentContext(void)
   1861 {
   1862     // eglGetCurrentContext returns the current EGL rendering context,
   1863     // as specified by eglMakeCurrent. If no context is current,
   1864     // EGL_NO_CONTEXT is returned.
   1865     return (EGLContext)getGlThreadSpecific();
   1866 }
   1867 
   1868 EGLSurface eglGetCurrentSurface(EGLint readdraw)
   1869 {
   1870     // eglGetCurrentSurface returns the read or draw surface attached
   1871     // to the current EGL rendering context, as specified by eglMakeCurrent.
   1872     // If no context is current, EGL_NO_SURFACE is returned.
   1873     EGLContext ctx = (EGLContext)getGlThreadSpecific();
   1874     if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
   1875     egl_context_t* c = egl_context_t::context(ctx);
   1876     if (readdraw == EGL_READ) {
   1877         return c->read;
   1878     } else if (readdraw == EGL_DRAW) {
   1879         return c->draw;
   1880     }
   1881     return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
   1882 }
   1883 
   1884 EGLDisplay eglGetCurrentDisplay(void)
   1885 {
   1886     // eglGetCurrentDisplay returns the current EGL display connection
   1887     // for the current EGL rendering context, as specified by eglMakeCurrent.
   1888     // If no context is current, EGL_NO_DISPLAY is returned.
   1889     EGLContext ctx = (EGLContext)getGlThreadSpecific();
   1890     if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
   1891     egl_context_t* c = egl_context_t::context(ctx);
   1892     return c->dpy;
   1893 }
   1894 
   1895 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
   1896                             EGLint attribute, EGLint *value)
   1897 {
   1898     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1899         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1900     egl_context_t* c = egl_context_t::context(ctx);
   1901     switch (attribute) {
   1902         case EGL_CONFIG_ID:
   1903             // Returns the ID of the EGL frame buffer configuration with
   1904             // respect to which the context was created
   1905             return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
   1906     }
   1907     return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1908 }
   1909 
   1910 EGLBoolean eglWaitGL(void)
   1911 {
   1912     return EGL_TRUE;
   1913 }
   1914 
   1915 EGLBoolean eglWaitNative(EGLint /*engine*/)
   1916 {
   1917     return EGL_TRUE;
   1918 }
   1919 
   1920 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
   1921 {
   1922     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1923         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1924 
   1925     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
   1926     if (!d->isValid())
   1927         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1928     if (d->dpy != dpy)
   1929         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1930 
   1931     // post the surface
   1932     d->swapBuffers();
   1933 
   1934     // if it's bound to a context, update the buffer
   1935     if (d->ctx != EGL_NO_CONTEXT) {
   1936         d->bindDrawSurface((ogles_context_t*)d->ctx);
   1937         // if this surface is also the read surface of the context
   1938         // it is bound to, make sure to update the read buffer as well.
   1939         // The EGL spec is a little unclear about this.
   1940         egl_context_t* c = egl_context_t::context(d->ctx);
   1941         if (c->read == draw) {
   1942             d->bindReadSurface((ogles_context_t*)d->ctx);
   1943         }
   1944     }
   1945 
   1946     return EGL_TRUE;
   1947 }
   1948 
   1949 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface /*surface*/,
   1950                             NativePixmapType /*target*/)
   1951 {
   1952     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1953         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1954     // TODO: eglCopyBuffers()
   1955     return EGL_FALSE;
   1956 }
   1957 
   1958 EGLint eglGetError(void)
   1959 {
   1960     return getError();
   1961 }
   1962 
   1963 const char* eglQueryString(EGLDisplay dpy, EGLint name)
   1964 {
   1965     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1966         return setError(EGL_BAD_DISPLAY, (const char*)0);
   1967 
   1968     switch (name) {
   1969         case EGL_VENDOR:
   1970             return gVendorString;
   1971         case EGL_VERSION:
   1972             return gVersionString;
   1973         case EGL_EXTENSIONS:
   1974             return gExtensionsString;
   1975         case EGL_CLIENT_APIS:
   1976             return gClientApiString;
   1977     }
   1978     return setError(EGL_BAD_PARAMETER, (const char *)0);
   1979 }
   1980 
   1981 // ----------------------------------------------------------------------------
   1982 // EGL 1.1
   1983 // ----------------------------------------------------------------------------
   1984 
   1985 EGLBoolean eglSurfaceAttrib(
   1986         EGLDisplay dpy, EGLSurface /*surface*/, EGLint /*attribute*/, EGLint /*value*/)
   1987 {
   1988     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1989         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1990     // TODO: eglSurfaceAttrib()
   1991     return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1992 }
   1993 
   1994 EGLBoolean eglBindTexImage(
   1995         EGLDisplay dpy, EGLSurface /*surface*/, EGLint /*buffer*/)
   1996 {
   1997     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1998         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1999     // TODO: eglBindTexImage()
   2000     return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2001 }
   2002 
   2003 EGLBoolean eglReleaseTexImage(
   2004         EGLDisplay dpy, EGLSurface /*surface*/, EGLint /*buffer*/)
   2005 {
   2006     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   2007         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2008     // TODO: eglReleaseTexImage()
   2009     return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2010 }
   2011 
   2012 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint /*interval*/)
   2013 {
   2014     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   2015         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2016     // TODO: eglSwapInterval()
   2017     return EGL_TRUE;
   2018 }
   2019 
   2020 // ----------------------------------------------------------------------------
   2021 // EGL 1.2
   2022 // ----------------------------------------------------------------------------
   2023 
   2024 EGLBoolean eglBindAPI(EGLenum api)
   2025 {
   2026     if (api != EGL_OPENGL_ES_API)
   2027         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2028     return EGL_TRUE;
   2029 }
   2030 
   2031 EGLenum eglQueryAPI(void)
   2032 {
   2033     return EGL_OPENGL_ES_API;
   2034 }
   2035 
   2036 EGLBoolean eglWaitClient(void)
   2037 {
   2038     glFinish();
   2039     return EGL_TRUE;
   2040 }
   2041 
   2042 EGLBoolean eglReleaseThread(void)
   2043 {
   2044     // TODO: eglReleaseThread()
   2045     return EGL_TRUE;
   2046 }
   2047 
   2048 EGLSurface eglCreatePbufferFromClientBuffer(
   2049           EGLDisplay dpy, EGLenum /*buftype*/, EGLClientBuffer /*buffer*/,
   2050           EGLConfig /*config*/, const EGLint* /*attrib_list*/)
   2051 {
   2052     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   2053         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   2054     // TODO: eglCreatePbufferFromClientBuffer()
   2055     return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   2056 }
   2057 
   2058 // ----------------------------------------------------------------------------
   2059 // EGL_EGLEXT_VERSION 3
   2060 // ----------------------------------------------------------------------------
   2061 
   2062 void (*eglGetProcAddress (const char *procname))()
   2063 {
   2064     extention_map_t const * const map = gExtentionMap;
   2065     for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
   2066         if (!strcmp(procname, map[i].name)) {
   2067             return map[i].address;
   2068         }
   2069     }
   2070     return NULL;
   2071 }
   2072 
   2073 EGLBoolean eglLockSurfaceKHR(EGLDisplay /*dpy*/, EGLSurface /*surface*/,
   2074         const EGLint* /*attrib_list*/)
   2075 {
   2076     EGLBoolean result = EGL_FALSE;
   2077     return result;
   2078 }
   2079 
   2080 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay /*dpy*/, EGLSurface /*surface*/)
   2081 {
   2082     EGLBoolean result = EGL_FALSE;
   2083     return result;
   2084 }
   2085 
   2086 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
   2087         EGLClientBuffer buffer, const EGLint* /*attrib_list*/)
   2088 {
   2089     if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
   2090         return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
   2091     }
   2092     if (ctx != EGL_NO_CONTEXT) {
   2093         return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   2094     }
   2095     if (target != EGL_NATIVE_BUFFER_ANDROID) {
   2096         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2097     }
   2098 
   2099     ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;
   2100 
   2101     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   2102         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2103 
   2104     if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
   2105         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2106 
   2107     switch (native_buffer->format) {
   2108         case HAL_PIXEL_FORMAT_RGBA_8888:
   2109         case HAL_PIXEL_FORMAT_RGBX_8888:
   2110         case HAL_PIXEL_FORMAT_RGB_888:
   2111         case HAL_PIXEL_FORMAT_RGB_565:
   2112         case HAL_PIXEL_FORMAT_BGRA_8888:
   2113             break;
   2114         default:
   2115             return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2116     }
   2117 
   2118     native_buffer->common.incRef(&native_buffer->common);
   2119     return (EGLImageKHR)native_buffer;
   2120 }
   2121 
   2122 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
   2123 {
   2124     if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
   2125         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2126     }
   2127 
   2128     ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img;
   2129 
   2130     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   2131         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2132 
   2133     if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
   2134         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2135 
   2136     native_buffer->common.decRef(&native_buffer->common);
   2137 
   2138     return EGL_TRUE;
   2139 }
   2140 
   2141 // ----------------------------------------------------------------------------
   2142 // EGL_KHR_fence_sync
   2143 // ----------------------------------------------------------------------------
   2144 
   2145 #define FENCE_SYNC_HANDLE ((EGLSyncKHR)0xFE4CE)
   2146 
   2147 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
   2148         const EGLint *attrib_list)
   2149 {
   2150     if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
   2151         return setError(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
   2152     }
   2153 
   2154     if (type != EGL_SYNC_FENCE_KHR ||
   2155             (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
   2156         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
   2157     }
   2158 
   2159     if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
   2160         return setError(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   2161     }
   2162 
   2163     // AGL is synchronous; nothing to do here.
   2164 
   2165     return FENCE_SYNC_HANDLE;
   2166 }
   2167 
   2168 EGLBoolean eglDestroySyncKHR(EGLDisplay /*dpy*/, EGLSyncKHR sync)
   2169 {
   2170     if (sync != FENCE_SYNC_HANDLE) {
   2171         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2172     }
   2173 
   2174     return EGL_TRUE;
   2175 }
   2176 
   2177 EGLint eglClientWaitSyncKHR(EGLDisplay /*dpy*/, EGLSyncKHR sync, EGLint /*flags*/,
   2178         EGLTimeKHR /*timeout*/)
   2179 {
   2180     if (sync != FENCE_SYNC_HANDLE) {
   2181         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2182     }
   2183 
   2184     return EGL_CONDITION_SATISFIED_KHR;
   2185 }
   2186 
   2187 EGLBoolean eglGetSyncAttribKHR(EGLDisplay /*dpy*/, EGLSyncKHR sync,
   2188         EGLint attribute, EGLint *value)
   2189 {
   2190     if (sync != FENCE_SYNC_HANDLE) {
   2191         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2192     }
   2193 
   2194     switch (attribute) {
   2195     case EGL_SYNC_TYPE_KHR:
   2196         *value = EGL_SYNC_FENCE_KHR;
   2197         return EGL_TRUE;
   2198     case EGL_SYNC_STATUS_KHR:
   2199         *value = EGL_SIGNALED_KHR;
   2200         return EGL_TRUE;
   2201     case EGL_SYNC_CONDITION_KHR:
   2202         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
   2203         return EGL_TRUE;
   2204     default:
   2205         return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   2206     }
   2207 }
   2208 
   2209 // ----------------------------------------------------------------------------
   2210 // ANDROID extensions
   2211 // ----------------------------------------------------------------------------
   2212 
   2213 EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
   2214         EGLint left, EGLint top, EGLint width, EGLint height)
   2215 {
   2216     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   2217         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2218 
   2219     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
   2220     if (!d->isValid())
   2221         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   2222     if (d->dpy != dpy)
   2223         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2224 
   2225     // post the surface
   2226     d->setSwapRectangle(left, top, width, height);
   2227 
   2228     return EGL_TRUE;
   2229 }
   2230