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