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