egl.cpp revision e71212ba5397387100a578d23b15862518a7a859
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 <EGL/android_natives.h>
37#include <GLES/gl.h>
38#include <GLES/glext.h>
39
40#include <pixelflinger/format.h>
41#include <pixelflinger/pixelflinger.h>
42
43#include "context.h"
44#include "state.h"
45#include "texture.h"
46#include "matrix.h"
47
48#ifdef LIBAGL_USE_GRALLOC_COPYBITS
49#include "gralloc_priv.h"
50#endif // LIBAGL_USE_GRALLOC_COPYBITS
51
52#undef NELEM
53#define NELEM(x) (sizeof(x)/sizeof(*(x)))
54
55// ----------------------------------------------------------------------------
56namespace android {
57// ----------------------------------------------------------------------------
58
59const unsigned int NUM_DISPLAYS = 1;
60
61static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
62static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
63static pthread_key_t gEGLErrorKey = -1;
64#ifndef HAVE_ANDROID_OS
65namespace gl {
66pthread_key_t gGLKey = -1;
67}; // namespace gl
68#endif
69
70template<typename T>
71static 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
82static 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
92struct 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
106static egl_display_t gDisplays[NUM_DISPLAYS];
107
108egl_display_t& egl_display_t::get_display(EGLDisplay dpy) {
109    return gDisplays[uintptr_t(dpy)-1U];
110}
111
112struct 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
131struct 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    virtual     bool    isValid() const = 0;
146
147    virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl) = 0;
148    virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl) = 0;
149    virtual     void        connect() {}
150    virtual     void        disconnect() {}
151    virtual     EGLint      getWidth() const = 0;
152    virtual     EGLint      getHeight() const = 0;
153
154    virtual     EGLint      getHorizontalResolution() const;
155    virtual     EGLint      getVerticalResolution() const;
156    virtual     EGLint      getRefreshRate() const;
157    virtual     EGLint      getSwapBehavior() const;
158    virtual     EGLBoolean  swapBuffers();
159protected:
160    GGLSurface              depth;
161};
162
163egl_surface_t::egl_surface_t(EGLDisplay dpy,
164        EGLConfig config,
165        int32_t depthFormat)
166    : magic(MAGIC), dpy(dpy), config(config), ctx(0)
167{
168    depth.version = sizeof(GGLSurface);
169    depth.data = 0;
170    depth.format = depthFormat;
171}
172egl_surface_t::~egl_surface_t()
173{
174    magic = 0;
175    free(depth.data);
176}
177EGLBoolean egl_surface_t::swapBuffers() {
178    return EGL_FALSE;
179}
180EGLint egl_surface_t::getHorizontalResolution() const {
181    return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
182}
183EGLint egl_surface_t::getVerticalResolution() const {
184    return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
185}
186EGLint egl_surface_t::getRefreshRate() const {
187    return (60 * EGL_DISPLAY_SCALING);
188}
189EGLint egl_surface_t::getSwapBehavior() const {
190    return EGL_BUFFER_PRESERVED;
191}
192
193// ----------------------------------------------------------------------------
194
195struct egl_window_surface_v2_t : public egl_surface_t
196{
197    egl_window_surface_v2_t(
198            EGLDisplay dpy, EGLConfig config,
199            int32_t depthFormat,
200            android_native_window_t* window);
201
202     ~egl_window_surface_v2_t();
203
204    virtual     bool        isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; }
205    virtual     EGLBoolean  swapBuffers();
206    virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
207    virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
208    virtual     void        connect();
209    virtual     void        disconnect();
210    virtual     EGLint      getWidth() const    { return buffer->width;  }
211    virtual     EGLint      getHeight() const   { return buffer->height; }
212    virtual     EGLint      getHorizontalResolution() const;
213    virtual     EGLint      getVerticalResolution() const;
214    virtual     EGLint      getRefreshRate() const;
215    virtual     EGLint      getSwapBehavior() const;
216
217private:
218    status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
219    status_t unlock(android_native_buffer_t* buf);
220    android_native_window_t*   nativeWindow;
221    android_native_buffer_t*   buffer;
222    gralloc_module_t const*    module;
223    int width;
224    int height;
225    void* bits;
226};
227
228egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
229        EGLConfig config,
230        int32_t depthFormat,
231        android_native_window_t* window)
232    : egl_surface_t(dpy, config, depthFormat),
233    nativeWindow(window), buffer(0), module(0), bits(NULL)
234{
235    hw_module_t const* pModule;
236    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
237    module = reinterpret_cast<gralloc_module_t const*>(pModule);
238
239    nativeWindow->common.incRef(&nativeWindow->common);
240
241    nativeWindow->dequeueBuffer(nativeWindow, &buffer);
242
243    width = buffer->width;
244    height = buffer->height;
245    if (depthFormat) {
246        depth.width   = width;
247        depth.height  = height;
248        depth.stride  = depth.width; // use the width here
249        depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
250        if (depth.data == 0) {
251            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
252            return;
253        }
254    }
255
256    buffer->common.incRef(&buffer->common);
257}
258
259void egl_window_surface_v2_t::connect()
260{
261    // Lock the buffer
262    nativeWindow->lockBuffer(nativeWindow, buffer);
263    lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits);
264}
265
266void egl_window_surface_v2_t::disconnect()
267{
268    if (buffer) {
269        bits = NULL;
270        unlock(buffer);
271    }
272}
273
274status_t egl_window_surface_v2_t::lock(
275        android_native_buffer_t* buf, int usage, void** vaddr)
276{
277    int err;
278    buffer_handle_t bufferHandle;
279    err = buf->getHandle(buf, &bufferHandle);
280    if (err < 0)
281        return err;
282
283    err = module->lock(module, bufferHandle,
284            usage, 0, 0, buf->width, buf->height, vaddr);
285    return err;
286}
287
288status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
289{
290    int err;
291    buffer_handle_t bufferHandle;
292    err = buf->getHandle(buf, &bufferHandle);
293    if (err < 0)
294        return err;
295
296    err = module->unlock(module, bufferHandle);
297    return err;
298}
299
300
301egl_window_surface_v2_t::~egl_window_surface_v2_t() {
302    if (buffer) {
303        buffer->common.decRef(&buffer->common);
304    }
305    nativeWindow->common.decRef(&nativeWindow->common);
306}
307
308EGLBoolean egl_window_surface_v2_t::swapBuffers()
309{
310    // TODO: this is roughly the code needed for preserving the back buffer
311    // efficiently. dirty is the area that has been modified.
312    //Region newDirty(dirty);
313    //newDirty.andSelf(Rect(nativeWindow->width, nativeWindow->height));
314    //mDirty = newDirty;
315    //const Region copyback(mDirty.subtract(newDirty));
316    //mDisplaySurface->copyFrontToBack(copyback);
317
318
319    unlock(buffer);
320    nativeWindow->queueBuffer(nativeWindow, buffer);
321    buffer->common.decRef(&buffer->common); buffer = 0;
322
323    nativeWindow->dequeueBuffer(nativeWindow, &buffer);
324    buffer->common.incRef(&buffer->common);
325
326    // TODO: lockBuffer should rather be executed when the very first
327    // direct rendering occurs.
328    void* vaddr;
329    nativeWindow->lockBuffer(nativeWindow, buffer);
330    lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits);
331
332    if ((width != buffer->width) || (height != buffer->height)) {
333        // TODO: we probably should reset the swap rect here
334        // if the window size has changed
335        width = buffer->width;
336        height = buffer->height;
337        if (depth.data) {
338            free(depth.data);
339            depth.width   = width;
340            depth.height  = height;
341            depth.stride  = buffer->stride;
342            depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
343            if (depth.data == 0) {
344                setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
345                return EGL_FALSE;
346            }
347        }
348    }
349    return EGL_TRUE;
350}
351
352#ifdef LIBAGL_USE_GRALLOC_COPYBITS
353
354static bool supportedCopybitsDestinationFormat(int format) {
355    // Hardware supported and no destination alpha
356    switch (format) {
357    case HAL_PIXEL_FORMAT_RGB_565:
358    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
359    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
360        return true;
361    default:
362        return false;
363    }
364}
365#endif
366
367EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
368{
369    GGLSurface buffer;
370    buffer.version = sizeof(GGLSurface);
371    buffer.width   = this->buffer->width;
372    buffer.height  = this->buffer->height;
373    buffer.stride  = this->buffer->stride;
374    buffer.data    = (GGLubyte*)bits;
375    buffer.format  = this->buffer->format;
376    gl->rasterizer.procs.colorBuffer(gl, &buffer);
377    if (depth.data != gl->rasterizer.state.buffers.depth.data)
378        gl->rasterizer.procs.depthBuffer(gl, &depth);
379#ifdef LIBAGL_USE_GRALLOC_COPYBITS
380    gl->copybits.drawSurfaceFd = -1;
381    if (supportedCopybitsDestinationFormat(buffer.format)) {
382        buffer_handle_t handle;
383        this->buffer->getHandle(this->buffer, &handle);
384        if (handle != NULL) {
385            private_handle_t* hand = private_handle_t::dynamicCast(handle);
386            if (hand != NULL) {
387                if (hand->usesPhysicallyContiguousMemory()) {
388                    gl->copybits.drawSurfaceFd = hand->fd;
389                }
390            }
391        }
392    }
393#endif // LIBAGL_USE_GRALLOC_COPYBITS
394    return EGL_TRUE;
395}
396EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
397{
398    GGLSurface buffer;
399    buffer.version = sizeof(GGLSurface);
400    buffer.width   = this->buffer->width;
401    buffer.height  = this->buffer->height;
402    buffer.stride  = this->buffer->stride;
403    buffer.data    = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
404    buffer.format  = this->buffer->format;
405    gl->rasterizer.procs.readBuffer(gl, &buffer);
406    return EGL_TRUE;
407}
408EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
409    return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
410}
411EGLint egl_window_surface_v2_t::getVerticalResolution() const {
412    return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
413}
414EGLint egl_window_surface_v2_t::getRefreshRate() const {
415    return (60 * EGL_DISPLAY_SCALING); // FIXME
416}
417EGLint egl_window_surface_v2_t::getSwapBehavior() const {
418    //uint32_t flags = nativeWindow->flags;
419    //if (flags & SURFACE_FLAG_PRESERVE_CONTENT)
420    //    return EGL_BUFFER_PRESERVED;
421    // This is now a feature of EGL, currently we don't preserve
422    // the content of the buffers.
423    return EGL_BUFFER_DESTROYED;
424}
425
426// ----------------------------------------------------------------------------
427
428struct egl_pixmap_surface_t : public egl_surface_t
429{
430    egl_pixmap_surface_t(
431            EGLDisplay dpy, EGLConfig config,
432            int32_t depthFormat,
433            egl_native_pixmap_t const * pixmap);
434
435    virtual ~egl_pixmap_surface_t() { }
436
437    virtual     bool        isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
438    virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
439    virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
440    virtual     EGLint      getWidth() const    { return nativePixmap.width;  }
441    virtual     EGLint      getHeight() const   { return nativePixmap.height; }
442private:
443    egl_native_pixmap_t     nativePixmap;
444};
445
446egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
447        EGLConfig config,
448        int32_t depthFormat,
449        egl_native_pixmap_t const * pixmap)
450    : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
451{
452    if (depthFormat) {
453        depth.width   = pixmap->width;
454        depth.height  = pixmap->height;
455        depth.stride  = depth.width; // use the width here
456        depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
457        if (depth.data == 0) {
458            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
459            return;
460        }
461    }
462}
463EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl)
464{
465    GGLSurface buffer;
466    buffer.version = sizeof(GGLSurface);
467    buffer.width   = nativePixmap.width;
468    buffer.height  = nativePixmap.height;
469    buffer.stride  = nativePixmap.stride;
470    buffer.data    = nativePixmap.data;
471    buffer.format  = nativePixmap.format;
472
473    gl->rasterizer.procs.colorBuffer(gl, &buffer);
474    if (depth.data != gl->rasterizer.state.buffers.depth.data)
475        gl->rasterizer.procs.depthBuffer(gl, &depth);
476    return EGL_TRUE;
477}
478EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl)
479{
480    GGLSurface buffer;
481    buffer.version = sizeof(GGLSurface);
482    buffer.width   = nativePixmap.width;
483    buffer.height  = nativePixmap.height;
484    buffer.stride  = nativePixmap.stride;
485    buffer.data    = nativePixmap.data;
486    buffer.format  = nativePixmap.format;
487    gl->rasterizer.procs.readBuffer(gl, &buffer);
488    return EGL_TRUE;
489}
490
491// ----------------------------------------------------------------------------
492
493struct egl_pbuffer_surface_t : public egl_surface_t
494{
495    egl_pbuffer_surface_t(
496            EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
497            int32_t w, int32_t h, int32_t f);
498
499    virtual ~egl_pbuffer_surface_t();
500
501    virtual     bool        isValid() const { return pbuffer.data != 0; }
502    virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
503    virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
504    virtual     EGLint      getWidth() const    { return pbuffer.width;  }
505    virtual     EGLint      getHeight() const   { return pbuffer.height; }
506private:
507    GGLSurface  pbuffer;
508};
509
510egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
511        EGLConfig config, int32_t depthFormat,
512        int32_t w, int32_t h, int32_t f)
513    : egl_surface_t(dpy, config, depthFormat)
514{
515    size_t size = w*h;
516    switch (f) {
517        case GGL_PIXEL_FORMAT_A_8:          size *= 1; break;
518        case GGL_PIXEL_FORMAT_RGB_565:      size *= 2; break;
519        case GGL_PIXEL_FORMAT_RGBA_8888:    size *= 4; break;
520        default:
521            LOGE("incompatible pixel format for pbuffer (format=%d)", f);
522            pbuffer.data = 0;
523            break;
524    }
525    pbuffer.version = sizeof(GGLSurface);
526    pbuffer.width   = w;
527    pbuffer.height  = h;
528    pbuffer.stride  = w;
529    pbuffer.data    = (GGLubyte*)malloc(size);
530    pbuffer.format  = f;
531
532    if (depthFormat) {
533        depth.width   = pbuffer.width;
534        depth.height  = pbuffer.height;
535        depth.stride  = depth.width; // use the width here
536        depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
537        if (depth.data == 0) {
538            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
539            return;
540        }
541    }
542}
543egl_pbuffer_surface_t::~egl_pbuffer_surface_t() {
544    free(pbuffer.data);
545}
546EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl)
547{
548    gl->rasterizer.procs.colorBuffer(gl, &pbuffer);
549    if (depth.data != gl->rasterizer.state.buffers.depth.data)
550        gl->rasterizer.procs.depthBuffer(gl, &depth);
551    return EGL_TRUE;
552}
553EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl)
554{
555    gl->rasterizer.procs.readBuffer(gl, &pbuffer);
556    return EGL_TRUE;
557}
558
559// ----------------------------------------------------------------------------
560
561struct config_pair_t {
562    GLint key;
563    GLint value;
564};
565
566struct configs_t {
567    const config_pair_t* array;
568    int                  size;
569};
570
571struct config_management_t {
572    GLint key;
573    bool (*match)(GLint reqValue, GLint confValue);
574    static bool atLeast(GLint reqValue, GLint confValue) {
575        return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
576    }
577    static bool exact(GLint reqValue, GLint confValue) {
578        return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
579    }
580    static bool mask(GLint reqValue, GLint confValue) {
581        return (confValue & reqValue) == reqValue;
582    }
583};
584
585// ----------------------------------------------------------------------------
586
587#define VERSION_MAJOR 1
588#define VERSION_MINOR 2
589static char const * const gVendorString     = "Google Inc.";
590static char const * const gVersionString    = "1.2 Android Driver";
591static char const * const gClientApiString  = "OpenGL ES";
592static char const * const gExtensionsString =
593        "KHR_image_base "
594        // "KHR_image_pixmap "
595        "EGL_ANDROID_image_native_buffer "
596        ;
597
598// ----------------------------------------------------------------------------
599
600struct extention_map_t {
601    const char * const name;
602    __eglMustCastToProperFunctionPointerType address;
603};
604
605static const extention_map_t gExtentionMap[] = {
606    { "glDrawTexsOES",
607            (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
608    { "glDrawTexiOES",
609            (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
610    { "glDrawTexfOES",
611            (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
612    { "glDrawTexxOES",
613            (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
614    { "glDrawTexsvOES",
615            (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
616    { "glDrawTexivOES",
617            (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
618    { "glDrawTexfvOES",
619            (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
620    { "glDrawTexxvOES",
621            (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
622    { "glQueryMatrixxOES",
623            (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
624    { "glEGLImageTargetTexture2DOES",
625            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
626    { "glEGLImageTargetRenderbufferStorageOES",
627            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
628    { "glClipPlanef",
629            (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
630    { "glClipPlanex",
631            (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
632    { "glBindBuffer",
633            (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
634    { "glBufferData",
635            (__eglMustCastToProperFunctionPointerType)&glBufferData },
636    { "glBufferSubData",
637            (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
638    { "glDeleteBuffers",
639            (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
640    { "glGenBuffers",
641            (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
642};
643
644/*
645 * In the lists below, attributes names MUST be sorted.
646 * Additionally, all configs must be sorted according to
647 * the EGL specification.
648 */
649
650static config_pair_t const config_base_attribute_list[] = {
651        { EGL_STENCIL_SIZE,               0                                 },
652        { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
653        { EGL_LEVEL,                      0                                 },
654        { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
655        { EGL_MAX_PBUFFER_PIXELS,
656                GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
657        { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
658        { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
659        { EGL_NATIVE_VISUAL_ID,           0                                 },
660        { EGL_NATIVE_VISUAL_TYPE,         GGL_PIXEL_FORMAT_RGB_565          },
661        { EGL_SAMPLES,                    0                                 },
662        { EGL_SAMPLE_BUFFERS,             0                                 },
663        { EGL_TRANSPARENT_TYPE,           EGL_NONE                          },
664        { EGL_TRANSPARENT_BLUE_VALUE,     0                                 },
665        { EGL_TRANSPARENT_GREEN_VALUE,    0                                 },
666        { EGL_TRANSPARENT_RED_VALUE,      0                                 },
667        { EGL_BIND_TO_TEXTURE_RGBA,       EGL_FALSE                         },
668        { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
669        { EGL_MIN_SWAP_INTERVAL,          1                                 },
670        { EGL_MAX_SWAP_INTERVAL,          4                                 },
671};
672
673// These configs can override the base attribute list
674// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
675
676static config_pair_t const config_0_attribute_list[] = {
677        { EGL_BUFFER_SIZE,     16 },
678        { EGL_ALPHA_SIZE,       0 },
679        { EGL_BLUE_SIZE,        5 },
680        { EGL_GREEN_SIZE,       6 },
681        { EGL_RED_SIZE,         5 },
682        { EGL_DEPTH_SIZE,       0 },
683        { EGL_CONFIG_ID,        0 },
684        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
685};
686
687static config_pair_t const config_1_attribute_list[] = {
688        { EGL_BUFFER_SIZE,     16 },
689        { EGL_ALPHA_SIZE,       0 },
690        { EGL_BLUE_SIZE,        5 },
691        { EGL_GREEN_SIZE,       6 },
692        { EGL_RED_SIZE,         5 },
693        { EGL_DEPTH_SIZE,      16 },
694        { EGL_CONFIG_ID,        1 },
695        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
696};
697
698static config_pair_t const config_2_attribute_list[] = {
699        { EGL_BUFFER_SIZE,     32 },
700        { EGL_ALPHA_SIZE,       8 },
701        { EGL_BLUE_SIZE,        8 },
702        { EGL_GREEN_SIZE,       8 },
703        { EGL_RED_SIZE,         8 },
704        { EGL_DEPTH_SIZE,       0 },
705        { EGL_CONFIG_ID,        2 },
706        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
707};
708
709static config_pair_t const config_3_attribute_list[] = {
710        { EGL_BUFFER_SIZE,     32 },
711        { EGL_ALPHA_SIZE,       8 },
712        { EGL_BLUE_SIZE,        8 },
713        { EGL_GREEN_SIZE,       8 },
714        { EGL_RED_SIZE,         8 },
715        { EGL_DEPTH_SIZE,      16 },
716        { EGL_CONFIG_ID,        3 },
717        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
718};
719
720static config_pair_t const config_4_attribute_list[] = {
721        { EGL_BUFFER_SIZE,      8 },
722        { EGL_ALPHA_SIZE,       8 },
723        { EGL_BLUE_SIZE,        0 },
724        { EGL_GREEN_SIZE,       0 },
725        { EGL_RED_SIZE,         0 },
726        { EGL_DEPTH_SIZE,       0 },
727        { EGL_CONFIG_ID,        4 },
728        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
729};
730
731static config_pair_t const config_5_attribute_list[] = {
732        { EGL_BUFFER_SIZE,      8 },
733        { EGL_ALPHA_SIZE,       8 },
734        { EGL_BLUE_SIZE,        0 },
735        { EGL_GREEN_SIZE,       0 },
736        { EGL_RED_SIZE,         0 },
737        { EGL_DEPTH_SIZE,      16 },
738        { EGL_CONFIG_ID,        5 },
739        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
740};
741
742static configs_t const gConfigs[] = {
743        { config_0_attribute_list, NELEM(config_0_attribute_list) },
744        { config_1_attribute_list, NELEM(config_1_attribute_list) },
745        { config_2_attribute_list, NELEM(config_2_attribute_list) },
746        { config_3_attribute_list, NELEM(config_3_attribute_list) },
747        { config_4_attribute_list, NELEM(config_4_attribute_list) },
748        { config_5_attribute_list, NELEM(config_5_attribute_list) },
749};
750
751static config_management_t const gConfigManagement[] = {
752        { EGL_BUFFER_SIZE,                config_management_t::atLeast },
753        { EGL_ALPHA_SIZE,                 config_management_t::atLeast },
754        { EGL_BLUE_SIZE,                  config_management_t::atLeast },
755        { EGL_GREEN_SIZE,                 config_management_t::atLeast },
756        { EGL_RED_SIZE,                   config_management_t::atLeast },
757        { EGL_DEPTH_SIZE,                 config_management_t::atLeast },
758        { EGL_STENCIL_SIZE,               config_management_t::atLeast },
759        { EGL_CONFIG_CAVEAT,              config_management_t::exact   },
760        { EGL_CONFIG_ID,                  config_management_t::exact   },
761        { EGL_LEVEL,                      config_management_t::exact   },
762        { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::exact   },
763        { EGL_MAX_PBUFFER_PIXELS,         config_management_t::exact   },
764        { EGL_MAX_PBUFFER_WIDTH,          config_management_t::exact   },
765        { EGL_NATIVE_RENDERABLE,          config_management_t::exact   },
766        { EGL_NATIVE_VISUAL_ID,           config_management_t::exact   },
767        { EGL_NATIVE_VISUAL_TYPE,         config_management_t::exact   },
768        { EGL_SAMPLES,                    config_management_t::exact   },
769        { EGL_SAMPLE_BUFFERS,             config_management_t::exact   },
770        { EGL_SURFACE_TYPE,               config_management_t::mask    },
771        { EGL_TRANSPARENT_TYPE,           config_management_t::exact   },
772        { EGL_TRANSPARENT_BLUE_VALUE,     config_management_t::exact   },
773        { EGL_TRANSPARENT_GREEN_VALUE,    config_management_t::exact   },
774        { EGL_TRANSPARENT_RED_VALUE,      config_management_t::exact   },
775        { EGL_BIND_TO_TEXTURE_RGBA,       config_management_t::exact   },
776        { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
777        { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
778        { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
779};
780
781static config_pair_t const config_defaults[] = {
782        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT },
783};
784
785// ----------------------------------------------------------------------------
786
787template<typename T>
788static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
789{
790   while (first <= last) {
791       int mid = (first + last) / 2;
792       if (key > sortedArray[mid].key) {
793           first = mid + 1;
794       } else if (key < sortedArray[mid].key) {
795           last = mid - 1;
796       } else {
797           return mid;
798       }
799   }
800   return -1;
801}
802
803static int isAttributeMatching(int i, EGLint attr, EGLint val)
804{
805    // look for the attribute in all of our configs
806    config_pair_t const* configFound = gConfigs[i].array;
807    int index = binarySearch<config_pair_t>(
808            gConfigs[i].array,
809            0, gConfigs[i].size-1,
810            attr);
811    if (index < 0) {
812        configFound = config_base_attribute_list;
813        index = binarySearch<config_pair_t>(
814                config_base_attribute_list,
815                0, NELEM(config_base_attribute_list)-1,
816                attr);
817    }
818    if (index >= 0) {
819        // attribute found, check if this config could match
820        int cfgMgtIndex = binarySearch<config_management_t>(
821                gConfigManagement,
822                0, NELEM(gConfigManagement)-1,
823                attr);
824        if (index >= 0) {
825            bool match = gConfigManagement[cfgMgtIndex].match(
826                    val, configFound[index].value);
827            if (match) {
828                // this config matches
829                return 1;
830            }
831        } else {
832            // attribute not found. this should NEVER happen.
833        }
834    } else {
835        // error, this attribute doesn't exist
836    }
837    return 0;
838}
839
840static int makeCurrent(ogles_context_t* gl)
841{
842    ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific();
843    if (gl) {
844        egl_context_t* c = egl_context_t::context(gl);
845        if (c->flags & egl_context_t::IS_CURRENT) {
846            if (current != gl) {
847                // it is an error to set a context current, if it's already
848                // current to another thread
849                return -1;
850            }
851        } else {
852            if (current) {
853                // mark the current context as not current, and flush
854                glFlush();
855                egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
856            }
857        }
858        if (!(c->flags & egl_context_t::IS_CURRENT)) {
859            // The context is not current, make it current!
860            setGlThreadSpecific(gl);
861            c->flags |= egl_context_t::IS_CURRENT;
862        }
863    } else {
864        if (current) {
865            // mark the current context as not current, and flush
866            glFlush();
867            egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
868        }
869        // this thread has no context attached to it
870        setGlThreadSpecific(0);
871    }
872    return 0;
873}
874
875static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
876        EGLint attribute, EGLint *value)
877{
878    size_t numConfigs =  NELEM(gConfigs);
879    int index = (int)config;
880    if (uint32_t(index) >= numConfigs)
881        return setError(EGL_BAD_CONFIG, EGL_FALSE);
882
883    int attrIndex;
884    attrIndex = binarySearch<config_pair_t>(
885            gConfigs[index].array,
886            0, gConfigs[index].size-1,
887            attribute);
888    if (attrIndex>=0) {
889        *value = gConfigs[index].array[attrIndex].value;
890        return EGL_TRUE;
891    }
892
893    attrIndex = binarySearch<config_pair_t>(
894            config_base_attribute_list,
895            0, NELEM(config_base_attribute_list)-1,
896            attribute);
897    if (attrIndex>=0) {
898        *value = config_base_attribute_list[attrIndex].value;
899        return EGL_TRUE;
900    }
901    return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
902}
903
904static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
905        NativeWindowType window, const EGLint *attrib_list)
906{
907    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
908        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
909    if (window == 0)
910        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
911
912    EGLint surfaceType;
913    if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
914        return EGL_FALSE;
915
916    if (!(surfaceType & EGL_WINDOW_BIT))
917        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
918
919    EGLint configID;
920    if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
921        return EGL_FALSE;
922
923    int32_t depthFormat;
924    int32_t pixelFormat;
925    switch(configID) {
926    case 0:
927        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
928        depthFormat = 0;
929        break;
930    case 1:
931        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
932        depthFormat = GGL_PIXEL_FORMAT_Z_16;
933        break;
934    case 2:
935        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
936        depthFormat = 0;
937        break;
938    case 3:
939        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
940        depthFormat = GGL_PIXEL_FORMAT_Z_16;
941        break;
942    case 4:
943        pixelFormat = GGL_PIXEL_FORMAT_A_8;
944        depthFormat = 0;
945        break;
946    case 5:
947        pixelFormat = GGL_PIXEL_FORMAT_A_8;
948        depthFormat = GGL_PIXEL_FORMAT_Z_16;
949        break;
950    default:
951        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
952    }
953
954    // FIXME: we don't have access to the pixelFormat here just yet.
955    // (it's possible that the surface is not fully initialized)
956    // maybe this should be done after the page-flip
957    //if (EGLint(info.format) != pixelFormat)
958    //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
959
960    egl_surface_t* surface;
961    surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
962            static_cast<android_native_window_t*>(window));
963
964    if (!surface->isValid()) {
965        // there was a problem in the ctor, the error
966        // flag has been set.
967        delete surface;
968        surface = 0;
969    }
970    return surface;
971}
972
973static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
974        NativePixmapType pixmap, const EGLint *attrib_list)
975{
976    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
977        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
978    if (pixmap == 0)
979        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
980
981    EGLint surfaceType;
982    if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
983        return EGL_FALSE;
984
985    if (!(surfaceType & EGL_PIXMAP_BIT))
986        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
987
988    EGLint configID;
989    if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
990        return EGL_FALSE;
991
992    int32_t depthFormat;
993    int32_t pixelFormat;
994    switch(configID) {
995    case 0:
996        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
997        depthFormat = 0;
998        break;
999    case 1:
1000        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1001        depthFormat = GGL_PIXEL_FORMAT_Z_16;
1002        break;
1003    case 2:
1004        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1005        depthFormat = 0;
1006        break;
1007    case 3:
1008        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1009        depthFormat = GGL_PIXEL_FORMAT_Z_16;
1010        break;
1011    case 4:
1012        pixelFormat = GGL_PIXEL_FORMAT_A_8;
1013        depthFormat = 0;
1014        break;
1015    case 5:
1016        pixelFormat = GGL_PIXEL_FORMAT_A_8;
1017        depthFormat = GGL_PIXEL_FORMAT_Z_16;
1018        break;
1019    default:
1020        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1021    }
1022
1023    if (pixmap->format != pixelFormat)
1024        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1025
1026    egl_surface_t* surface =
1027        new egl_pixmap_surface_t(dpy, config, depthFormat,
1028                static_cast<egl_native_pixmap_t*>(pixmap));
1029
1030    if (!surface->isValid()) {
1031        // there was a problem in the ctor, the error
1032        // flag has been set.
1033        delete surface;
1034        surface = 0;
1035    }
1036    return surface;
1037}
1038
1039static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
1040        const EGLint *attrib_list)
1041{
1042    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1043        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1044
1045    EGLint surfaceType;
1046    if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1047        return EGL_FALSE;
1048
1049    if (!(surfaceType & EGL_PBUFFER_BIT))
1050        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1051
1052    EGLint configID;
1053    if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1054        return EGL_FALSE;
1055
1056    int32_t depthFormat;
1057    int32_t pixelFormat;
1058    switch(configID) {
1059    case 0:
1060        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1061        depthFormat = 0;
1062        break;
1063    case 1:
1064        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1065        depthFormat = GGL_PIXEL_FORMAT_Z_16;
1066        break;
1067    case 2:
1068        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1069        depthFormat = 0;
1070        break;
1071    case 3:
1072        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1073        depthFormat = GGL_PIXEL_FORMAT_Z_16;
1074        break;
1075    case 4:
1076        pixelFormat = GGL_PIXEL_FORMAT_A_8;
1077        depthFormat = 0;
1078        break;
1079    case 5:
1080        pixelFormat = GGL_PIXEL_FORMAT_A_8;
1081        depthFormat = GGL_PIXEL_FORMAT_Z_16;
1082        break;
1083    default:
1084        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1085    }
1086
1087    int32_t w = 0;
1088    int32_t h = 0;
1089    while (attrib_list[0]) {
1090        if (attrib_list[0] == EGL_WIDTH)  w = attrib_list[1];
1091        if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
1092        attrib_list+=2;
1093    }
1094
1095    egl_surface_t* surface =
1096        new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
1097
1098    if (!surface->isValid()) {
1099        // there was a problem in the ctor, the error
1100        // flag has been set.
1101        delete surface;
1102        surface = 0;
1103    }
1104    return surface;
1105}
1106
1107// ----------------------------------------------------------------------------
1108}; // namespace android
1109// ----------------------------------------------------------------------------
1110
1111using namespace android;
1112
1113// ----------------------------------------------------------------------------
1114// Initialization
1115// ----------------------------------------------------------------------------
1116
1117EGLDisplay eglGetDisplay(NativeDisplayType display)
1118{
1119#ifndef HAVE_ANDROID_OS
1120    // this just needs to be done once
1121    if (gGLKey == -1) {
1122        pthread_mutex_lock(&gInitMutex);
1123        if (gGLKey == -1)
1124            pthread_key_create(&gGLKey, NULL);
1125        pthread_mutex_unlock(&gInitMutex);
1126    }
1127#endif
1128    if (display == EGL_DEFAULT_DISPLAY) {
1129        EGLDisplay dpy = (EGLDisplay)1;
1130        egl_display_t& d = egl_display_t::get_display(dpy);
1131        d.type = display;
1132        return dpy;
1133    }
1134    return EGL_NO_DISPLAY;
1135}
1136
1137EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
1138{
1139    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1140        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1141
1142    EGLBoolean res = EGL_TRUE;
1143    egl_display_t& d = egl_display_t::get_display(dpy);
1144
1145    if (android_atomic_inc(&d.initialized) == 0) {
1146        // initialize stuff here if needed
1147        //pthread_mutex_lock(&gInitMutex);
1148        //pthread_mutex_unlock(&gInitMutex);
1149    }
1150
1151    if (res == EGL_TRUE) {
1152        if (major != NULL) *major = VERSION_MAJOR;
1153        if (minor != NULL) *minor = VERSION_MINOR;
1154    }
1155    return res;
1156}
1157
1158EGLBoolean eglTerminate(EGLDisplay dpy)
1159{
1160    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1161        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1162
1163    EGLBoolean res = EGL_TRUE;
1164    egl_display_t& d = egl_display_t::get_display(dpy);
1165    if (android_atomic_dec(&d.initialized) == 1) {
1166        // TODO: destroy all resources (surfaces, contexts, etc...)
1167        //pthread_mutex_lock(&gInitMutex);
1168        //pthread_mutex_unlock(&gInitMutex);
1169    }
1170    return res;
1171}
1172
1173// ----------------------------------------------------------------------------
1174// configuration
1175// ----------------------------------------------------------------------------
1176
1177EGLBoolean eglGetConfigs(   EGLDisplay dpy,
1178                            EGLConfig *configs,
1179                            EGLint config_size, EGLint *num_config)
1180{
1181    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1182        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1183
1184    GLint numConfigs = NELEM(gConfigs);
1185    if (!configs) {
1186        *num_config = numConfigs;
1187        return EGL_TRUE;
1188    }
1189    GLint i;
1190    for (i=0 ; i<numConfigs && i<config_size ; i++) {
1191        *configs++ = (EGLConfig)i;
1192    }
1193    *num_config = i;
1194    return EGL_TRUE;
1195}
1196
1197EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
1198                            EGLConfig *configs, EGLint config_size,
1199                            EGLint *num_config)
1200{
1201    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1202        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1203
1204    if (ggl_unlikely(num_config==0)) {
1205        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1206    }
1207
1208    if (ggl_unlikely(attrib_list==0)) {
1209        *num_config = 0;
1210        return EGL_TRUE;
1211    }
1212
1213    int numAttributes = 0;
1214    int numConfigs =  NELEM(gConfigs);
1215    uint32_t possibleMatch = (1<<numConfigs)-1;
1216    while(possibleMatch && *attrib_list != EGL_NONE) {
1217        numAttributes++;
1218        EGLint attr = *attrib_list++;
1219        EGLint val  = *attrib_list++;
1220        for (int i=0 ; i<numConfigs ; i++) {
1221            if (!(possibleMatch & (1<<i)))
1222                continue;
1223            if (isAttributeMatching(i, attr, val) == 0) {
1224                possibleMatch &= ~(1<<i);
1225            }
1226        }
1227    }
1228
1229    // now, handle the attributes which have a useful default value
1230    for (size_t j=0 ; j<NELEM(config_defaults) ; j++) {
1231        // see if this attribute was specified, if not apply its
1232        // default value
1233        if (binarySearch<config_pair_t>(
1234                (config_pair_t const*)attrib_list,
1235                0, numAttributes,
1236                config_defaults[j].key) < 0)
1237        {
1238            for (int i=0 ; i<numConfigs ; i++) {
1239                if (!(possibleMatch & (1<<i)))
1240                    continue;
1241                if (isAttributeMatching(i,
1242                        config_defaults[j].key,
1243                        config_defaults[j].value) == 0)
1244                {
1245                    possibleMatch &= ~(1<<i);
1246                }
1247            }
1248        }
1249    }
1250
1251    // return the configurations found
1252    int n=0;
1253    if (possibleMatch) {
1254        if (configs) {
1255            for (int i=0 ; config_size && i<numConfigs ; i++) {
1256                if (possibleMatch & (1<<i)) {
1257                    *configs++ = (EGLConfig)i;
1258                    config_size--;
1259                    n++;
1260                }
1261            }
1262        } else {
1263            for (int i=0 ; i<numConfigs ; i++) {
1264                if (possibleMatch & (1<<i)) {
1265                    n++;
1266                }
1267            }
1268        }
1269    }
1270    *num_config = n;
1271     return EGL_TRUE;
1272}
1273
1274EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
1275        EGLint attribute, EGLint *value)
1276{
1277    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1278        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1279
1280    return getConfigAttrib(dpy, config, attribute, value);
1281}
1282
1283// ----------------------------------------------------------------------------
1284// surfaces
1285// ----------------------------------------------------------------------------
1286
1287EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
1288                                    NativeWindowType window,
1289                                    const EGLint *attrib_list)
1290{
1291    return createWindowSurface(dpy, config, window, attrib_list);
1292}
1293
1294EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
1295                                    NativePixmapType pixmap,
1296                                    const EGLint *attrib_list)
1297{
1298    return createPixmapSurface(dpy, config, pixmap, attrib_list);
1299}
1300
1301EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1302                                    const EGLint *attrib_list)
1303{
1304    return createPbufferSurface(dpy, config, attrib_list);
1305}
1306
1307EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1308{
1309    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1310        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1311    if (eglSurface != EGL_NO_SURFACE) {
1312        egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1313        if (surface->magic != egl_surface_t::MAGIC)
1314            return setError(EGL_BAD_SURFACE, EGL_FALSE);
1315        if (surface->dpy != dpy)
1316            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1317        if (surface->ctx) {
1318            // FIXME: this surface is current check what the spec says
1319            surface->disconnect();
1320            surface->ctx = 0;
1321        }
1322        delete surface;
1323    }
1324    return EGL_TRUE;
1325}
1326
1327EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
1328                            EGLint attribute, EGLint *value)
1329{
1330    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1331        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1332    egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
1333    if (surface->dpy != dpy)
1334        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1335
1336    EGLBoolean ret = EGL_TRUE;
1337    switch (attribute) {
1338        case EGL_CONFIG_ID:
1339            ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
1340            break;
1341        case EGL_WIDTH:
1342            *value = surface->getWidth();
1343            break;
1344        case EGL_HEIGHT:
1345            *value = surface->getHeight();
1346            break;
1347        case EGL_LARGEST_PBUFFER:
1348            // not modified for a window or pixmap surface
1349            break;
1350        case EGL_TEXTURE_FORMAT:
1351            *value = EGL_NO_TEXTURE;
1352            break;
1353        case EGL_TEXTURE_TARGET:
1354            *value = EGL_NO_TEXTURE;
1355            break;
1356        case EGL_MIPMAP_TEXTURE:
1357            *value = EGL_FALSE;
1358            break;
1359        case EGL_MIPMAP_LEVEL:
1360            *value = 0;
1361            break;
1362        case EGL_RENDER_BUFFER:
1363            // TODO: return the real RENDER_BUFFER here
1364            *value = EGL_BACK_BUFFER;
1365            break;
1366        case EGL_HORIZONTAL_RESOLUTION:
1367            // pixel/mm * EGL_DISPLAY_SCALING
1368            *value = surface->getHorizontalResolution();
1369            break;
1370        case EGL_VERTICAL_RESOLUTION:
1371            // pixel/mm * EGL_DISPLAY_SCALING
1372            *value = surface->getVerticalResolution();
1373            break;
1374        case EGL_PIXEL_ASPECT_RATIO: {
1375            // w/h * EGL_DISPLAY_SCALING
1376            int wr = surface->getHorizontalResolution();
1377            int hr = surface->getVerticalResolution();
1378            *value = (wr * EGL_DISPLAY_SCALING) / hr;
1379        } break;
1380        case EGL_SWAP_BEHAVIOR:
1381            *value = surface->getSwapBehavior();
1382            break;
1383        default:
1384            ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1385    }
1386    return ret;
1387}
1388
1389EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1390                            EGLContext share_list, const EGLint *attrib_list)
1391{
1392    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1393        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1394
1395    ogles_context_t* gl = ogles_init(sizeof(egl_context_t));
1396    if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1397
1398    egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
1399    c->flags = egl_context_t::NEVER_CURRENT;
1400    c->dpy = dpy;
1401    c->config = config;
1402    c->read = 0;
1403    c->draw = 0;
1404    return (EGLContext)gl;
1405}
1406
1407EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1408{
1409    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1410        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1411    egl_context_t* c = egl_context_t::context(ctx);
1412    if (c->flags & egl_context_t::IS_CURRENT)
1413        setGlThreadSpecific(0);
1414    ogles_uninit((ogles_context_t*)ctx);
1415    return EGL_TRUE;
1416}
1417
1418EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
1419                            EGLSurface read, EGLContext ctx)
1420{
1421    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1422        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1423    if (draw) {
1424        egl_surface_t* s = (egl_surface_t*)draw;
1425        if (s->dpy != dpy)
1426            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1427        // TODO: check that draw and read are compatible with the context
1428    }
1429
1430    EGLContext current_ctx = EGL_NO_CONTEXT;
1431
1432    if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1433        return setError(EGL_BAD_MATCH, EGL_FALSE);
1434
1435    if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1436        return setError(EGL_BAD_MATCH, EGL_FALSE);
1437
1438    if (ctx == EGL_NO_CONTEXT) {
1439        // if we're detaching, we need the current context
1440        current_ctx = (EGLContext)getGlThreadSpecific();
1441    } else {
1442        egl_context_t* c = egl_context_t::context(ctx);
1443        egl_surface_t* d = (egl_surface_t*)draw;
1444        egl_surface_t* r = (egl_surface_t*)read;
1445        if ((d && d->ctx && d->ctx != ctx) ||
1446            (r && r->ctx && r->ctx != ctx)) {
1447            // one of the surface is bound to a context in another thread
1448            return setError(EGL_BAD_ACCESS, EGL_FALSE);
1449        }
1450    }
1451
1452    ogles_context_t* gl = (ogles_context_t*)ctx;
1453    if (makeCurrent(gl) == 0) {
1454        if (ctx) {
1455            egl_context_t* c = egl_context_t::context(ctx);
1456            egl_surface_t* d = (egl_surface_t*)draw;
1457            egl_surface_t* r = (egl_surface_t*)read;
1458
1459            if (c->draw) {
1460                reinterpret_cast<egl_surface_t*>(c->draw)->disconnect();
1461            }
1462            if (c->read) {
1463                // FIXME: unlock/disconnect the read surface too
1464            }
1465
1466            c->draw = draw;
1467            c->read = read;
1468
1469            if (c->flags & egl_context_t::NEVER_CURRENT) {
1470                c->flags &= ~egl_context_t::NEVER_CURRENT;
1471                GLint w = 0;
1472                GLint h = 0;
1473                if (draw) {
1474                    w = d->getWidth();
1475                    h = d->getHeight();
1476                }
1477                ogles_surfaceport(gl, 0, 0);
1478                ogles_viewport(gl, 0, 0, w, h);
1479                ogles_scissor(gl, 0, 0, w, h);
1480            }
1481            if (d) {
1482                d->connect();
1483                d->ctx = ctx;
1484                d->bindDrawSurface(gl);
1485            }
1486            if (r) {
1487                // FIXME: lock/connect the read surface too
1488                r->ctx = ctx;
1489                r->bindReadSurface(gl);
1490            }
1491        } else {
1492            // if surfaces were bound to the context bound to this thread
1493            // mark then as unbound.
1494            if (current_ctx) {
1495                egl_context_t* c = egl_context_t::context(current_ctx);
1496                egl_surface_t* d = (egl_surface_t*)c->draw;
1497                egl_surface_t* r = (egl_surface_t*)c->read;
1498                if (d) {
1499                    d->ctx = EGL_NO_CONTEXT;
1500                    d->disconnect();
1501                }
1502                if (r) {
1503                    r->ctx = EGL_NO_CONTEXT;
1504                    // FIXME: unlock/disconnect the read surface too
1505                }
1506            }
1507        }
1508        return EGL_TRUE;
1509    }
1510    return setError(EGL_BAD_ACCESS, EGL_FALSE);
1511}
1512
1513EGLContext eglGetCurrentContext(void)
1514{
1515    // eglGetCurrentContext returns the current EGL rendering context,
1516    // as specified by eglMakeCurrent. If no context is current,
1517    // EGL_NO_CONTEXT is returned.
1518    return (EGLContext)getGlThreadSpecific();
1519}
1520
1521EGLSurface eglGetCurrentSurface(EGLint readdraw)
1522{
1523    // eglGetCurrentSurface returns the read or draw surface attached
1524    // to the current EGL rendering context, as specified by eglMakeCurrent.
1525    // If no context is current, EGL_NO_SURFACE is returned.
1526    EGLContext ctx = (EGLContext)getGlThreadSpecific();
1527    if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
1528    egl_context_t* c = egl_context_t::context(ctx);
1529    if (readdraw == EGL_READ) {
1530        return c->read;
1531    } else if (readdraw == EGL_DRAW) {
1532        return c->draw;
1533    }
1534    return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
1535}
1536
1537EGLDisplay eglGetCurrentDisplay(void)
1538{
1539    // eglGetCurrentDisplay returns the current EGL display connection
1540    // for the current EGL rendering context, as specified by eglMakeCurrent.
1541    // If no context is current, EGL_NO_DISPLAY is returned.
1542    EGLContext ctx = (EGLContext)getGlThreadSpecific();
1543    if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
1544    egl_context_t* c = egl_context_t::context(ctx);
1545    return c->dpy;
1546}
1547
1548EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1549                            EGLint attribute, EGLint *value)
1550{
1551    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1552        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1553    egl_context_t* c = egl_context_t::context(ctx);
1554    switch (attribute) {
1555        case EGL_CONFIG_ID:
1556            // Returns the ID of the EGL frame buffer configuration with
1557            // respect to which the context was created
1558            return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
1559    }
1560    return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1561}
1562
1563EGLBoolean eglWaitGL(void)
1564{
1565    return EGL_TRUE;
1566}
1567
1568EGLBoolean eglWaitNative(EGLint engine)
1569{
1570    return EGL_TRUE;
1571}
1572
1573EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1574{
1575    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1576        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1577
1578    egl_surface_t* d = static_cast<egl_surface_t*>(draw);
1579    if (d->dpy != dpy)
1580        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1581
1582    // post the surface
1583    d->swapBuffers();
1584
1585    // if it's bound to a context, update the buffer
1586    if (d->ctx != EGL_NO_CONTEXT) {
1587        d->bindDrawSurface((ogles_context_t*)d->ctx);
1588        // if this surface is also the read surface of the context
1589        // it is bound to, make sure to update the read buffer as well.
1590        // The EGL spec is a little unclear about this.
1591        egl_context_t* c = egl_context_t::context(d->ctx);
1592        if (c->read == draw) {
1593            d->bindReadSurface((ogles_context_t*)d->ctx);
1594        }
1595    }
1596
1597    return EGL_TRUE;
1598}
1599
1600EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1601                            NativePixmapType target)
1602{
1603    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1604        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1605    // TODO: eglCopyBuffers()
1606    return EGL_FALSE;
1607}
1608
1609EGLint eglGetError(void)
1610{
1611    return getError();
1612}
1613
1614const char* eglQueryString(EGLDisplay dpy, EGLint name)
1615{
1616    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1617        return setError(EGL_BAD_DISPLAY, (const char*)0);
1618
1619    switch (name) {
1620        case EGL_VENDOR:
1621            return gVendorString;
1622        case EGL_VERSION:
1623            return gVersionString;
1624        case EGL_EXTENSIONS:
1625            return gExtensionsString;
1626        case EGL_CLIENT_APIS:
1627            return gClientApiString;
1628    }
1629    return setError(EGL_BAD_PARAMETER, (const char *)0);
1630}
1631
1632// ----------------------------------------------------------------------------
1633// EGL 1.1
1634// ----------------------------------------------------------------------------
1635
1636EGLBoolean eglSurfaceAttrib(
1637        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1638{
1639    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1640        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1641    // TODO: eglSurfaceAttrib()
1642    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1643}
1644
1645EGLBoolean eglBindTexImage(
1646        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1647{
1648    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1649        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1650    // TODO: eglBindTexImage()
1651    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1652}
1653
1654EGLBoolean eglReleaseTexImage(
1655        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1656{
1657    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1658        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1659    // TODO: eglReleaseTexImage()
1660    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1661}
1662
1663EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1664{
1665    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1666        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1667    // TODO: eglSwapInterval()
1668    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1669}
1670
1671// ----------------------------------------------------------------------------
1672// EGL 1.2
1673// ----------------------------------------------------------------------------
1674
1675EGLBoolean eglBindAPI(EGLenum api)
1676{
1677    if (api != EGL_OPENGL_ES_API)
1678        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1679    return EGL_TRUE;
1680}
1681
1682EGLenum eglQueryAPI(void)
1683{
1684    return EGL_OPENGL_ES_API;
1685}
1686
1687EGLBoolean eglWaitClient(void)
1688{
1689    glFinish();
1690    return EGL_TRUE;
1691}
1692
1693EGLBoolean eglReleaseThread(void)
1694{
1695    // TODO: eglReleaseThread()
1696    return EGL_TRUE;
1697}
1698
1699EGLSurface eglCreatePbufferFromClientBuffer(
1700          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1701          EGLConfig config, const EGLint *attrib_list)
1702{
1703    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1704        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1705    // TODO: eglCreatePbufferFromClientBuffer()
1706    return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1707}
1708
1709// ----------------------------------------------------------------------------
1710// EGL_EGLEXT_VERSION 3
1711// ----------------------------------------------------------------------------
1712
1713void (*eglGetProcAddress (const char *procname))()
1714{
1715    extention_map_t const * const map = gExtentionMap;
1716    for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
1717        if (!strcmp(procname, map[i].name)) {
1718            return map[i].address;
1719        }
1720    }
1721    return NULL;
1722}
1723
1724EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1725        const EGLint *attrib_list)
1726{
1727    EGLBoolean result = EGL_FALSE;
1728    return result;
1729}
1730
1731EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1732{
1733    EGLBoolean result = EGL_FALSE;
1734    return result;
1735}
1736
1737EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1738        EGLClientBuffer buffer, const EGLint *attrib_list)
1739{
1740    if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
1741        return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1742    }
1743    if (ctx != EGL_NO_CONTEXT) {
1744        return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1745    }
1746    if (target != EGL_NATIVE_BUFFER_ANDROID) {
1747        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1748    }
1749
1750    android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
1751
1752    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1753        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1754
1755    if (native_buffer->common.version != sizeof(android_native_buffer_t))
1756        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1757
1758    native_buffer->common.incRef(&native_buffer->common);
1759    return (EGLImageKHR)native_buffer;
1760}
1761
1762EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1763{
1764    if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
1765        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1766    }
1767
1768    android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
1769
1770    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
1771        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1772
1773    if (native_buffer->common.version != sizeof(android_native_buffer_t))
1774        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1775
1776    native_buffer->common.decRef(&native_buffer->common);
1777
1778    return EGL_TRUE;
1779}
1780