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