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