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