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