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