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