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