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