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