OSDN Git Service

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