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