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 #include <ui/ANativeObjectBase.h>
     34 
     35 #include <EGL/egl.h>
     36 #include <EGL/eglext.h>
     37 #include <GLES/gl.h>
     38 #include <GLES/glext.h>
     39 
     40 #include <pixelflinger/format.h>
     41 #include <pixelflinger/pixelflinger.h>
     42 
     43 #include "context.h"
     44 #include "state.h"
     45 #include "texture.h"
     46 #include "matrix.h"
     47 
     48 #undef NELEM
     49 #define NELEM(x) (sizeof(x)/sizeof(*(x)))
     50 
     51 // ----------------------------------------------------------------------------
     52 
     53 EGLBoolean EGLAPI eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
     54         EGLint left, EGLint top, EGLint width, EGLint height);
     55 
     56 // ----------------------------------------------------------------------------
     57 namespace android {
     58 
     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     ALOGE_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             ALOGD("%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         ALOGE("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             ALOGE("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             ALOGE("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_fence_sync "
    800         "EGL_KHR_image_base "
    801         // "KHR_image_pixmap "
    802         "EGL_ANDROID_image_native_buffer "
    803         "EGL_ANDROID_swap_rectangle "
    804         ;
    805 
    806 // ----------------------------------------------------------------------------
    807 
    808 struct extention_map_t {
    809     const char * const name;
    810     __eglMustCastToProperFunctionPointerType address;
    811 };
    812 
    813 static const extention_map_t gExtentionMap[] = {
    814     { "glDrawTexsOES",
    815             (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
    816     { "glDrawTexiOES",
    817             (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
    818     { "glDrawTexfOES",
    819             (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
    820     { "glDrawTexxOES",
    821             (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
    822     { "glDrawTexsvOES",
    823             (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
    824     { "glDrawTexivOES",
    825             (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
    826     { "glDrawTexfvOES",
    827             (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
    828     { "glDrawTexxvOES",
    829             (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
    830     { "glQueryMatrixxOES",
    831             (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
    832     { "glEGLImageTargetTexture2DOES",
    833             (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
    834     { "glEGLImageTargetRenderbufferStorageOES",
    835             (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
    836     { "glClipPlanef",
    837             (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
    838     { "glClipPlanex",
    839             (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
    840     { "glBindBuffer",
    841             (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
    842     { "glBufferData",
    843             (__eglMustCastToProperFunctionPointerType)&glBufferData },
    844     { "glBufferSubData",
    845             (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
    846     { "glDeleteBuffers",
    847             (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
    848     { "glGenBuffers",
    849             (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
    850     { "eglCreateImageKHR",
    851             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
    852     { "eglDestroyImageKHR",
    853             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
    854     { "eglCreateSyncKHR",
    855             (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
    856     { "eglDestroySyncKHR",
    857             (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
    858     { "eglClientWaitSyncKHR",
    859             (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
    860     { "eglGetSyncAttribKHR",
    861             (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
    862     { "eglSetSwapRectangleANDROID",
    863             (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
    864 };
    865 
    866 /*
    867  * In the lists below, attributes names MUST be sorted.
    868  * Additionally, all configs must be sorted according to
    869  * the EGL specification.
    870  */
    871 
    872 static config_pair_t const config_base_attribute_list[] = {
    873         { EGL_STENCIL_SIZE,               0                                 },
    874         { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
    875         { EGL_LEVEL,                      0                                 },
    876         { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
    877         { EGL_MAX_PBUFFER_PIXELS,
    878                 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
    879         { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
    880         { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
    881         { EGL_NATIVE_VISUAL_ID,           0                                 },
    882         { EGL_NATIVE_VISUAL_TYPE,         GGL_PIXEL_FORMAT_RGB_565          },
    883         { EGL_SAMPLES,                    0                                 },
    884         { EGL_SAMPLE_BUFFERS,             0                                 },
    885         { EGL_TRANSPARENT_TYPE,           EGL_NONE                          },
    886         { EGL_TRANSPARENT_BLUE_VALUE,     0                                 },
    887         { EGL_TRANSPARENT_GREEN_VALUE,    0                                 },
    888         { EGL_TRANSPARENT_RED_VALUE,      0                                 },
    889         { EGL_BIND_TO_TEXTURE_RGBA,       EGL_FALSE                         },
    890         { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
    891         { EGL_MIN_SWAP_INTERVAL,          1                                 },
    892         { EGL_MAX_SWAP_INTERVAL,          1                                 },
    893         { EGL_LUMINANCE_SIZE,             0                                 },
    894         { EGL_ALPHA_MASK_SIZE,            0                                 },
    895         { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
    896         { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES_BIT                 },
    897         { EGL_CONFORMANT,                 0                                 }
    898 };
    899 
    900 // These configs can override the base attribute list
    901 // NOTE: when adding a config here, don't forget to update eglCreate*Surface()
    902 
    903 // 565 configs
    904 static config_pair_t const config_0_attribute_list[] = {
    905         { EGL_BUFFER_SIZE,     16 },
    906         { EGL_ALPHA_SIZE,       0 },
    907         { EGL_BLUE_SIZE,        5 },
    908         { EGL_GREEN_SIZE,       6 },
    909         { EGL_RED_SIZE,         5 },
    910         { EGL_DEPTH_SIZE,       0 },
    911         { EGL_CONFIG_ID,        0 },
    912         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
    913         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    914 };
    915 
    916 static config_pair_t const config_1_attribute_list[] = {
    917         { EGL_BUFFER_SIZE,     16 },
    918         { EGL_ALPHA_SIZE,       0 },
    919         { EGL_BLUE_SIZE,        5 },
    920         { EGL_GREEN_SIZE,       6 },
    921         { EGL_RED_SIZE,         5 },
    922         { EGL_DEPTH_SIZE,      16 },
    923         { EGL_CONFIG_ID,        1 },
    924         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
    925         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    926 };
    927 
    928 // RGB 888 configs
    929 static config_pair_t const config_2_attribute_list[] = {
    930         { EGL_BUFFER_SIZE,     32 },
    931         { EGL_ALPHA_SIZE,       0 },
    932         { EGL_BLUE_SIZE,        8 },
    933         { EGL_GREEN_SIZE,       8 },
    934         { EGL_RED_SIZE,         8 },
    935         { EGL_DEPTH_SIZE,       0 },
    936         { EGL_CONFIG_ID,        6 },
    937         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
    938         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    939 };
    940 
    941 static config_pair_t const config_3_attribute_list[] = {
    942         { EGL_BUFFER_SIZE,     32 },
    943         { EGL_ALPHA_SIZE,       0 },
    944         { EGL_BLUE_SIZE,        8 },
    945         { EGL_GREEN_SIZE,       8 },
    946         { EGL_RED_SIZE,         8 },
    947         { EGL_DEPTH_SIZE,      16 },
    948         { EGL_CONFIG_ID,        7 },
    949         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
    950         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    951 };
    952 
    953 // 8888 configs
    954 static config_pair_t const config_4_attribute_list[] = {
    955         { EGL_BUFFER_SIZE,     32 },
    956         { EGL_ALPHA_SIZE,       8 },
    957         { EGL_BLUE_SIZE,        8 },
    958         { EGL_GREEN_SIZE,       8 },
    959         { EGL_RED_SIZE,         8 },
    960         { EGL_DEPTH_SIZE,       0 },
    961         { EGL_CONFIG_ID,        2 },
    962         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
    963         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    964 };
    965 
    966 static config_pair_t const config_5_attribute_list[] = {
    967         { EGL_BUFFER_SIZE,     32 },
    968         { EGL_ALPHA_SIZE,       8 },
    969         { EGL_BLUE_SIZE,        8 },
    970         { EGL_GREEN_SIZE,       8 },
    971         { EGL_RED_SIZE,         8 },
    972         { EGL_DEPTH_SIZE,      16 },
    973         { EGL_CONFIG_ID,        3 },
    974         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
    975         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    976 };
    977 
    978 // A8 configs
    979 static config_pair_t const config_6_attribute_list[] = {
    980         { EGL_BUFFER_SIZE,      8 },
    981         { EGL_ALPHA_SIZE,       8 },
    982         { EGL_BLUE_SIZE,        0 },
    983         { EGL_GREEN_SIZE,       0 },
    984         { EGL_RED_SIZE,         0 },
    985         { EGL_DEPTH_SIZE,       0 },
    986         { EGL_CONFIG_ID,        4 },
    987         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
    988         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
    989 };
    990 
    991 static config_pair_t const config_7_attribute_list[] = {
    992         { EGL_BUFFER_SIZE,      8 },
    993         { EGL_ALPHA_SIZE,       8 },
    994         { EGL_BLUE_SIZE,        0 },
    995         { EGL_GREEN_SIZE,       0 },
    996         { EGL_RED_SIZE,         0 },
    997         { EGL_DEPTH_SIZE,      16 },
    998         { EGL_CONFIG_ID,        5 },
    999         { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
   1000         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
   1001 };
   1002 
   1003 static configs_t const gConfigs[] = {
   1004         { config_0_attribute_list, NELEM(config_0_attribute_list) },
   1005         { config_1_attribute_list, NELEM(config_1_attribute_list) },
   1006         { config_2_attribute_list, NELEM(config_2_attribute_list) },
   1007         { config_3_attribute_list, NELEM(config_3_attribute_list) },
   1008         { config_4_attribute_list, NELEM(config_4_attribute_list) },
   1009         { config_5_attribute_list, NELEM(config_5_attribute_list) },
   1010         { config_6_attribute_list, NELEM(config_6_attribute_list) },
   1011         { config_7_attribute_list, NELEM(config_7_attribute_list) },
   1012 };
   1013 
   1014 static config_management_t const gConfigManagement[] = {
   1015         { EGL_BUFFER_SIZE,                config_management_t::atLeast },
   1016         { EGL_ALPHA_SIZE,                 config_management_t::atLeast },
   1017         { EGL_BLUE_SIZE,                  config_management_t::atLeast },
   1018         { EGL_GREEN_SIZE,                 config_management_t::atLeast },
   1019         { EGL_RED_SIZE,                   config_management_t::atLeast },
   1020         { EGL_DEPTH_SIZE,                 config_management_t::atLeast },
   1021         { EGL_STENCIL_SIZE,               config_management_t::atLeast },
   1022         { EGL_CONFIG_CAVEAT,              config_management_t::exact   },
   1023         { EGL_CONFIG_ID,                  config_management_t::exact   },
   1024         { EGL_LEVEL,                      config_management_t::exact   },
   1025         { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::ignore   },
   1026         { EGL_MAX_PBUFFER_PIXELS,         config_management_t::ignore   },
   1027         { EGL_MAX_PBUFFER_WIDTH,          config_management_t::ignore   },
   1028         { EGL_NATIVE_RENDERABLE,          config_management_t::exact   },
   1029         { EGL_NATIVE_VISUAL_ID,           config_management_t::ignore   },
   1030         { EGL_NATIVE_VISUAL_TYPE,         config_management_t::exact   },
   1031         { EGL_SAMPLES,                    config_management_t::exact   },
   1032         { EGL_SAMPLE_BUFFERS,             config_management_t::exact   },
   1033         { EGL_SURFACE_TYPE,               config_management_t::mask    },
   1034         { EGL_TRANSPARENT_TYPE,           config_management_t::exact   },
   1035         { EGL_TRANSPARENT_BLUE_VALUE,     config_management_t::exact   },
   1036         { EGL_TRANSPARENT_GREEN_VALUE,    config_management_t::exact   },
   1037         { EGL_TRANSPARENT_RED_VALUE,      config_management_t::exact   },
   1038         { EGL_BIND_TO_TEXTURE_RGBA,       config_management_t::exact   },
   1039         { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
   1040         { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
   1041         { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
   1042         { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
   1043         { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
   1044         { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
   1045         { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
   1046         { EGL_CONFORMANT,                 config_management_t::mask    }
   1047 };
   1048 
   1049 
   1050 static config_pair_t const config_defaults[] = {
   1051     // attributes that are not specified are simply ignored, if a particular
   1052     // one needs not be ignored, it must be specified here, eg:
   1053     // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
   1054 };
   1055 
   1056 // ----------------------------------------------------------------------------
   1057 
   1058 static status_t getConfigFormatInfo(EGLint configID,
   1059         int32_t& pixelFormat, int32_t& depthFormat)
   1060 {
   1061     switch(configID) {
   1062     case 0:
   1063         pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
   1064         depthFormat = 0;
   1065         break;
   1066     case 1:
   1067         pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
   1068         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1069         break;
   1070     case 2:
   1071         pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
   1072         depthFormat = 0;
   1073         break;
   1074     case 3:
   1075         pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
   1076         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1077         break;
   1078     case 4:
   1079         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
   1080         depthFormat = 0;
   1081         break;
   1082     case 5:
   1083         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
   1084         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1085         break;
   1086     case 6:
   1087         pixelFormat = GGL_PIXEL_FORMAT_A_8;
   1088         depthFormat = 0;
   1089         break;
   1090     case 7:
   1091         pixelFormat = GGL_PIXEL_FORMAT_A_8;
   1092         depthFormat = GGL_PIXEL_FORMAT_Z_16;
   1093         break;
   1094     default:
   1095         return NAME_NOT_FOUND;
   1096     }
   1097     return NO_ERROR;
   1098 }
   1099 
   1100 // ----------------------------------------------------------------------------
   1101 
   1102 template<typename T>
   1103 static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
   1104 {
   1105    while (first <= last) {
   1106        int mid = (first + last) / 2;
   1107        if (key > sortedArray[mid].key) {
   1108            first = mid + 1;
   1109        } else if (key < sortedArray[mid].key) {
   1110            last = mid - 1;
   1111        } else {
   1112            return mid;
   1113        }
   1114    }
   1115    return -1;
   1116 }
   1117 
   1118 static int isAttributeMatching(int i, EGLint attr, EGLint val)
   1119 {
   1120     // look for the attribute in all of our configs
   1121     config_pair_t const* configFound = gConfigs[i].array;
   1122     int index = binarySearch<config_pair_t>(
   1123             gConfigs[i].array,
   1124             0, gConfigs[i].size-1,
   1125             attr);
   1126     if (index < 0) {
   1127         configFound = config_base_attribute_list;
   1128         index = binarySearch<config_pair_t>(
   1129                 config_base_attribute_list,
   1130                 0, NELEM(config_base_attribute_list)-1,
   1131                 attr);
   1132     }
   1133     if (index >= 0) {
   1134         // attribute found, check if this config could match
   1135         int cfgMgtIndex = binarySearch<config_management_t>(
   1136                 gConfigManagement,
   1137                 0, NELEM(gConfigManagement)-1,
   1138                 attr);
   1139         if (cfgMgtIndex >= 0) {
   1140             bool match = gConfigManagement[cfgMgtIndex].match(
   1141                     val, configFound[index].value);
   1142             if (match) {
   1143                 // this config matches
   1144                 return 1;
   1145             }
   1146         } else {
   1147             // attribute not found. this should NEVER happen.
   1148         }
   1149     } else {
   1150         // error, this attribute doesn't exist
   1151     }
   1152     return 0;
   1153 }
   1154 
   1155 static int makeCurrent(ogles_context_t* gl)
   1156 {
   1157     ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific();
   1158     if (gl) {
   1159         egl_context_t* c = egl_context_t::context(gl);
   1160         if (c->flags & egl_context_t::IS_CURRENT) {
   1161             if (current != gl) {
   1162                 // it is an error to set a context current, if it's already
   1163                 // current to another thread
   1164                 return -1;
   1165             }
   1166         } else {
   1167             if (current) {
   1168                 // mark the current context as not current, and flush
   1169                 glFlush();
   1170                 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
   1171             }
   1172         }
   1173         if (!(c->flags & egl_context_t::IS_CURRENT)) {
   1174             // The context is not current, make it current!
   1175             setGlThreadSpecific(gl);
   1176             c->flags |= egl_context_t::IS_CURRENT;
   1177         }
   1178     } else {
   1179         if (current) {
   1180             // mark the current context as not current, and flush
   1181             glFlush();
   1182             egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
   1183         }
   1184         // this thread has no context attached to it
   1185         setGlThreadSpecific(0);
   1186     }
   1187     return 0;
   1188 }
   1189 
   1190 static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
   1191         EGLint attribute, EGLint *value)
   1192 {
   1193     size_t numConfigs =  NELEM(gConfigs);
   1194     int index = (int)config;
   1195     if (uint32_t(index) >= numConfigs)
   1196         return setError(EGL_BAD_CONFIG, EGL_FALSE);
   1197 
   1198     int attrIndex;
   1199     attrIndex = binarySearch<config_pair_t>(
   1200             gConfigs[index].array,
   1201             0, gConfigs[index].size-1,
   1202             attribute);
   1203     if (attrIndex>=0) {
   1204         *value = gConfigs[index].array[attrIndex].value;
   1205         return EGL_TRUE;
   1206     }
   1207 
   1208     attrIndex = binarySearch<config_pair_t>(
   1209             config_base_attribute_list,
   1210             0, NELEM(config_base_attribute_list)-1,
   1211             attribute);
   1212     if (attrIndex>=0) {
   1213         *value = config_base_attribute_list[attrIndex].value;
   1214         return EGL_TRUE;
   1215     }
   1216     return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1217 }
   1218 
   1219 static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
   1220         NativeWindowType window, const EGLint *attrib_list)
   1221 {
   1222     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1223         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1224     if (window == 0)
   1225         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1226 
   1227     EGLint surfaceType;
   1228     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
   1229         return EGL_FALSE;
   1230 
   1231     if (!(surfaceType & EGL_WINDOW_BIT))
   1232         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1233 
   1234     if (static_cast<ANativeWindow*>(window)->common.magic !=
   1235             ANDROID_NATIVE_WINDOW_MAGIC) {
   1236         return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
   1237     }
   1238 
   1239     EGLint configID;
   1240     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
   1241         return EGL_FALSE;
   1242 
   1243     int32_t depthFormat;
   1244     int32_t pixelFormat;
   1245     if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
   1246         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1247     }
   1248 
   1249     // FIXME: we don't have access to the pixelFormat here just yet.
   1250     // (it's possible that the surface is not fully initialized)
   1251     // maybe this should be done after the page-flip
   1252     //if (EGLint(info.format) != pixelFormat)
   1253     //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1254 
   1255     egl_surface_t* surface;
   1256     surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
   1257             static_cast<ANativeWindow*>(window));
   1258 
   1259     if (!surface->initCheck()) {
   1260         // there was a problem in the ctor, the error
   1261         // flag has been set.
   1262         delete surface;
   1263         surface = 0;
   1264     }
   1265     return surface;
   1266 }
   1267 
   1268 static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
   1269         NativePixmapType pixmap, const EGLint *attrib_list)
   1270 {
   1271     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1272         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1273     if (pixmap == 0)
   1274         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1275 
   1276     EGLint surfaceType;
   1277     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
   1278         return EGL_FALSE;
   1279 
   1280     if (!(surfaceType & EGL_PIXMAP_BIT))
   1281         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1282 
   1283     if (static_cast<egl_native_pixmap_t*>(pixmap)->version !=
   1284             sizeof(egl_native_pixmap_t)) {
   1285         return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
   1286     }
   1287 
   1288     EGLint configID;
   1289     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
   1290         return EGL_FALSE;
   1291 
   1292     int32_t depthFormat;
   1293     int32_t pixelFormat;
   1294     if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
   1295         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1296     }
   1297 
   1298     if (pixmap->format != pixelFormat)
   1299         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1300 
   1301     egl_surface_t* surface =
   1302         new egl_pixmap_surface_t(dpy, config, depthFormat,
   1303                 static_cast<egl_native_pixmap_t*>(pixmap));
   1304 
   1305     if (!surface->initCheck()) {
   1306         // there was a problem in the ctor, the error
   1307         // flag has been set.
   1308         delete surface;
   1309         surface = 0;
   1310     }
   1311     return surface;
   1312 }
   1313 
   1314 static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
   1315         const EGLint *attrib_list)
   1316 {
   1317     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1318         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1319 
   1320     EGLint surfaceType;
   1321     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
   1322         return EGL_FALSE;
   1323 
   1324     if (!(surfaceType & EGL_PBUFFER_BIT))
   1325         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1326 
   1327     EGLint configID;
   1328     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
   1329         return EGL_FALSE;
   1330 
   1331     int32_t depthFormat;
   1332     int32_t pixelFormat;
   1333     if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
   1334         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
   1335     }
   1336 
   1337     int32_t w = 0;
   1338     int32_t h = 0;
   1339     while (attrib_list[0]) {
   1340         if (attrib_list[0] == EGL_WIDTH)  w = attrib_list[1];
   1341         if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
   1342         attrib_list+=2;
   1343     }
   1344 
   1345     egl_surface_t* surface =
   1346         new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
   1347 
   1348     if (!surface->initCheck()) {
   1349         // there was a problem in the ctor, the error
   1350         // flag has been set.
   1351         delete surface;
   1352         surface = 0;
   1353     }
   1354     return surface;
   1355 }
   1356 
   1357 // ----------------------------------------------------------------------------
   1358 }; // namespace android
   1359 // ----------------------------------------------------------------------------
   1360 
   1361 using namespace android;
   1362 
   1363 // ----------------------------------------------------------------------------
   1364 // Initialization
   1365 // ----------------------------------------------------------------------------
   1366 
   1367 EGLDisplay eglGetDisplay(NativeDisplayType display)
   1368 {
   1369 #ifndef HAVE_ANDROID_OS
   1370     // this just needs to be done once
   1371     if (gGLKey == -1) {
   1372         pthread_mutex_lock(&gInitMutex);
   1373         if (gGLKey == -1)
   1374             pthread_key_create(&gGLKey, NULL);
   1375         pthread_mutex_unlock(&gInitMutex);
   1376     }
   1377 #endif
   1378     if (display == EGL_DEFAULT_DISPLAY) {
   1379         EGLDisplay dpy = (EGLDisplay)1;
   1380         egl_display_t& d = egl_display_t::get_display(dpy);
   1381         d.type = display;
   1382         return dpy;
   1383     }
   1384     return EGL_NO_DISPLAY;
   1385 }
   1386 
   1387 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
   1388 {
   1389     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1390         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1391 
   1392     EGLBoolean res = EGL_TRUE;
   1393     egl_display_t& d = egl_display_t::get_display(dpy);
   1394 
   1395     if (android_atomic_inc(&d.initialized) == 0) {
   1396         // initialize stuff here if needed
   1397         //pthread_mutex_lock(&gInitMutex);
   1398         //pthread_mutex_unlock(&gInitMutex);
   1399     }
   1400 
   1401     if (res == EGL_TRUE) {
   1402         if (major != NULL) *major = VERSION_MAJOR;
   1403         if (minor != NULL) *minor = VERSION_MINOR;
   1404     }
   1405     return res;
   1406 }
   1407 
   1408 EGLBoolean eglTerminate(EGLDisplay dpy)
   1409 {
   1410     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1411         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1412 
   1413     EGLBoolean res = EGL_TRUE;
   1414     egl_display_t& d = egl_display_t::get_display(dpy);
   1415     if (android_atomic_dec(&d.initialized) == 1) {
   1416         // TODO: destroy all resources (surfaces, contexts, etc...)
   1417         //pthread_mutex_lock(&gInitMutex);
   1418         //pthread_mutex_unlock(&gInitMutex);
   1419     }
   1420     return res;
   1421 }
   1422 
   1423 // ----------------------------------------------------------------------------
   1424 // configuration
   1425 // ----------------------------------------------------------------------------
   1426 
   1427 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
   1428                             EGLConfig *configs,
   1429                             EGLint config_size, EGLint *num_config)
   1430 {
   1431     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1432         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1433 
   1434     GLint numConfigs = NELEM(gConfigs);
   1435     if (!configs) {
   1436         *num_config = numConfigs;
   1437         return EGL_TRUE;
   1438     }
   1439     GLint i;
   1440     for (i=0 ; i<numConfigs && i<config_size ; i++) {
   1441         *configs++ = (EGLConfig)i;
   1442     }
   1443     *num_config = i;
   1444     return EGL_TRUE;
   1445 }
   1446 
   1447 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
   1448                             EGLConfig *configs, EGLint config_size,
   1449                             EGLint *num_config)
   1450 {
   1451     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1452         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1453 
   1454     if (ggl_unlikely(num_config==0)) {
   1455         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1456     }
   1457 
   1458     if (ggl_unlikely(attrib_list==0)) {
   1459         /*
   1460          * A NULL attrib_list should be treated as though it was an empty
   1461          * one (terminated with EGL_NONE) as defined in
   1462          * section 3.4.1 "Querying Configurations" in the EGL specification.
   1463          */
   1464         static const EGLint dummy = EGL_NONE;
   1465         attrib_list = &dummy;
   1466     }
   1467 
   1468     int numAttributes = 0;
   1469     int numConfigs =  NELEM(gConfigs);
   1470     uint32_t possibleMatch = (1<<numConfigs)-1;
   1471     while(possibleMatch && *attrib_list != EGL_NONE) {
   1472         numAttributes++;
   1473         EGLint attr = *attrib_list++;
   1474         EGLint val  = *attrib_list++;
   1475         for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
   1476             if (!(possibleMatch & (1<<i)))
   1477                 continue;
   1478             if (isAttributeMatching(i, attr, val) == 0) {
   1479                 possibleMatch &= ~(1<<i);
   1480             }
   1481         }
   1482     }
   1483 
   1484     // now, handle the attributes which have a useful default value
   1485     for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
   1486         // see if this attribute was specified, if not, apply its
   1487         // default value
   1488         if (binarySearch<config_pair_t>(
   1489                 (config_pair_t const*)attrib_list,
   1490                 0, numAttributes-1,
   1491                 config_defaults[j].key) < 0)
   1492         {
   1493             for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
   1494                 if (!(possibleMatch & (1<<i)))
   1495                     continue;
   1496                 if (isAttributeMatching(i,
   1497                         config_defaults[j].key,
   1498                         config_defaults[j].value) == 0)
   1499                 {
   1500                     possibleMatch &= ~(1<<i);
   1501                 }
   1502             }
   1503         }
   1504     }
   1505 
   1506     // return the configurations found
   1507     int n=0;
   1508     if (possibleMatch) {
   1509         if (configs) {
   1510             for (int i=0 ; config_size && i<numConfigs ; i++) {
   1511                 if (possibleMatch & (1<<i)) {
   1512                     *configs++ = (EGLConfig)i;
   1513                     config_size--;
   1514                     n++;
   1515                 }
   1516             }
   1517         } else {
   1518             for (int i=0 ; i<numConfigs ; i++) {
   1519                 if (possibleMatch & (1<<i)) {
   1520                     n++;
   1521                 }
   1522             }
   1523         }
   1524     }
   1525     *num_config = n;
   1526      return EGL_TRUE;
   1527 }
   1528 
   1529 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
   1530         EGLint attribute, EGLint *value)
   1531 {
   1532     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1533         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1534 
   1535     return getConfigAttrib(dpy, config, attribute, value);
   1536 }
   1537 
   1538 // ----------------------------------------------------------------------------
   1539 // surfaces
   1540 // ----------------------------------------------------------------------------
   1541 
   1542 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
   1543                                     NativeWindowType window,
   1544                                     const EGLint *attrib_list)
   1545 {
   1546     return createWindowSurface(dpy, config, window, attrib_list);
   1547 }
   1548 
   1549 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
   1550                                     NativePixmapType pixmap,
   1551                                     const EGLint *attrib_list)
   1552 {
   1553     return createPixmapSurface(dpy, config, pixmap, attrib_list);
   1554 }
   1555 
   1556 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
   1557                                     const EGLint *attrib_list)
   1558 {
   1559     return createPbufferSurface(dpy, config, attrib_list);
   1560 }
   1561 
   1562 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
   1563 {
   1564     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1565         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1566     if (eglSurface != EGL_NO_SURFACE) {
   1567         egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
   1568         if (!surface->isValid())
   1569             return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1570         if (surface->dpy != dpy)
   1571             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1572         if (surface->ctx) {
   1573             // FIXME: this surface is current check what the spec says
   1574             surface->disconnect();
   1575             surface->ctx = 0;
   1576         }
   1577         delete surface;
   1578     }
   1579     return EGL_TRUE;
   1580 }
   1581 
   1582 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
   1583                             EGLint attribute, EGLint *value)
   1584 {
   1585     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1586         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1587     egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
   1588     if (!surface->isValid())
   1589         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1590     if (surface->dpy != dpy)
   1591         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1592 
   1593     EGLBoolean ret = EGL_TRUE;
   1594     switch (attribute) {
   1595         case EGL_CONFIG_ID:
   1596             ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
   1597             break;
   1598         case EGL_WIDTH:
   1599             *value = surface->getWidth();
   1600             break;
   1601         case EGL_HEIGHT:
   1602             *value = surface->getHeight();
   1603             break;
   1604         case EGL_LARGEST_PBUFFER:
   1605             // not modified for a window or pixmap surface
   1606             break;
   1607         case EGL_TEXTURE_FORMAT:
   1608             *value = EGL_NO_TEXTURE;
   1609             break;
   1610         case EGL_TEXTURE_TARGET:
   1611             *value = EGL_NO_TEXTURE;
   1612             break;
   1613         case EGL_MIPMAP_TEXTURE:
   1614             *value = EGL_FALSE;
   1615             break;
   1616         case EGL_MIPMAP_LEVEL:
   1617             *value = 0;
   1618             break;
   1619         case EGL_RENDER_BUFFER:
   1620             // TODO: return the real RENDER_BUFFER here
   1621             *value = EGL_BACK_BUFFER;
   1622             break;
   1623         case EGL_HORIZONTAL_RESOLUTION:
   1624             // pixel/mm * EGL_DISPLAY_SCALING
   1625             *value = surface->getHorizontalResolution();
   1626             break;
   1627         case EGL_VERTICAL_RESOLUTION:
   1628             // pixel/mm * EGL_DISPLAY_SCALING
   1629             *value = surface->getVerticalResolution();
   1630             break;
   1631         case EGL_PIXEL_ASPECT_RATIO: {
   1632             // w/h * EGL_DISPLAY_SCALING
   1633             int wr = surface->getHorizontalResolution();
   1634             int hr = surface->getVerticalResolution();
   1635             *value = (wr * EGL_DISPLAY_SCALING) / hr;
   1636         } break;
   1637         case EGL_SWAP_BEHAVIOR:
   1638             *value = surface->getSwapBehavior();
   1639             break;
   1640         default:
   1641             ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1642     }
   1643     return ret;
   1644 }
   1645 
   1646 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
   1647                             EGLContext share_list, const EGLint *attrib_list)
   1648 {
   1649     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1650         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1651 
   1652     ogles_context_t* gl = ogles_init(sizeof(egl_context_t));
   1653     if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
   1654 
   1655     egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
   1656     c->flags = egl_context_t::NEVER_CURRENT;
   1657     c->dpy = dpy;
   1658     c->config = config;
   1659     c->read = 0;
   1660     c->draw = 0;
   1661     return (EGLContext)gl;
   1662 }
   1663 
   1664 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
   1665 {
   1666     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1667         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1668     egl_context_t* c = egl_context_t::context(ctx);
   1669     if (c->flags & egl_context_t::IS_CURRENT)
   1670         setGlThreadSpecific(0);
   1671     ogles_uninit((ogles_context_t*)ctx);
   1672     return EGL_TRUE;
   1673 }
   1674 
   1675 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
   1676                             EGLSurface read, EGLContext ctx)
   1677 {
   1678     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1679         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1680     if (draw) {
   1681         egl_surface_t* s = (egl_surface_t*)draw;
   1682         if (!s->isValid())
   1683             return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1684         if (s->dpy != dpy)
   1685             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1686         // TODO: check that draw is compatible with the context
   1687     }
   1688     if (read && read!=draw) {
   1689         egl_surface_t* s = (egl_surface_t*)read;
   1690         if (!s->isValid())
   1691             return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1692         if (s->dpy != dpy)
   1693             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1694         // TODO: check that read is compatible with the context
   1695     }
   1696 
   1697     EGLContext current_ctx = EGL_NO_CONTEXT;
   1698 
   1699     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
   1700         return setError(EGL_BAD_MATCH, EGL_FALSE);
   1701 
   1702     if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
   1703         return setError(EGL_BAD_MATCH, EGL_FALSE);
   1704 
   1705     if (ctx == EGL_NO_CONTEXT) {
   1706         // if we're detaching, we need the current context
   1707         current_ctx = (EGLContext)getGlThreadSpecific();
   1708     } else {
   1709         egl_context_t* c = egl_context_t::context(ctx);
   1710         egl_surface_t* d = (egl_surface_t*)draw;
   1711         egl_surface_t* r = (egl_surface_t*)read;
   1712         if ((d && d->ctx && d->ctx != ctx) ||
   1713             (r && r->ctx && r->ctx != ctx)) {
   1714             // one of the surface is bound to a context in another thread
   1715             return setError(EGL_BAD_ACCESS, EGL_FALSE);
   1716         }
   1717     }
   1718 
   1719     ogles_context_t* gl = (ogles_context_t*)ctx;
   1720     if (makeCurrent(gl) == 0) {
   1721         if (ctx) {
   1722             egl_context_t* c = egl_context_t::context(ctx);
   1723             egl_surface_t* d = (egl_surface_t*)draw;
   1724             egl_surface_t* r = (egl_surface_t*)read;
   1725 
   1726             if (c->draw) {
   1727                 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
   1728                 s->disconnect();
   1729             }
   1730             if (c->read) {
   1731                 // FIXME: unlock/disconnect the read surface too
   1732             }
   1733 
   1734             c->draw = draw;
   1735             c->read = read;
   1736 
   1737             if (c->flags & egl_context_t::NEVER_CURRENT) {
   1738                 c->flags &= ~egl_context_t::NEVER_CURRENT;
   1739                 GLint w = 0;
   1740                 GLint h = 0;
   1741                 if (draw) {
   1742                     w = d->getWidth();
   1743                     h = d->getHeight();
   1744                 }
   1745                 ogles_surfaceport(gl, 0, 0);
   1746                 ogles_viewport(gl, 0, 0, w, h);
   1747                 ogles_scissor(gl, 0, 0, w, h);
   1748             }
   1749             if (d) {
   1750                 if (d->connect() == EGL_FALSE) {
   1751                     return EGL_FALSE;
   1752                 }
   1753                 d->ctx = ctx;
   1754                 d->bindDrawSurface(gl);
   1755             }
   1756             if (r) {
   1757                 // FIXME: lock/connect the read surface too
   1758                 r->ctx = ctx;
   1759                 r->bindReadSurface(gl);
   1760             }
   1761         } else {
   1762             // if surfaces were bound to the context bound to this thread
   1763             // mark then as unbound.
   1764             if (current_ctx) {
   1765                 egl_context_t* c = egl_context_t::context(current_ctx);
   1766                 egl_surface_t* d = (egl_surface_t*)c->draw;
   1767                 egl_surface_t* r = (egl_surface_t*)c->read;
   1768                 if (d) {
   1769                     c->draw = 0;
   1770                     d->ctx = EGL_NO_CONTEXT;
   1771                     d->disconnect();
   1772                 }
   1773                 if (r) {
   1774                     c->read = 0;
   1775                     r->ctx = EGL_NO_CONTEXT;
   1776                     // FIXME: unlock/disconnect the read surface too
   1777                 }
   1778             }
   1779         }
   1780         return EGL_TRUE;
   1781     }
   1782     return setError(EGL_BAD_ACCESS, EGL_FALSE);
   1783 }
   1784 
   1785 EGLContext eglGetCurrentContext(void)
   1786 {
   1787     // eglGetCurrentContext returns the current EGL rendering context,
   1788     // as specified by eglMakeCurrent. If no context is current,
   1789     // EGL_NO_CONTEXT is returned.
   1790     return (EGLContext)getGlThreadSpecific();
   1791 }
   1792 
   1793 EGLSurface eglGetCurrentSurface(EGLint readdraw)
   1794 {
   1795     // eglGetCurrentSurface returns the read or draw surface attached
   1796     // to the current EGL rendering context, as specified by eglMakeCurrent.
   1797     // If no context is current, EGL_NO_SURFACE is returned.
   1798     EGLContext ctx = (EGLContext)getGlThreadSpecific();
   1799     if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
   1800     egl_context_t* c = egl_context_t::context(ctx);
   1801     if (readdraw == EGL_READ) {
   1802         return c->read;
   1803     } else if (readdraw == EGL_DRAW) {
   1804         return c->draw;
   1805     }
   1806     return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
   1807 }
   1808 
   1809 EGLDisplay eglGetCurrentDisplay(void)
   1810 {
   1811     // eglGetCurrentDisplay returns the current EGL display connection
   1812     // for the current EGL rendering context, as specified by eglMakeCurrent.
   1813     // If no context is current, EGL_NO_DISPLAY is returned.
   1814     EGLContext ctx = (EGLContext)getGlThreadSpecific();
   1815     if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
   1816     egl_context_t* c = egl_context_t::context(ctx);
   1817     return c->dpy;
   1818 }
   1819 
   1820 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
   1821                             EGLint attribute, EGLint *value)
   1822 {
   1823     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1824         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1825     egl_context_t* c = egl_context_t::context(ctx);
   1826     switch (attribute) {
   1827         case EGL_CONFIG_ID:
   1828             // Returns the ID of the EGL frame buffer configuration with
   1829             // respect to which the context was created
   1830             return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
   1831     }
   1832     return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   1833 }
   1834 
   1835 EGLBoolean eglWaitGL(void)
   1836 {
   1837     return EGL_TRUE;
   1838 }
   1839 
   1840 EGLBoolean eglWaitNative(EGLint engine)
   1841 {
   1842     return EGL_TRUE;
   1843 }
   1844 
   1845 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
   1846 {
   1847     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1848         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1849 
   1850     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
   1851     if (!d->isValid())
   1852         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   1853     if (d->dpy != dpy)
   1854         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1855 
   1856     // post the surface
   1857     d->swapBuffers();
   1858 
   1859     // if it's bound to a context, update the buffer
   1860     if (d->ctx != EGL_NO_CONTEXT) {
   1861         d->bindDrawSurface((ogles_context_t*)d->ctx);
   1862         // if this surface is also the read surface of the context
   1863         // it is bound to, make sure to update the read buffer as well.
   1864         // The EGL spec is a little unclear about this.
   1865         egl_context_t* c = egl_context_t::context(d->ctx);
   1866         if (c->read == draw) {
   1867             d->bindReadSurface((ogles_context_t*)d->ctx);
   1868         }
   1869     }
   1870 
   1871     return EGL_TRUE;
   1872 }
   1873 
   1874 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
   1875                             NativePixmapType target)
   1876 {
   1877     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1878         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1879     // TODO: eglCopyBuffers()
   1880     return EGL_FALSE;
   1881 }
   1882 
   1883 EGLint eglGetError(void)
   1884 {
   1885     return getError();
   1886 }
   1887 
   1888 const char* eglQueryString(EGLDisplay dpy, EGLint name)
   1889 {
   1890     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1891         return setError(EGL_BAD_DISPLAY, (const char*)0);
   1892 
   1893     switch (name) {
   1894         case EGL_VENDOR:
   1895             return gVendorString;
   1896         case EGL_VERSION:
   1897             return gVersionString;
   1898         case EGL_EXTENSIONS:
   1899             return gExtensionsString;
   1900         case EGL_CLIENT_APIS:
   1901             return gClientApiString;
   1902     }
   1903     return setError(EGL_BAD_PARAMETER, (const char *)0);
   1904 }
   1905 
   1906 // ----------------------------------------------------------------------------
   1907 // EGL 1.1
   1908 // ----------------------------------------------------------------------------
   1909 
   1910 EGLBoolean eglSurfaceAttrib(
   1911         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
   1912 {
   1913     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1914         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1915     // TODO: eglSurfaceAttrib()
   1916     return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1917 }
   1918 
   1919 EGLBoolean eglBindTexImage(
   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: eglBindTexImage()
   1925     return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1926 }
   1927 
   1928 EGLBoolean eglReleaseTexImage(
   1929         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
   1930 {
   1931     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1932         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1933     // TODO: eglReleaseTexImage()
   1934     return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1935 }
   1936 
   1937 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
   1938 {
   1939     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1940         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   1941     // TODO: eglSwapInterval()
   1942     return EGL_TRUE;
   1943 }
   1944 
   1945 // ----------------------------------------------------------------------------
   1946 // EGL 1.2
   1947 // ----------------------------------------------------------------------------
   1948 
   1949 EGLBoolean eglBindAPI(EGLenum api)
   1950 {
   1951     if (api != EGL_OPENGL_ES_API)
   1952         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   1953     return EGL_TRUE;
   1954 }
   1955 
   1956 EGLenum eglQueryAPI(void)
   1957 {
   1958     return EGL_OPENGL_ES_API;
   1959 }
   1960 
   1961 EGLBoolean eglWaitClient(void)
   1962 {
   1963     glFinish();
   1964     return EGL_TRUE;
   1965 }
   1966 
   1967 EGLBoolean eglReleaseThread(void)
   1968 {
   1969     // TODO: eglReleaseThread()
   1970     return EGL_TRUE;
   1971 }
   1972 
   1973 EGLSurface eglCreatePbufferFromClientBuffer(
   1974           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
   1975           EGLConfig config, const EGLint *attrib_list)
   1976 {
   1977     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   1978         return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
   1979     // TODO: eglCreatePbufferFromClientBuffer()
   1980     return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
   1981 }
   1982 
   1983 // ----------------------------------------------------------------------------
   1984 // EGL_EGLEXT_VERSION 3
   1985 // ----------------------------------------------------------------------------
   1986 
   1987 void (*eglGetProcAddress (const char *procname))()
   1988 {
   1989     extention_map_t const * const map = gExtentionMap;
   1990     for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
   1991         if (!strcmp(procname, map[i].name)) {
   1992             return map[i].address;
   1993         }
   1994     }
   1995     return NULL;
   1996 }
   1997 
   1998 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
   1999         const EGLint *attrib_list)
   2000 {
   2001     EGLBoolean result = EGL_FALSE;
   2002     return result;
   2003 }
   2004 
   2005 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
   2006 {
   2007     EGLBoolean result = EGL_FALSE;
   2008     return result;
   2009 }
   2010 
   2011 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
   2012         EGLClientBuffer buffer, const EGLint *attrib_list)
   2013 {
   2014     if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
   2015         return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
   2016     }
   2017     if (ctx != EGL_NO_CONTEXT) {
   2018         return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
   2019     }
   2020     if (target != EGL_NATIVE_BUFFER_ANDROID) {
   2021         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2022     }
   2023 
   2024     ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;
   2025 
   2026     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   2027         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2028 
   2029     if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
   2030         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2031 
   2032     switch (native_buffer->format) {
   2033         case HAL_PIXEL_FORMAT_RGBA_8888:
   2034         case HAL_PIXEL_FORMAT_RGBX_8888:
   2035         case HAL_PIXEL_FORMAT_RGB_888:
   2036         case HAL_PIXEL_FORMAT_RGB_565:
   2037         case HAL_PIXEL_FORMAT_BGRA_8888:
   2038         case HAL_PIXEL_FORMAT_RGBA_5551:
   2039         case HAL_PIXEL_FORMAT_RGBA_4444:
   2040             break;
   2041         default:
   2042             return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
   2043     }
   2044 
   2045     native_buffer->common.incRef(&native_buffer->common);
   2046     return (EGLImageKHR)native_buffer;
   2047 }
   2048 
   2049 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
   2050 {
   2051     if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
   2052         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2053     }
   2054 
   2055     ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img;
   2056 
   2057     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
   2058         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2059 
   2060     if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
   2061         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2062 
   2063     native_buffer->common.decRef(&native_buffer->common);
   2064 
   2065     return EGL_TRUE;
   2066 }
   2067 
   2068 // ----------------------------------------------------------------------------
   2069 // EGL_KHR_fence_sync
   2070 // ----------------------------------------------------------------------------
   2071 
   2072 #define FENCE_SYNC_HANDLE ((EGLSyncKHR)0xFE4CE)
   2073 
   2074 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
   2075         const EGLint *attrib_list)
   2076 {
   2077     if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
   2078         return setError(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
   2079     }
   2080 
   2081     if (type != EGL_SYNC_FENCE_KHR ||
   2082             (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
   2083         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
   2084     }
   2085 
   2086     if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
   2087         return setError(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
   2088     }
   2089 
   2090     // AGL is synchronous; nothing to do here.
   2091 
   2092     return FENCE_SYNC_HANDLE;
   2093 }
   2094 
   2095 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
   2096 {
   2097     if (sync != FENCE_SYNC_HANDLE) {
   2098         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2099     }
   2100 
   2101     return EGL_TRUE;
   2102 }
   2103 
   2104 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
   2105         EGLTimeKHR timeout)
   2106 {
   2107     if (sync != FENCE_SYNC_HANDLE) {
   2108         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2109     }
   2110 
   2111     return EGL_CONDITION_SATISFIED_KHR;
   2112 }
   2113 
   2114 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
   2115         EGLint attribute, EGLint *value)
   2116 {
   2117     if (sync != FENCE_SYNC_HANDLE) {
   2118         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
   2119     }
   2120 
   2121     switch (attribute) {
   2122     case EGL_SYNC_TYPE_KHR:
   2123         *value = EGL_SYNC_FENCE_KHR;
   2124         return EGL_TRUE;
   2125     case EGL_SYNC_STATUS_KHR:
   2126         *value = EGL_SIGNALED_KHR;
   2127         return EGL_TRUE;
   2128     case EGL_SYNC_CONDITION_KHR:
   2129         *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
   2130         return EGL_TRUE;
   2131     default:
   2132         return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
   2133     }
   2134 }
   2135 
   2136 // ----------------------------------------------------------------------------
   2137 // ANDROID extensions
   2138 // ----------------------------------------------------------------------------
   2139 
   2140 EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
   2141         EGLint left, EGLint top, EGLint width, EGLint height)
   2142 {
   2143     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
   2144         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2145 
   2146     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
   2147     if (!d->isValid())
   2148         return setError(EGL_BAD_SURFACE, EGL_FALSE);
   2149     if (d->dpy != dpy)
   2150         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
   2151 
   2152     // post the surface
   2153     d->setSwapRectangle(left, top, width, height);
   2154 
   2155     return EGL_TRUE;
   2156 }
   2157