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