blob: d43b61b98a54899aa1fc39f7430088549aa550d9 [file] [log] [blame]
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002**
3** Copyright 2007 The Android Open Source Project
4**
Mathias Agopian076b1cc2009-04-10 14:24:30 -07005** 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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08008**
Mathias Agopian076b1cc2009-04-10 14:24:30 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080010**
Mathias Agopian076b1cc2009-04-10 14:24:30 -070011** 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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080018#include <assert.h>
Jesse Hall3aa75f92016-05-20 10:47:07 -070019#include <atomic>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080020#include <errno.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <sys/ioctl.h>
27#include <sys/types.h>
28#include <sys/mman.h>
29
30#include <cutils/log.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080031
32#include <utils/threads.h>
Mathias Agopian5f2165f2012-02-24 18:25:41 -080033#include <ui/ANativeObjectBase.h>
Jamie Gennisd8e812c2012-06-13 16:32:25 -070034#include <ui/Fence.h>
Dan Stoza204240a2016-01-08 10:52:16 -080035#include <ui/GraphicBufferMapper.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036
37#include <EGL/egl.h>
38#include <EGL/eglext.h>
39#include <GLES/gl.h>
40#include <GLES/glext.h>
41
42#include <pixelflinger/format.h>
43#include <pixelflinger/pixelflinger.h>
44
45#include "context.h"
46#include "state.h"
47#include "texture.h"
48#include "matrix.h"
49
50#undef NELEM
51#define NELEM(x) (sizeof(x)/sizeof(*(x)))
52
Mathias Agopian5f2165f2012-02-24 18:25:41 -080053// ----------------------------------------------------------------------------
Mathias Agopian4b9511c2011-11-13 23:52:47 -080054
55EGLBoolean EGLAPI eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
56 EGLint left, EGLint top, EGLint width, EGLint height);
57
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080058// ----------------------------------------------------------------------------
59namespace android {
Mathias Agopian5f2165f2012-02-24 18:25:41 -080060
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080061// ----------------------------------------------------------------------------
62
63const unsigned int NUM_DISPLAYS = 1;
64
65static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
66static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
67static pthread_key_t gEGLErrorKey = -1;
Elliott Hughes6071da72015-08-12 15:27:47 -070068#ifndef __ANDROID__
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080069namespace gl {
70pthread_key_t gGLKey = -1;
71}; // namespace gl
72#endif
73
74template<typename T>
75static T setError(GLint error, T returnValue) {
76 if (ggl_unlikely(gEGLErrorKey == -1)) {
77 pthread_mutex_lock(&gErrorKeyMutex);
78 if (gEGLErrorKey == -1)
79 pthread_key_create(&gEGLErrorKey, NULL);
80 pthread_mutex_unlock(&gErrorKeyMutex);
81 }
Colin Cross444839b2014-01-24 14:35:39 -080082 pthread_setspecific(gEGLErrorKey, (void*)(uintptr_t)error);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080083 return returnValue;
84}
85
86static GLint getError() {
87 if (ggl_unlikely(gEGLErrorKey == -1))
88 return EGL_SUCCESS;
Colin Cross444839b2014-01-24 14:35:39 -080089 GLint error = (GLint)(uintptr_t)pthread_getspecific(gEGLErrorKey);
Jamie Gennis2076f352011-01-30 15:59:36 -080090 if (error == 0) {
91 // The TLS key has been created by another thread, but the value for
92 // this thread has not been initialized.
93 return EGL_SUCCESS;
94 }
Colin Cross444839b2014-01-24 14:35:39 -080095 pthread_setspecific(gEGLErrorKey, (void*)(uintptr_t)EGL_SUCCESS);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080096 return error;
97}
98
99// ----------------------------------------------------------------------------
100
101struct egl_display_t
102{
103 egl_display_t() : type(0), initialized(0) { }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700104
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800105 static egl_display_t& get_display(EGLDisplay dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700106
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800107 static EGLBoolean is_valid(EGLDisplay dpy) {
108 return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
109 }
110
Jesse Hall3aa75f92016-05-20 10:47:07 -0700111 NativeDisplayType type;
112 std::atomic_size_t initialized;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800113};
114
115static egl_display_t gDisplays[NUM_DISPLAYS];
116
117egl_display_t& egl_display_t::get_display(EGLDisplay dpy) {
118 return gDisplays[uintptr_t(dpy)-1U];
119}
120
121struct egl_context_t {
122 enum {
123 IS_CURRENT = 0x00010000,
124 NEVER_CURRENT = 0x00020000
125 };
126 uint32_t flags;
127 EGLDisplay dpy;
128 EGLConfig config;
129 EGLSurface read;
130 EGLSurface draw;
131
132 static inline egl_context_t* context(EGLContext ctx) {
133 ogles_context_t* const gl = static_cast<ogles_context_t*>(ctx);
134 return static_cast<egl_context_t*>(gl->rasterizer.base);
135 }
136};
137
138// ----------------------------------------------------------------------------
139
140struct egl_surface_t
141{
142 enum {
143 PAGE_FLIP = 0x00000001,
144 MAGIC = 0x31415265
145 };
146
147 uint32_t magic;
148 EGLDisplay dpy;
149 EGLConfig config;
150 EGLContext ctx;
Jesse Hall78141e32013-03-07 09:56:26 -0800151 bool zombie;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800152
153 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
154 virtual ~egl_surface_t();
Mathias Agopian0696a572009-08-20 00:12:56 -0700155 bool isValid() const;
156 virtual bool initCheck() const = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700157
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800158 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0;
159 virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0;
Mathias Agopiancf81c842009-07-31 14:47:00 -0700160 virtual EGLBoolean connect() { return EGL_TRUE; }
Mathias Agopiane71212b2009-05-05 00:37:46 -0700161 virtual void disconnect() {}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800162 virtual EGLint getWidth() const = 0;
163 virtual EGLint getHeight() const = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800164
165 virtual EGLint getHorizontalResolution() const;
166 virtual EGLint getVerticalResolution() const;
167 virtual EGLint getRefreshRate() const;
168 virtual EGLint getSwapBehavior() const;
169 virtual EGLBoolean swapBuffers();
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700170 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800171protected:
172 GGLSurface depth;
173};
174
175egl_surface_t::egl_surface_t(EGLDisplay dpy,
176 EGLConfig config,
177 int32_t depthFormat)
Jesse Hall78141e32013-03-07 09:56:26 -0800178 : magic(MAGIC), dpy(dpy), config(config), ctx(0), zombie(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179{
180 depth.version = sizeof(GGLSurface);
181 depth.data = 0;
182 depth.format = depthFormat;
183}
184egl_surface_t::~egl_surface_t()
185{
186 magic = 0;
187 free(depth.data);
188}
Mathias Agopian0696a572009-08-20 00:12:56 -0700189bool egl_surface_t::isValid() const {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000190 ALOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
Mathias Agopian0696a572009-08-20 00:12:56 -0700191 return magic == MAGIC;
192}
193
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194EGLBoolean egl_surface_t::swapBuffers() {
195 return EGL_FALSE;
196}
197EGLint egl_surface_t::getHorizontalResolution() const {
198 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
199}
200EGLint egl_surface_t::getVerticalResolution() const {
201 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
202}
203EGLint egl_surface_t::getRefreshRate() const {
204 return (60 * EGL_DISPLAY_SCALING);
205}
206EGLint egl_surface_t::getSwapBehavior() const {
207 return EGL_BUFFER_PRESERVED;
208}
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700209EGLBoolean egl_surface_t::setSwapRectangle(
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700210 EGLint /*l*/, EGLint /*t*/, EGLint /*w*/, EGLint /*h*/)
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700211{
212 return EGL_FALSE;
213}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800214
215// ----------------------------------------------------------------------------
216
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700217struct egl_window_surface_v2_t : public egl_surface_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800218{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700219 egl_window_surface_v2_t(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220 EGLDisplay dpy, EGLConfig config,
221 int32_t depthFormat,
Dianne Hackborn4b5e91e2010-06-30 13:56:17 -0700222 ANativeWindow* window);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223
Mathias Agopian0696a572009-08-20 00:12:56 -0700224 ~egl_window_surface_v2_t();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800225
Mathias Agopian0696a572009-08-20 00:12:56 -0700226 virtual bool initCheck() const { return true; } // TODO: report failure if ctor fails
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800227 virtual EGLBoolean swapBuffers();
228 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
229 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
Mathias Agopiancf81c842009-07-31 14:47:00 -0700230 virtual EGLBoolean connect();
Mathias Agopiane71212b2009-05-05 00:37:46 -0700231 virtual void disconnect();
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700232 virtual EGLint getWidth() const { return width; }
233 virtual EGLint getHeight() const { return height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800234 virtual EGLint getHorizontalResolution() const;
235 virtual EGLint getVerticalResolution() const;
236 virtual EGLint getRefreshRate() const;
237 virtual EGLint getSwapBehavior() const;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700238 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700239
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800240private:
Iliyan Malchev697526b2011-05-01 11:33:26 -0700241 status_t lock(ANativeWindowBuffer* buf, int usage, void** vaddr);
242 status_t unlock(ANativeWindowBuffer* buf);
Dianne Hackborn4b5e91e2010-06-30 13:56:17 -0700243 ANativeWindow* nativeWindow;
Iliyan Malchev697526b2011-05-01 11:33:26 -0700244 ANativeWindowBuffer* buffer;
245 ANativeWindowBuffer* previousBuffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700246 int width;
247 int height;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700248 void* bits;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700249 GGLFormat const* pixelFormatTable;
250
251 struct Rect {
252 inline Rect() { };
253 inline Rect(int32_t w, int32_t h)
254 : left(0), top(0), right(w), bottom(h) { }
255 inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
256 : left(l), top(t), right(r), bottom(b) { }
257 Rect& andSelf(const Rect& r) {
258 left = max(left, r.left);
259 top = max(top, r.top);
260 right = min(right, r.right);
261 bottom = min(bottom, r.bottom);
262 return *this;
263 }
264 bool isEmpty() const {
265 return (left>=right || top>=bottom);
266 }
267 void dump(char const* what) {
Steve Block9d453682011-12-20 16:23:08 +0000268 ALOGD("%s { %5d, %5d, w=%5d, h=%5d }",
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700269 what, left, top, right-left, bottom-top);
270 }
271
272 int32_t left;
273 int32_t top;
274 int32_t right;
275 int32_t bottom;
276 };
277
278 struct Region {
279 inline Region() : count(0) { }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700280 typedef Rect const* const_iterator;
281 const_iterator begin() const { return storage; }
282 const_iterator end() const { return storage+count; }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700283 static Region subtract(const Rect& lhs, const Rect& rhs) {
284 Region reg;
285 Rect* storage = reg.storage;
286 if (!lhs.isEmpty()) {
287 if (lhs.top < rhs.top) { // top rect
288 storage->left = lhs.left;
289 storage->top = lhs.top;
290 storage->right = lhs.right;
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700291 storage->bottom = rhs.top;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700292 storage++;
293 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700294 const int32_t top = max(lhs.top, rhs.top);
295 const int32_t bot = min(lhs.bottom, rhs.bottom);
296 if (top < bot) {
297 if (lhs.left < rhs.left) { // left-side rect
298 storage->left = lhs.left;
299 storage->top = top;
300 storage->right = rhs.left;
301 storage->bottom = bot;
302 storage++;
303 }
304 if (lhs.right > rhs.right) { // right-side rect
305 storage->left = rhs.right;
306 storage->top = top;
307 storage->right = lhs.right;
308 storage->bottom = bot;
309 storage++;
310 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700311 }
312 if (lhs.bottom > rhs.bottom) { // bottom rect
313 storage->left = lhs.left;
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700314 storage->top = rhs.bottom;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700315 storage->right = lhs.right;
316 storage->bottom = lhs.bottom;
317 storage++;
318 }
319 reg.count = storage - reg.storage;
320 }
321 return reg;
322 }
323 bool isEmpty() const {
324 return count<=0;
325 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700326 private:
327 Rect storage[4];
328 ssize_t count;
329 };
330
331 void copyBlt(
Iliyan Malchev697526b2011-05-01 11:33:26 -0700332 ANativeWindowBuffer* dst, void* dst_vaddr,
333 ANativeWindowBuffer* src, void const* src_vaddr,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700334 const Region& clip);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700335
336 Rect dirtyRegion;
337 Rect oldDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800338};
339
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700340egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800341 EGLConfig config,
342 int32_t depthFormat,
Dianne Hackborn4b5e91e2010-06-30 13:56:17 -0700343 ANativeWindow* window)
Dan Stoza204240a2016-01-08 10:52:16 -0800344 : egl_surface_t(dpy, config, depthFormat),
345 nativeWindow(window), buffer(0), previousBuffer(0), bits(NULL)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800346{
Mathias Agopian69e43b72011-05-11 13:41:09 -0700347
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700348 pixelFormatTable = gglGetPixelFormatTable();
Dan Stoza204240a2016-01-08 10:52:16 -0800349
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700350 // keep a reference on the window
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700351 nativeWindow->common.incRef(&nativeWindow->common);
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700352 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
353 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
Mathias Agopiane71212b2009-05-05 00:37:46 -0700354}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700355
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700356egl_window_surface_v2_t::~egl_window_surface_v2_t() {
357 if (buffer) {
358 buffer->common.decRef(&buffer->common);
359 }
360 if (previousBuffer) {
361 previousBuffer->common.decRef(&previousBuffer->common);
362 }
363 nativeWindow->common.decRef(&nativeWindow->common);
364}
365
Mathias Agopiancf81c842009-07-31 14:47:00 -0700366EGLBoolean egl_window_surface_v2_t::connect()
Mathias Agopiane71212b2009-05-05 00:37:46 -0700367{
Mathias Agopian52212712009-08-11 22:34:02 -0700368 // we're intending to do software rendering
369 native_window_set_usage(nativeWindow,
370 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
371
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700372 // dequeue a buffer
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700373 int fenceFd = -1;
374 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer,
375 &fenceFd) != NO_ERROR) {
376 return setError(EGL_BAD_ALLOC, EGL_FALSE);
377 }
378
379 // wait for the buffer
380 sp<Fence> fence(new Fence(fenceFd));
381 if (fence->wait(Fence::TIMEOUT_NEVER) != NO_ERROR) {
382 nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd);
Mathias Agopiancf81c842009-07-31 14:47:00 -0700383 return setError(EGL_BAD_ALLOC, EGL_FALSE);
384 }
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700385
386 // allocate a corresponding depth-buffer
387 width = buffer->width;
388 height = buffer->height;
389 if (depth.format) {
390 depth.width = width;
391 depth.height = height;
392 depth.stride = depth.width; // use the width here
Michael Lentine95303882015-05-28 17:43:06 -0700393 uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
394 static_cast<uint64_t>(depth.height) * 2;
395 if (depth.stride < 0 || depth.height > INT_MAX ||
396 allocSize > UINT32_MAX) {
397 return setError(EGL_BAD_ALLOC, EGL_FALSE);
398 }
399 depth.data = (GGLubyte*)malloc(allocSize);
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700400 if (depth.data == 0) {
Mathias Agopiancf81c842009-07-31 14:47:00 -0700401 return setError(EGL_BAD_ALLOC, EGL_FALSE);
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700402 }
403 }
404
405 // keep a reference on the buffer
406 buffer->common.incRef(&buffer->common);
407
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700408 // pin the buffer down
409 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
410 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000411 ALOGE("connect() failed to lock buffer %p (%ux%u)",
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700412 buffer, buffer->width, buffer->height);
Mathias Agopiancf81c842009-07-31 14:47:00 -0700413 return setError(EGL_BAD_ACCESS, EGL_FALSE);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700414 // FIXME: we should make sure we're not accessing the buffer anymore
415 }
Mathias Agopiancf81c842009-07-31 14:47:00 -0700416 return EGL_TRUE;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700417}
418
419void egl_window_surface_v2_t::disconnect()
420{
Mathias Agopian9648c1a2009-06-03 19:00:53 -0700421 if (buffer && bits) {
Mathias Agopiane71212b2009-05-05 00:37:46 -0700422 bits = NULL;
423 unlock(buffer);
424 }
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700425 if (buffer) {
Jesse Hall5f555562013-03-07 15:14:18 -0800426 nativeWindow->cancelBuffer(nativeWindow, buffer, -1);
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700427 buffer->common.decRef(&buffer->common);
428 buffer = 0;
429 }
430 if (previousBuffer) {
431 previousBuffer->common.decRef(&previousBuffer->common);
432 previousBuffer = 0;
433 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800434}
435
Mathias Agopian0926f502009-05-04 14:17:04 -0700436status_t egl_window_surface_v2_t::lock(
Iliyan Malchev697526b2011-05-01 11:33:26 -0700437 ANativeWindowBuffer* buf, int usage, void** vaddr)
Mathias Agopian0926f502009-05-04 14:17:04 -0700438{
Dan Stoza204240a2016-01-08 10:52:16 -0800439 auto& mapper = GraphicBufferMapper::get();
440 return mapper.lock(buf->handle, usage,
441 android::Rect(buf->width, buf->height), vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -0700442}
443
Iliyan Malchev697526b2011-05-01 11:33:26 -0700444status_t egl_window_surface_v2_t::unlock(ANativeWindowBuffer* buf)
Mathias Agopian0926f502009-05-04 14:17:04 -0700445{
Mathias Agopiancf81c842009-07-31 14:47:00 -0700446 if (!buf) return BAD_VALUE;
Dan Stoza204240a2016-01-08 10:52:16 -0800447 auto& mapper = GraphicBufferMapper::get();
448 return mapper.unlock(buf->handle);
Mathias Agopian0926f502009-05-04 14:17:04 -0700449}
450
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700451void egl_window_surface_v2_t::copyBlt(
Iliyan Malchev697526b2011-05-01 11:33:26 -0700452 ANativeWindowBuffer* dst, void* dst_vaddr,
453 ANativeWindowBuffer* src, void const* src_vaddr,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700454 const Region& clip)
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700455{
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700456 // NOTE: dst and src must be the same format
457
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700458 Region::const_iterator cur = clip.begin();
459 Region::const_iterator end = clip.end();
Mathias Agopian0926f502009-05-04 14:17:04 -0700460
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700461 const size_t bpp = pixelFormatTable[src->format].size;
462 const size_t dbpr = dst->stride * bpp;
463 const size_t sbpr = src->stride * bpp;
464
465 uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
466 uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
467
468 while (cur != end) {
469 const Rect& r(*cur++);
470 ssize_t w = r.right - r.left;
471 ssize_t h = r.bottom - r.top;
472 if (w <= 0 || h<=0) continue;
473 size_t size = w * bpp;
474 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
475 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
476 if (dbpr==sbpr && size==sbpr) {
477 size *= h;
478 h = 1;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700479 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700480 do {
481 memcpy(d, s, size);
482 d += dbpr;
483 s += sbpr;
484 } while (--h > 0);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700485 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700486}
487
488EGLBoolean egl_window_surface_v2_t::swapBuffers()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800489{
Mathias Agopiancf81c842009-07-31 14:47:00 -0700490 if (!buffer) {
491 return setError(EGL_BAD_ACCESS, EGL_FALSE);
492 }
493
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700494 /*
495 * Handle eglSetSwapRectangleANDROID()
496 * We copyback from the front buffer
497 */
498 if (!dirtyRegion.isEmpty()) {
499 dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
500 if (previousBuffer) {
Kristian Monsen72c384e2010-10-27 17:59:09 +0100501 // This was const Region copyBack, but that causes an
502 // internal compile error on simulator builds
503 /*const*/ Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700504 if (!copyBack.isEmpty()) {
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700505 void* prevBits;
506 if (lock(previousBuffer,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700507 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
508 // copy from previousBuffer to buffer
509 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700510 unlock(previousBuffer);
511 }
512 }
513 }
514 oldDirtyRegion = dirtyRegion;
515 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700516
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700517 if (previousBuffer) {
518 previousBuffer->common.decRef(&previousBuffer->common);
519 previousBuffer = 0;
520 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700521
Mathias Agopian0926f502009-05-04 14:17:04 -0700522 unlock(buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700523 previousBuffer = buffer;
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700524 nativeWindow->queueBuffer(nativeWindow, buffer, -1);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700525 buffer = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700526
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700527 // dequeue a new buffer
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700528 int fenceFd = -1;
529 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &fenceFd) == NO_ERROR) {
530 sp<Fence> fence(new Fence(fenceFd));
531 if (fence->wait(Fence::TIMEOUT_NEVER)) {
532 nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd);
533 return setError(EGL_BAD_ALLOC, EGL_FALSE);
534 }
Mathias Agopian031213e2010-08-18 16:07:34 -0700535
536 // reallocate the depth-buffer if needed
537 if ((width != buffer->width) || (height != buffer->height)) {
538 // TODO: we probably should reset the swap rect here
539 // if the window size has changed
540 width = buffer->width;
541 height = buffer->height;
542 if (depth.data) {
543 free(depth.data);
544 depth.width = width;
545 depth.height = height;
546 depth.stride = buffer->stride;
Michael Lentine95303882015-05-28 17:43:06 -0700547 uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
548 static_cast<uint64_t>(depth.height) * 2;
549 if (depth.stride < 0 || depth.height > INT_MAX ||
550 allocSize > UINT32_MAX) {
551 setError(EGL_BAD_ALLOC, EGL_FALSE);
552 return EGL_FALSE;
553 }
554 depth.data = (GGLubyte*)malloc(allocSize);
Mathias Agopian031213e2010-08-18 16:07:34 -0700555 if (depth.data == 0) {
556 setError(EGL_BAD_ALLOC, EGL_FALSE);
557 return EGL_FALSE;
558 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800559 }
560 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700561
Mathias Agopian031213e2010-08-18 16:07:34 -0700562 // keep a reference on the buffer
563 buffer->common.incRef(&buffer->common);
564
565 // finally pin the buffer down
566 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
567 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000568 ALOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
Mathias Agopian031213e2010-08-18 16:07:34 -0700569 buffer, buffer->width, buffer->height);
570 return setError(EGL_BAD_ACCESS, EGL_FALSE);
571 // FIXME: we should make sure we're not accessing the buffer anymore
572 }
573 } else {
574 return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700575 }
576
577 return EGL_TRUE;
578}
579
580EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
581 EGLint l, EGLint t, EGLint w, EGLint h)
582{
583 dirtyRegion = Rect(l, t, l+w, t+h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800584 return EGL_TRUE;
585}
586
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700587EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800588{
589 GGLSurface buffer;
590 buffer.version = sizeof(GGLSurface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700591 buffer.width = this->buffer->width;
592 buffer.height = this->buffer->height;
593 buffer.stride = this->buffer->stride;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700594 buffer.data = (GGLubyte*)bits;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700595 buffer.format = this->buffer->format;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800596 gl->rasterizer.procs.colorBuffer(gl, &buffer);
597 if (depth.data != gl->rasterizer.state.buffers.depth.data)
598 gl->rasterizer.procs.depthBuffer(gl, &depth);
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700599
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800600 return EGL_TRUE;
601}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700602EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800603{
604 GGLSurface buffer;
605 buffer.version = sizeof(GGLSurface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700606 buffer.width = this->buffer->width;
607 buffer.height = this->buffer->height;
608 buffer.stride = this->buffer->stride;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700609 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700610 buffer.format = this->buffer->format;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800611 gl->rasterizer.procs.readBuffer(gl, &buffer);
612 return EGL_TRUE;
613}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700614EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800615 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
616}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700617EGLint egl_window_surface_v2_t::getVerticalResolution() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800618 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
619}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700620EGLint egl_window_surface_v2_t::getRefreshRate() const {
621 return (60 * EGL_DISPLAY_SCALING); // FIXME
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800622}
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700623EGLint egl_window_surface_v2_t::getSwapBehavior() const
624{
625 /*
626 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
627 * the content of the swapped buffer.
628 *
629 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
630 *
631 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
632 * only applies to the area specified by eglSetSwapRectangleANDROID(), that
633 * is, everything outside of this area is preserved.
634 *
635 * This implementation of EGL assumes the later case.
636 *
637 */
638
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700639 return EGL_BUFFER_DESTROYED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800640}
641
642// ----------------------------------------------------------------------------
643
644struct egl_pixmap_surface_t : public egl_surface_t
645{
646 egl_pixmap_surface_t(
647 EGLDisplay dpy, EGLConfig config,
648 int32_t depthFormat,
649 egl_native_pixmap_t const * pixmap);
650
651 virtual ~egl_pixmap_surface_t() { }
652
Mathias Agopian0696a572009-08-20 00:12:56 -0700653 virtual bool initCheck() const { return !depth.format || depth.data!=0; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800654 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
655 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
656 virtual EGLint getWidth() const { return nativePixmap.width; }
657 virtual EGLint getHeight() const { return nativePixmap.height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800658private:
659 egl_native_pixmap_t nativePixmap;
660};
661
662egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
663 EGLConfig config,
664 int32_t depthFormat,
665 egl_native_pixmap_t const * pixmap)
666 : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
667{
668 if (depthFormat) {
669 depth.width = pixmap->width;
670 depth.height = pixmap->height;
671 depth.stride = depth.width; // use the width here
Michael Lentine95303882015-05-28 17:43:06 -0700672 uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
673 static_cast<uint64_t>(depth.height) * 2;
674 if (depth.stride < 0 || depth.height > INT_MAX ||
675 allocSize > UINT32_MAX) {
676 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
677 return;
678 }
679 depth.data = (GGLubyte*)malloc(allocSize);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800680 if (depth.data == 0) {
681 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800682 }
683 }
684}
685EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl)
686{
687 GGLSurface buffer;
688 buffer.version = sizeof(GGLSurface);
689 buffer.width = nativePixmap.width;
690 buffer.height = nativePixmap.height;
691 buffer.stride = nativePixmap.stride;
692 buffer.data = nativePixmap.data;
693 buffer.format = nativePixmap.format;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700694
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800695 gl->rasterizer.procs.colorBuffer(gl, &buffer);
696 if (depth.data != gl->rasterizer.state.buffers.depth.data)
697 gl->rasterizer.procs.depthBuffer(gl, &depth);
698 return EGL_TRUE;
699}
700EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl)
701{
702 GGLSurface buffer;
703 buffer.version = sizeof(GGLSurface);
704 buffer.width = nativePixmap.width;
705 buffer.height = nativePixmap.height;
706 buffer.stride = nativePixmap.stride;
707 buffer.data = nativePixmap.data;
708 buffer.format = nativePixmap.format;
709 gl->rasterizer.procs.readBuffer(gl, &buffer);
710 return EGL_TRUE;
711}
712
713// ----------------------------------------------------------------------------
714
715struct egl_pbuffer_surface_t : public egl_surface_t
716{
717 egl_pbuffer_surface_t(
718 EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
719 int32_t w, int32_t h, int32_t f);
720
721 virtual ~egl_pbuffer_surface_t();
722
Mathias Agopian0696a572009-08-20 00:12:56 -0700723 virtual bool initCheck() const { return pbuffer.data != 0; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800724 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
725 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
726 virtual EGLint getWidth() const { return pbuffer.width; }
727 virtual EGLint getHeight() const { return pbuffer.height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800728private:
729 GGLSurface pbuffer;
730};
731
732egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
733 EGLConfig config, int32_t depthFormat,
734 int32_t w, int32_t h, int32_t f)
735 : egl_surface_t(dpy, config, depthFormat)
736{
737 size_t size = w*h;
738 switch (f) {
739 case GGL_PIXEL_FORMAT_A_8: size *= 1; break;
740 case GGL_PIXEL_FORMAT_RGB_565: size *= 2; break;
741 case GGL_PIXEL_FORMAT_RGBA_8888: size *= 4; break;
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800742 case GGL_PIXEL_FORMAT_RGBX_8888: size *= 4; break;
Amit Pundir90c75a22015-04-18 20:37:58 +0530743 case GGL_PIXEL_FORMAT_BGRA_8888: size *= 4; break;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800744 default:
Steve Blocke6f43dd2012-01-06 19:20:56 +0000745 ALOGE("incompatible pixel format for pbuffer (format=%d)", f);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800746 pbuffer.data = 0;
747 break;
748 }
749 pbuffer.version = sizeof(GGLSurface);
750 pbuffer.width = w;
751 pbuffer.height = h;
752 pbuffer.stride = w;
753 pbuffer.data = (GGLubyte*)malloc(size);
754 pbuffer.format = f;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700755
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800756 if (depthFormat) {
757 depth.width = pbuffer.width;
758 depth.height = pbuffer.height;
759 depth.stride = depth.width; // use the width here
Michael Lentine95303882015-05-28 17:43:06 -0700760 uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
761 static_cast<uint64_t>(depth.height) * 2;
762 if (depth.stride < 0 || depth.height > INT_MAX ||
763 allocSize > UINT32_MAX) {
764 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
765 return;
766 }
767 depth.data = (GGLubyte*)malloc(allocSize);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800768 if (depth.data == 0) {
769 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
770 return;
771 }
772 }
773}
774egl_pbuffer_surface_t::~egl_pbuffer_surface_t() {
775 free(pbuffer.data);
776}
777EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl)
778{
779 gl->rasterizer.procs.colorBuffer(gl, &pbuffer);
780 if (depth.data != gl->rasterizer.state.buffers.depth.data)
781 gl->rasterizer.procs.depthBuffer(gl, &depth);
782 return EGL_TRUE;
783}
784EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl)
785{
786 gl->rasterizer.procs.readBuffer(gl, &pbuffer);
787 return EGL_TRUE;
788}
789
790// ----------------------------------------------------------------------------
791
792struct config_pair_t {
793 GLint key;
794 GLint value;
795};
796
797struct configs_t {
798 const config_pair_t* array;
799 int size;
800};
801
802struct config_management_t {
803 GLint key;
804 bool (*match)(GLint reqValue, GLint confValue);
805 static bool atLeast(GLint reqValue, GLint confValue) {
806 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
807 }
808 static bool exact(GLint reqValue, GLint confValue) {
809 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
810 }
811 static bool mask(GLint reqValue, GLint confValue) {
812 return (confValue & reqValue) == reqValue;
813 }
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700814 static bool ignore(GLint /*reqValue*/, GLint /*confValue*/) {
Mathias Agopian63971672010-10-25 15:51:24 -0700815 return true;
816 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817};
818
819// ----------------------------------------------------------------------------
820
821#define VERSION_MAJOR 1
822#define VERSION_MINOR 2
823static char const * const gVendorString = "Google Inc.";
Mathias Agopian141550b2010-10-19 14:47:08 -0700824static char const * const gVersionString = "1.2 Android Driver 1.2.0";
Mathias Agopiancc2b1562012-05-21 14:01:37 -0700825static char const * const gClientApiString = "OpenGL_ES";
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700826static char const * const gExtensionsString =
Jesse Hall83e7c8c2012-05-22 10:42:56 -0700827 "EGL_KHR_fence_sync "
Mathias Agopiane6bf8b32009-05-06 23:47:08 -0700828 "EGL_KHR_image_base "
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700829 // "KHR_image_pixmap "
830 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700831 "EGL_ANDROID_swap_rectangle "
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700832 ;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800833
834// ----------------------------------------------------------------------------
835
836struct extention_map_t {
837 const char * const name;
838 __eglMustCastToProperFunctionPointerType address;
839};
840
841static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700842 { "glDrawTexsOES",
843 (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
844 { "glDrawTexiOES",
845 (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
846 { "glDrawTexfOES",
847 (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
848 { "glDrawTexxOES",
849 (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
850 { "glDrawTexsvOES",
851 (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
852 { "glDrawTexivOES",
853 (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
854 { "glDrawTexfvOES",
855 (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
856 { "glDrawTexxvOES",
857 (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
858 { "glQueryMatrixxOES",
859 (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
860 { "glEGLImageTargetTexture2DOES",
861 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
862 { "glEGLImageTargetRenderbufferStorageOES",
863 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
864 { "glClipPlanef",
865 (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
866 { "glClipPlanex",
867 (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
868 { "glBindBuffer",
869 (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
870 { "glBufferData",
871 (__eglMustCastToProperFunctionPointerType)&glBufferData },
872 { "glBufferSubData",
873 (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
874 { "glDeleteBuffers",
875 (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
876 { "glGenBuffers",
877 (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700878 { "eglCreateImageKHR",
879 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
880 { "eglDestroyImageKHR",
881 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Jesse Hall83e7c8c2012-05-22 10:42:56 -0700882 { "eglCreateSyncKHR",
883 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
884 { "eglDestroySyncKHR",
885 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
886 { "eglClientWaitSyncKHR",
887 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
888 { "eglGetSyncAttribKHR",
889 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700890 { "eglSetSwapRectangleANDROID",
891 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800892};
893
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700894/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800895 * In the lists below, attributes names MUST be sorted.
896 * Additionally, all configs must be sorted according to
897 * the EGL specification.
898 */
899
900static config_pair_t const config_base_attribute_list[] = {
901 { EGL_STENCIL_SIZE, 0 },
902 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
903 { EGL_LEVEL, 0 },
904 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700905 { EGL_MAX_PBUFFER_PIXELS,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800906 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
907 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
908 { EGL_NATIVE_RENDERABLE, EGL_TRUE },
909 { EGL_NATIVE_VISUAL_ID, 0 },
910 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGB_565 },
911 { EGL_SAMPLES, 0 },
912 { EGL_SAMPLE_BUFFERS, 0 },
913 { EGL_TRANSPARENT_TYPE, EGL_NONE },
914 { EGL_TRANSPARENT_BLUE_VALUE, 0 },
915 { EGL_TRANSPARENT_GREEN_VALUE, 0 },
916 { EGL_TRANSPARENT_RED_VALUE, 0 },
917 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
918 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
919 { EGL_MIN_SWAP_INTERVAL, 1 },
Mathias Agopian56fa2752009-09-27 20:18:16 -0700920 { EGL_MAX_SWAP_INTERVAL, 1 },
Mathias Agopian0985f6a2009-10-19 14:46:27 -0700921 { EGL_LUMINANCE_SIZE, 0 },
922 { EGL_ALPHA_MASK_SIZE, 0 },
923 { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER },
Mathias Agopian56fa2752009-09-27 20:18:16 -0700924 { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT },
Mathias Agopian0985f6a2009-10-19 14:46:27 -0700925 { EGL_CONFORMANT, 0 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800926};
927
928// These configs can override the base attribute list
929// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
930
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800931// 565 configs
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800932static config_pair_t const config_0_attribute_list[] = {
933 { EGL_BUFFER_SIZE, 16 },
934 { EGL_ALPHA_SIZE, 0 },
935 { EGL_BLUE_SIZE, 5 },
936 { EGL_GREEN_SIZE, 6 },
937 { EGL_RED_SIZE, 5 },
938 { EGL_DEPTH_SIZE, 0 },
939 { EGL_CONFIG_ID, 0 },
Mathias Agopiand8e5ceb2010-10-20 17:21:43 -0700940 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800941 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
942};
943
944static config_pair_t const config_1_attribute_list[] = {
945 { EGL_BUFFER_SIZE, 16 },
946 { EGL_ALPHA_SIZE, 0 },
947 { EGL_BLUE_SIZE, 5 },
948 { EGL_GREEN_SIZE, 6 },
949 { EGL_RED_SIZE, 5 },
950 { EGL_DEPTH_SIZE, 16 },
951 { EGL_CONFIG_ID, 1 },
Mathias Agopiand8e5ceb2010-10-20 17:21:43 -0700952 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800953 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
954};
955
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800956// RGB 888 configs
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800957static config_pair_t const config_2_attribute_list[] = {
958 { EGL_BUFFER_SIZE, 32 },
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800959 { EGL_ALPHA_SIZE, 0 },
960 { EGL_BLUE_SIZE, 8 },
961 { EGL_GREEN_SIZE, 8 },
962 { EGL_RED_SIZE, 8 },
963 { EGL_DEPTH_SIZE, 0 },
964 { EGL_CONFIG_ID, 6 },
Mathias Agopiand8e5ceb2010-10-20 17:21:43 -0700965 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800966 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
967};
968
969static config_pair_t const config_3_attribute_list[] = {
970 { EGL_BUFFER_SIZE, 32 },
971 { EGL_ALPHA_SIZE, 0 },
972 { EGL_BLUE_SIZE, 8 },
973 { EGL_GREEN_SIZE, 8 },
974 { EGL_RED_SIZE, 8 },
975 { EGL_DEPTH_SIZE, 16 },
976 { EGL_CONFIG_ID, 7 },
Mathias Agopiand8e5ceb2010-10-20 17:21:43 -0700977 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800978 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
979};
980
981// 8888 configs
982static config_pair_t const config_4_attribute_list[] = {
983 { EGL_BUFFER_SIZE, 32 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800984 { EGL_ALPHA_SIZE, 8 },
985 { EGL_BLUE_SIZE, 8 },
986 { EGL_GREEN_SIZE, 8 },
987 { EGL_RED_SIZE, 8 },
988 { EGL_DEPTH_SIZE, 0 },
989 { EGL_CONFIG_ID, 2 },
Mathias Agopian6af358e2010-10-21 15:58:25 -0700990 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800991 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
992};
993
Mathias Agopian8b6b95a2009-11-03 16:17:55 -0800994static config_pair_t const config_5_attribute_list[] = {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800995 { EGL_BUFFER_SIZE, 32 },
996 { EGL_ALPHA_SIZE, 8 },
997 { EGL_BLUE_SIZE, 8 },
998 { EGL_GREEN_SIZE, 8 },
999 { EGL_RED_SIZE, 8 },
1000 { EGL_DEPTH_SIZE, 16 },
1001 { EGL_CONFIG_ID, 3 },
Mathias Agopiand8e5ceb2010-10-20 17:21:43 -07001002 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001003 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
1004};
1005
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001006// A8 configs
1007static config_pair_t const config_6_attribute_list[] = {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001008 { EGL_BUFFER_SIZE, 8 },
1009 { EGL_ALPHA_SIZE, 8 },
1010 { EGL_BLUE_SIZE, 0 },
1011 { EGL_GREEN_SIZE, 0 },
1012 { EGL_RED_SIZE, 0 },
1013 { EGL_DEPTH_SIZE, 0 },
1014 { EGL_CONFIG_ID, 4 },
Mathias Agopiand8e5ceb2010-10-20 17:21:43 -07001015 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001016 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
1017};
1018
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001019static config_pair_t const config_7_attribute_list[] = {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001020 { EGL_BUFFER_SIZE, 8 },
1021 { EGL_ALPHA_SIZE, 8 },
1022 { EGL_BLUE_SIZE, 0 },
1023 { EGL_GREEN_SIZE, 0 },
1024 { EGL_RED_SIZE, 0 },
1025 { EGL_DEPTH_SIZE, 16 },
1026 { EGL_CONFIG_ID, 5 },
Mathias Agopian6af358e2010-10-21 15:58:25 -07001027 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001028 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
1029};
1030
Amit Pundir90c75a22015-04-18 20:37:58 +05301031// BGRA 8888 config
1032static config_pair_t const config_8_attribute_list[] = {
1033 { EGL_BUFFER_SIZE, 32 },
1034 { EGL_ALPHA_SIZE, 8 },
1035 { EGL_BLUE_SIZE, 8 },
1036 { EGL_GREEN_SIZE, 8 },
1037 { EGL_RED_SIZE, 8 },
1038 { EGL_DEPTH_SIZE, 0 },
1039 { EGL_CONFIG_ID, 8 },
1040 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_BGRA_8888 },
1041 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
1042};
1043
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001044static configs_t const gConfigs[] = {
1045 { config_0_attribute_list, NELEM(config_0_attribute_list) },
1046 { config_1_attribute_list, NELEM(config_1_attribute_list) },
1047 { config_2_attribute_list, NELEM(config_2_attribute_list) },
1048 { config_3_attribute_list, NELEM(config_3_attribute_list) },
1049 { config_4_attribute_list, NELEM(config_4_attribute_list) },
1050 { config_5_attribute_list, NELEM(config_5_attribute_list) },
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001051 { config_6_attribute_list, NELEM(config_6_attribute_list) },
1052 { config_7_attribute_list, NELEM(config_7_attribute_list) },
Amit Pundir90c75a22015-04-18 20:37:58 +05301053 { config_8_attribute_list, NELEM(config_8_attribute_list) },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001054};
1055
1056static config_management_t const gConfigManagement[] = {
1057 { EGL_BUFFER_SIZE, config_management_t::atLeast },
1058 { EGL_ALPHA_SIZE, config_management_t::atLeast },
1059 { EGL_BLUE_SIZE, config_management_t::atLeast },
1060 { EGL_GREEN_SIZE, config_management_t::atLeast },
1061 { EGL_RED_SIZE, config_management_t::atLeast },
1062 { EGL_DEPTH_SIZE, config_management_t::atLeast },
1063 { EGL_STENCIL_SIZE, config_management_t::atLeast },
1064 { EGL_CONFIG_CAVEAT, config_management_t::exact },
1065 { EGL_CONFIG_ID, config_management_t::exact },
1066 { EGL_LEVEL, config_management_t::exact },
Mathias Agopian63971672010-10-25 15:51:24 -07001067 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore },
1068 { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore },
1069 { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001070 { EGL_NATIVE_RENDERABLE, config_management_t::exact },
Mathias Agopian63971672010-10-25 15:51:24 -07001071 { EGL_NATIVE_VISUAL_ID, config_management_t::ignore },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001072 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
1073 { EGL_SAMPLES, config_management_t::exact },
1074 { EGL_SAMPLE_BUFFERS, config_management_t::exact },
1075 { EGL_SURFACE_TYPE, config_management_t::mask },
1076 { EGL_TRANSPARENT_TYPE, config_management_t::exact },
1077 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
1078 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
1079 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
1080 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
1081 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
1082 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
1083 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
Mathias Agopian0985f6a2009-10-19 14:46:27 -07001084 { EGL_LUMINANCE_SIZE, config_management_t::atLeast },
1085 { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast },
1086 { EGL_COLOR_BUFFER_TYPE, config_management_t::exact },
1087 { EGL_RENDERABLE_TYPE, config_management_t::mask },
1088 { EGL_CONFORMANT, config_management_t::mask }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001089};
1090
Mathias Agopian0985f6a2009-10-19 14:46:27 -07001091
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001092static config_pair_t const config_defaults[] = {
Mathias Agopian0985f6a2009-10-19 14:46:27 -07001093 // attributes that are not specified are simply ignored, if a particular
1094 // one needs not be ignored, it must be specified here, eg:
1095 // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001096};
1097
1098// ----------------------------------------------------------------------------
1099
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001100static status_t getConfigFormatInfo(EGLint configID,
1101 int32_t& pixelFormat, int32_t& depthFormat)
1102{
1103 switch(configID) {
1104 case 0:
1105 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1106 depthFormat = 0;
1107 break;
1108 case 1:
1109 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1110 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1111 break;
1112 case 2:
1113 pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
1114 depthFormat = 0;
1115 break;
1116 case 3:
1117 pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
1118 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1119 break;
1120 case 4:
1121 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1122 depthFormat = 0;
1123 break;
1124 case 5:
1125 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1126 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1127 break;
1128 case 6:
1129 pixelFormat = GGL_PIXEL_FORMAT_A_8;
1130 depthFormat = 0;
1131 break;
1132 case 7:
1133 pixelFormat = GGL_PIXEL_FORMAT_A_8;
1134 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1135 break;
Amit Pundir90c75a22015-04-18 20:37:58 +05301136 case 8:
1137 pixelFormat = GGL_PIXEL_FORMAT_BGRA_8888;
1138 depthFormat = 0;
1139 break;
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001140 default:
1141 return NAME_NOT_FOUND;
1142 }
1143 return NO_ERROR;
1144}
1145
1146// ----------------------------------------------------------------------------
1147
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001148template<typename T>
1149static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
1150{
1151 while (first <= last) {
1152 int mid = (first + last) / 2;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001153 if (key > sortedArray[mid].key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001154 first = mid + 1;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001155 } else if (key < sortedArray[mid].key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001156 last = mid - 1;
1157 } else {
1158 return mid;
1159 }
1160 }
1161 return -1;
1162}
1163
1164static int isAttributeMatching(int i, EGLint attr, EGLint val)
1165{
1166 // look for the attribute in all of our configs
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001167 config_pair_t const* configFound = gConfigs[i].array;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001168 int index = binarySearch<config_pair_t>(
1169 gConfigs[i].array,
1170 0, gConfigs[i].size-1,
1171 attr);
1172 if (index < 0) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001173 configFound = config_base_attribute_list;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001174 index = binarySearch<config_pair_t>(
1175 config_base_attribute_list,
1176 0, NELEM(config_base_attribute_list)-1,
1177 attr);
1178 }
1179 if (index >= 0) {
1180 // attribute found, check if this config could match
1181 int cfgMgtIndex = binarySearch<config_management_t>(
1182 gConfigManagement,
1183 0, NELEM(gConfigManagement)-1,
1184 attr);
Christoffer Gurell97640b92009-10-12 11:57:27 +02001185 if (cfgMgtIndex >= 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001186 bool match = gConfigManagement[cfgMgtIndex].match(
1187 val, configFound[index].value);
1188 if (match) {
1189 // this config matches
1190 return 1;
1191 }
1192 } else {
1193 // attribute not found. this should NEVER happen.
1194 }
1195 } else {
1196 // error, this attribute doesn't exist
1197 }
1198 return 0;
1199}
1200
1201static int makeCurrent(ogles_context_t* gl)
1202{
1203 ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific();
1204 if (gl) {
1205 egl_context_t* c = egl_context_t::context(gl);
1206 if (c->flags & egl_context_t::IS_CURRENT) {
1207 if (current != gl) {
1208 // it is an error to set a context current, if it's already
1209 // current to another thread
1210 return -1;
1211 }
1212 } else {
1213 if (current) {
1214 // mark the current context as not current, and flush
1215 glFlush();
1216 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1217 }
1218 }
1219 if (!(c->flags & egl_context_t::IS_CURRENT)) {
1220 // The context is not current, make it current!
1221 setGlThreadSpecific(gl);
1222 c->flags |= egl_context_t::IS_CURRENT;
1223 }
1224 } else {
1225 if (current) {
1226 // mark the current context as not current, and flush
1227 glFlush();
1228 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1229 }
1230 // this thread has no context attached to it
1231 setGlThreadSpecific(0);
1232 }
1233 return 0;
1234}
1235
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001236static EGLBoolean getConfigAttrib(EGLDisplay /*dpy*/, EGLConfig config,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001237 EGLint attribute, EGLint *value)
1238{
1239 size_t numConfigs = NELEM(gConfigs);
Colin Cross444839b2014-01-24 14:35:39 -08001240 int index = (int)(uintptr_t)config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001241 if (uint32_t(index) >= numConfigs)
1242 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1243
1244 int attrIndex;
1245 attrIndex = binarySearch<config_pair_t>(
1246 gConfigs[index].array,
1247 0, gConfigs[index].size-1,
1248 attribute);
1249 if (attrIndex>=0) {
1250 *value = gConfigs[index].array[attrIndex].value;
1251 return EGL_TRUE;
1252 }
1253
1254 attrIndex = binarySearch<config_pair_t>(
1255 config_base_attribute_list,
1256 0, NELEM(config_base_attribute_list)-1,
1257 attribute);
1258 if (attrIndex>=0) {
1259 *value = config_base_attribute_list[attrIndex].value;
1260 return EGL_TRUE;
1261 }
1262 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1263}
1264
1265static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001266 NativeWindowType window, const EGLint* /*attrib_list*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001267{
1268 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1269 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1270 if (window == 0)
1271 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1272
1273 EGLint surfaceType;
1274 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1275 return EGL_FALSE;
1276
1277 if (!(surfaceType & EGL_WINDOW_BIT))
1278 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1279
Dianne Hackborn4b5e91e2010-06-30 13:56:17 -07001280 if (static_cast<ANativeWindow*>(window)->common.magic !=
Mathias Agopian0696a572009-08-20 00:12:56 -07001281 ANDROID_NATIVE_WINDOW_MAGIC) {
1282 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
1283 }
1284
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001285 EGLint configID;
1286 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1287 return EGL_FALSE;
1288
1289 int32_t depthFormat;
1290 int32_t pixelFormat;
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001291 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001292 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1293 }
1294
1295 // FIXME: we don't have access to the pixelFormat here just yet.
1296 // (it's possible that the surface is not fully initialized)
1297 // maybe this should be done after the page-flip
1298 //if (EGLint(info.format) != pixelFormat)
1299 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1300
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001301 egl_surface_t* surface;
1302 surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
Dianne Hackborn4b5e91e2010-06-30 13:56:17 -07001303 static_cast<ANativeWindow*>(window));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001304
Mathias Agopian0696a572009-08-20 00:12:56 -07001305 if (!surface->initCheck()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001306 // there was a problem in the ctor, the error
1307 // flag has been set.
1308 delete surface;
1309 surface = 0;
1310 }
1311 return surface;
1312}
1313
1314static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001315 NativePixmapType pixmap, const EGLint* /*attrib_list*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001316{
1317 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1318 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1319 if (pixmap == 0)
1320 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1321
1322 EGLint surfaceType;
1323 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1324 return EGL_FALSE;
1325
1326 if (!(surfaceType & EGL_PIXMAP_BIT))
1327 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1328
Mathias Agopian0696a572009-08-20 00:12:56 -07001329 if (static_cast<egl_native_pixmap_t*>(pixmap)->version !=
1330 sizeof(egl_native_pixmap_t)) {
1331 return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1332 }
1333
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001334 EGLint configID;
1335 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1336 return EGL_FALSE;
1337
1338 int32_t depthFormat;
1339 int32_t pixelFormat;
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001340 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001341 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1342 }
1343
1344 if (pixmap->format != pixelFormat)
1345 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1346
1347 egl_surface_t* surface =
1348 new egl_pixmap_surface_t(dpy, config, depthFormat,
1349 static_cast<egl_native_pixmap_t*>(pixmap));
1350
Mathias Agopian0696a572009-08-20 00:12:56 -07001351 if (!surface->initCheck()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001352 // there was a problem in the ctor, the error
1353 // flag has been set.
1354 delete surface;
1355 surface = 0;
1356 }
1357 return surface;
1358}
1359
1360static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
1361 const EGLint *attrib_list)
1362{
1363 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1364 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1365
1366 EGLint surfaceType;
1367 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1368 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001369
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001370 if (!(surfaceType & EGL_PBUFFER_BIT))
1371 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001372
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001373 EGLint configID;
1374 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1375 return EGL_FALSE;
1376
1377 int32_t depthFormat;
1378 int32_t pixelFormat;
Mathias Agopian8b6b95a2009-11-03 16:17:55 -08001379 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001380 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1381 }
1382
1383 int32_t w = 0;
1384 int32_t h = 0;
Jesse Hall2e8ca9d2015-08-21 07:41:46 -07001385 while (attrib_list[0] != EGL_NONE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001386 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
1387 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
1388 attrib_list+=2;
1389 }
1390
1391 egl_surface_t* surface =
1392 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
1393
Mathias Agopian0696a572009-08-20 00:12:56 -07001394 if (!surface->initCheck()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001395 // there was a problem in the ctor, the error
1396 // flag has been set.
1397 delete surface;
1398 surface = 0;
1399 }
1400 return surface;
1401}
1402
1403// ----------------------------------------------------------------------------
1404}; // namespace android
1405// ----------------------------------------------------------------------------
1406
1407using namespace android;
1408
1409// ----------------------------------------------------------------------------
1410// Initialization
1411// ----------------------------------------------------------------------------
1412
1413EGLDisplay eglGetDisplay(NativeDisplayType display)
1414{
Elliott Hughes6071da72015-08-12 15:27:47 -07001415#ifndef __ANDROID__
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001416 // this just needs to be done once
1417 if (gGLKey == -1) {
1418 pthread_mutex_lock(&gInitMutex);
1419 if (gGLKey == -1)
1420 pthread_key_create(&gGLKey, NULL);
1421 pthread_mutex_unlock(&gInitMutex);
1422 }
1423#endif
1424 if (display == EGL_DEFAULT_DISPLAY) {
1425 EGLDisplay dpy = (EGLDisplay)1;
1426 egl_display_t& d = egl_display_t::get_display(dpy);
1427 d.type = display;
1428 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001429 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001430 return EGL_NO_DISPLAY;
1431}
1432
1433EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
1434{
1435 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1436 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001437
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001438 EGLBoolean res = EGL_TRUE;
1439 egl_display_t& d = egl_display_t::get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001440
Jesse Hall3aa75f92016-05-20 10:47:07 -07001441 if (d.initialized.fetch_add(1, std::memory_order_acquire) == 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001442 // initialize stuff here if needed
1443 //pthread_mutex_lock(&gInitMutex);
1444 //pthread_mutex_unlock(&gInitMutex);
1445 }
1446
1447 if (res == EGL_TRUE) {
1448 if (major != NULL) *major = VERSION_MAJOR;
1449 if (minor != NULL) *minor = VERSION_MINOR;
1450 }
1451 return res;
1452}
1453
1454EGLBoolean eglTerminate(EGLDisplay dpy)
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);
Jesse Hall3aa75f92016-05-20 10:47:07 -07001461 if (d.initialized.fetch_sub(1, std::memory_order_release) == 1) {
1462 std::atomic_thread_fence(std::memory_order_acquire);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001463 // TODO: destroy all resources (surfaces, contexts, etc...)
1464 //pthread_mutex_lock(&gInitMutex);
1465 //pthread_mutex_unlock(&gInitMutex);
1466 }
1467 return res;
1468}
1469
1470// ----------------------------------------------------------------------------
1471// configuration
1472// ----------------------------------------------------------------------------
1473
1474EGLBoolean eglGetConfigs( EGLDisplay dpy,
1475 EGLConfig *configs,
1476 EGLint config_size, EGLint *num_config)
1477{
1478 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1479 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1480
1481 GLint numConfigs = NELEM(gConfigs);
1482 if (!configs) {
1483 *num_config = numConfigs;
1484 return EGL_TRUE;
1485 }
1486 GLint i;
1487 for (i=0 ; i<numConfigs && i<config_size ; i++) {
Colin Cross444839b2014-01-24 14:35:39 -08001488 *configs++ = (EGLConfig)(uintptr_t)i;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001489 }
1490 *num_config = i;
1491 return EGL_TRUE;
1492}
1493
1494EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
1495 EGLConfig *configs, EGLint config_size,
1496 EGLint *num_config)
1497{
1498 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1499 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Jack Palevich749c63d2009-03-25 15:12:17 -07001500
1501 if (ggl_unlikely(num_config==0)) {
1502 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1503 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001504
Jack Palevich749c63d2009-03-25 15:12:17 -07001505 if (ggl_unlikely(attrib_list==0)) {
Mathias Agopian04aed212010-05-17 14:45:43 -07001506 /*
1507 * A NULL attrib_list should be treated as though it was an empty
1508 * one (terminated with EGL_NONE) as defined in
1509 * section 3.4.1 "Querying Configurations" in the EGL specification.
1510 */
1511 static const EGLint dummy = EGL_NONE;
1512 attrib_list = &dummy;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001513 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001514
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001515 int numAttributes = 0;
1516 int numConfigs = NELEM(gConfigs);
1517 uint32_t possibleMatch = (1<<numConfigs)-1;
1518 while(possibleMatch && *attrib_list != EGL_NONE) {
1519 numAttributes++;
1520 EGLint attr = *attrib_list++;
1521 EGLint val = *attrib_list++;
Mathias Agopian0985f6a2009-10-19 14:46:27 -07001522 for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001523 if (!(possibleMatch & (1<<i)))
1524 continue;
1525 if (isAttributeMatching(i, attr, val) == 0) {
1526 possibleMatch &= ~(1<<i);
1527 }
1528 }
1529 }
1530
1531 // now, handle the attributes which have a useful default value
Mathias Agopian0985f6a2009-10-19 14:46:27 -07001532 for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
1533 // see if this attribute was specified, if not, apply its
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001534 // default value
1535 if (binarySearch<config_pair_t>(
1536 (config_pair_t const*)attrib_list,
Mathias Agopiandacd7a32009-07-09 17:33:15 -07001537 0, numAttributes-1,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001538 config_defaults[j].key) < 0)
1539 {
Mathias Agopian0985f6a2009-10-19 14:46:27 -07001540 for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001541 if (!(possibleMatch & (1<<i)))
1542 continue;
1543 if (isAttributeMatching(i,
1544 config_defaults[j].key,
1545 config_defaults[j].value) == 0)
1546 {
1547 possibleMatch &= ~(1<<i);
1548 }
1549 }
1550 }
1551 }
1552
1553 // return the configurations found
1554 int n=0;
1555 if (possibleMatch) {
Jack Palevich749c63d2009-03-25 15:12:17 -07001556 if (configs) {
1557 for (int i=0 ; config_size && i<numConfigs ; i++) {
1558 if (possibleMatch & (1<<i)) {
Colin Cross444839b2014-01-24 14:35:39 -08001559 *configs++ = (EGLConfig)(uintptr_t)i;
Jack Palevich749c63d2009-03-25 15:12:17 -07001560 config_size--;
1561 n++;
1562 }
1563 }
1564 } else {
1565 for (int i=0 ; i<numConfigs ; i++) {
1566 if (possibleMatch & (1<<i)) {
1567 n++;
1568 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001569 }
1570 }
1571 }
1572 *num_config = n;
1573 return EGL_TRUE;
1574}
1575
1576EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
1577 EGLint attribute, EGLint *value)
1578{
1579 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1580 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1581
1582 return getConfigAttrib(dpy, config, attribute, value);
1583}
1584
1585// ----------------------------------------------------------------------------
1586// surfaces
1587// ----------------------------------------------------------------------------
1588
1589EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
1590 NativeWindowType window,
1591 const EGLint *attrib_list)
1592{
1593 return createWindowSurface(dpy, config, window, attrib_list);
1594}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001595
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001596EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1597 NativePixmapType pixmap,
1598 const EGLint *attrib_list)
1599{
1600 return createPixmapSurface(dpy, config, pixmap, attrib_list);
1601}
1602
1603EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1604 const EGLint *attrib_list)
1605{
1606 return createPbufferSurface(dpy, config, attrib_list);
1607}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001608
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001609EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1610{
1611 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1612 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1613 if (eglSurface != EGL_NO_SURFACE) {
1614 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
Mathias Agopian0696a572009-08-20 00:12:56 -07001615 if (!surface->isValid())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001616 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1617 if (surface->dpy != dpy)
1618 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopiane71212b2009-05-05 00:37:46 -07001619 if (surface->ctx) {
Jesse Hall78141e32013-03-07 09:56:26 -08001620 // defer disconnect/delete until no longer current
1621 surface->zombie = true;
1622 } else {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001623 surface->disconnect();
Jesse Hall78141e32013-03-07 09:56:26 -08001624 delete surface;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001625 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001626 }
1627 return EGL_TRUE;
1628}
1629
1630EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
1631 EGLint attribute, EGLint *value)
1632{
1633 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1634 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1635 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
Mathias Agopian0696a572009-08-20 00:12:56 -07001636 if (!surface->isValid())
1637 return setError(EGL_BAD_SURFACE, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001638 if (surface->dpy != dpy)
1639 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1640
1641 EGLBoolean ret = EGL_TRUE;
1642 switch (attribute) {
1643 case EGL_CONFIG_ID:
1644 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
1645 break;
1646 case EGL_WIDTH:
1647 *value = surface->getWidth();
1648 break;
1649 case EGL_HEIGHT:
1650 *value = surface->getHeight();
1651 break;
1652 case EGL_LARGEST_PBUFFER:
1653 // not modified for a window or pixmap surface
1654 break;
1655 case EGL_TEXTURE_FORMAT:
1656 *value = EGL_NO_TEXTURE;
1657 break;
1658 case EGL_TEXTURE_TARGET:
1659 *value = EGL_NO_TEXTURE;
1660 break;
1661 case EGL_MIPMAP_TEXTURE:
1662 *value = EGL_FALSE;
1663 break;
1664 case EGL_MIPMAP_LEVEL:
1665 *value = 0;
1666 break;
1667 case EGL_RENDER_BUFFER:
1668 // TODO: return the real RENDER_BUFFER here
1669 *value = EGL_BACK_BUFFER;
1670 break;
1671 case EGL_HORIZONTAL_RESOLUTION:
1672 // pixel/mm * EGL_DISPLAY_SCALING
1673 *value = surface->getHorizontalResolution();
1674 break;
1675 case EGL_VERTICAL_RESOLUTION:
1676 // pixel/mm * EGL_DISPLAY_SCALING
1677 *value = surface->getVerticalResolution();
1678 break;
1679 case EGL_PIXEL_ASPECT_RATIO: {
1680 // w/h * EGL_DISPLAY_SCALING
1681 int wr = surface->getHorizontalResolution();
1682 int hr = surface->getVerticalResolution();
1683 *value = (wr * EGL_DISPLAY_SCALING) / hr;
1684 } break;
1685 case EGL_SWAP_BEHAVIOR:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001686 *value = surface->getSwapBehavior();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001687 break;
1688 default:
1689 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1690 }
1691 return ret;
1692}
1693
1694EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001695 EGLContext /*share_list*/, const EGLint* /*attrib_list*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001696{
1697 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1698 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1699
1700 ogles_context_t* gl = ogles_init(sizeof(egl_context_t));
1701 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1702
1703 egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
1704 c->flags = egl_context_t::NEVER_CURRENT;
1705 c->dpy = dpy;
1706 c->config = config;
1707 c->read = 0;
1708 c->draw = 0;
1709 return (EGLContext)gl;
1710}
1711
1712EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1713{
1714 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1715 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1716 egl_context_t* c = egl_context_t::context(ctx);
1717 if (c->flags & egl_context_t::IS_CURRENT)
1718 setGlThreadSpecific(0);
1719 ogles_uninit((ogles_context_t*)ctx);
1720 return EGL_TRUE;
1721}
1722
1723EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1724 EGLSurface read, EGLContext ctx)
1725{
1726 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1727 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1728 if (draw) {
1729 egl_surface_t* s = (egl_surface_t*)draw;
Mathias Agopian0696a572009-08-20 00:12:56 -07001730 if (!s->isValid())
1731 return setError(EGL_BAD_SURFACE, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001732 if (s->dpy != dpy)
1733 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian0696a572009-08-20 00:12:56 -07001734 // TODO: check that draw is compatible with the context
1735 }
1736 if (read && read!=draw) {
1737 egl_surface_t* s = (egl_surface_t*)read;
1738 if (!s->isValid())
1739 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1740 if (s->dpy != dpy)
1741 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1742 // TODO: check that read is compatible with the context
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001743 }
1744
1745 EGLContext current_ctx = EGL_NO_CONTEXT;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001746
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001747 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1748 return setError(EGL_BAD_MATCH, EGL_FALSE);
1749
1750 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1751 return setError(EGL_BAD_MATCH, EGL_FALSE);
1752
1753 if (ctx == EGL_NO_CONTEXT) {
1754 // if we're detaching, we need the current context
1755 current_ctx = (EGLContext)getGlThreadSpecific();
1756 } else {
1757 egl_context_t* c = egl_context_t::context(ctx);
1758 egl_surface_t* d = (egl_surface_t*)draw;
1759 egl_surface_t* r = (egl_surface_t*)read;
1760 if ((d && d->ctx && d->ctx != ctx) ||
1761 (r && r->ctx && r->ctx != ctx)) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001762 // one of the surface is bound to a context in another thread
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001763 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1764 }
1765 }
1766
1767 ogles_context_t* gl = (ogles_context_t*)ctx;
1768 if (makeCurrent(gl) == 0) {
1769 if (ctx) {
1770 egl_context_t* c = egl_context_t::context(ctx);
1771 egl_surface_t* d = (egl_surface_t*)draw;
1772 egl_surface_t* r = (egl_surface_t*)read;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001773
1774 if (c->draw) {
Mathias Agopian0696a572009-08-20 00:12:56 -07001775 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
1776 s->disconnect();
Jesse Hall78141e32013-03-07 09:56:26 -08001777 s->ctx = EGL_NO_CONTEXT;
1778 if (s->zombie)
1779 delete s;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001780 }
1781 if (c->read) {
1782 // FIXME: unlock/disconnect the read surface too
1783 }
1784
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001785 c->draw = draw;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001786 c->read = read;
1787
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001788 if (c->flags & egl_context_t::NEVER_CURRENT) {
1789 c->flags &= ~egl_context_t::NEVER_CURRENT;
1790 GLint w = 0;
1791 GLint h = 0;
1792 if (draw) {
1793 w = d->getWidth();
1794 h = d->getHeight();
1795 }
1796 ogles_surfaceport(gl, 0, 0);
1797 ogles_viewport(gl, 0, 0, w, h);
1798 ogles_scissor(gl, 0, 0, w, h);
1799 }
1800 if (d) {
Mathias Agopiancf81c842009-07-31 14:47:00 -07001801 if (d->connect() == EGL_FALSE) {
1802 return EGL_FALSE;
1803 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001804 d->ctx = ctx;
1805 d->bindDrawSurface(gl);
1806 }
1807 if (r) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001808 // FIXME: lock/connect the read surface too
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001809 r->ctx = ctx;
1810 r->bindReadSurface(gl);
1811 }
1812 } else {
1813 // if surfaces were bound to the context bound to this thread
1814 // mark then as unbound.
1815 if (current_ctx) {
1816 egl_context_t* c = egl_context_t::context(current_ctx);
1817 egl_surface_t* d = (egl_surface_t*)c->draw;
1818 egl_surface_t* r = (egl_surface_t*)c->read;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001819 if (d) {
Mathias Agopian9648c1a2009-06-03 19:00:53 -07001820 c->draw = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001821 d->disconnect();
Jesse Hall78141e32013-03-07 09:56:26 -08001822 d->ctx = EGL_NO_CONTEXT;
1823 if (d->zombie)
1824 delete d;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001825 }
1826 if (r) {
Mathias Agopian9648c1a2009-06-03 19:00:53 -07001827 c->read = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001828 r->ctx = EGL_NO_CONTEXT;
1829 // FIXME: unlock/disconnect the read surface too
1830 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001831 }
1832 }
1833 return EGL_TRUE;
1834 }
1835 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1836}
1837
1838EGLContext eglGetCurrentContext(void)
1839{
1840 // eglGetCurrentContext returns the current EGL rendering context,
1841 // as specified by eglMakeCurrent. If no context is current,
1842 // EGL_NO_CONTEXT is returned.
1843 return (EGLContext)getGlThreadSpecific();
1844}
1845
1846EGLSurface eglGetCurrentSurface(EGLint readdraw)
1847{
1848 // eglGetCurrentSurface returns the read or draw surface attached
1849 // to the current EGL rendering context, as specified by eglMakeCurrent.
1850 // If no context is current, EGL_NO_SURFACE is returned.
1851 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1852 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
1853 egl_context_t* c = egl_context_t::context(ctx);
1854 if (readdraw == EGL_READ) {
1855 return c->read;
1856 } else if (readdraw == EGL_DRAW) {
1857 return c->draw;
1858 }
1859 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
1860}
1861
1862EGLDisplay eglGetCurrentDisplay(void)
1863{
1864 // eglGetCurrentDisplay returns the current EGL display connection
1865 // for the current EGL rendering context, as specified by eglMakeCurrent.
1866 // If no context is current, EGL_NO_DISPLAY is returned.
1867 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1868 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
1869 egl_context_t* c = egl_context_t::context(ctx);
1870 return c->dpy;
1871}
1872
1873EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1874 EGLint attribute, EGLint *value)
1875{
1876 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1877 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1878 egl_context_t* c = egl_context_t::context(ctx);
1879 switch (attribute) {
1880 case EGL_CONFIG_ID:
1881 // Returns the ID of the EGL frame buffer configuration with
1882 // respect to which the context was created
1883 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
1884 }
1885 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1886}
1887
1888EGLBoolean eglWaitGL(void)
1889{
1890 return EGL_TRUE;
1891}
1892
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001893EGLBoolean eglWaitNative(EGLint /*engine*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001894{
1895 return EGL_TRUE;
1896}
1897
1898EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1899{
1900 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1901 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001902
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001903 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
Mathias Agopian0696a572009-08-20 00:12:56 -07001904 if (!d->isValid())
1905 return setError(EGL_BAD_SURFACE, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001906 if (d->dpy != dpy)
1907 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1908
1909 // post the surface
1910 d->swapBuffers();
1911
1912 // if it's bound to a context, update the buffer
1913 if (d->ctx != EGL_NO_CONTEXT) {
1914 d->bindDrawSurface((ogles_context_t*)d->ctx);
1915 // if this surface is also the read surface of the context
1916 // it is bound to, make sure to update the read buffer as well.
1917 // The EGL spec is a little unclear about this.
1918 egl_context_t* c = egl_context_t::context(d->ctx);
1919 if (c->read == draw) {
1920 d->bindReadSurface((ogles_context_t*)d->ctx);
1921 }
1922 }
1923
1924 return EGL_TRUE;
1925}
1926
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001927EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface /*surface*/,
1928 NativePixmapType /*target*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001929{
1930 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1931 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1932 // TODO: eglCopyBuffers()
1933 return EGL_FALSE;
1934}
1935
1936EGLint eglGetError(void)
1937{
1938 return getError();
1939}
1940
1941const char* eglQueryString(EGLDisplay dpy, EGLint name)
1942{
1943 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1944 return setError(EGL_BAD_DISPLAY, (const char*)0);
1945
1946 switch (name) {
1947 case EGL_VENDOR:
1948 return gVendorString;
1949 case EGL_VERSION:
1950 return gVersionString;
1951 case EGL_EXTENSIONS:
1952 return gExtensionsString;
1953 case EGL_CLIENT_APIS:
1954 return gClientApiString;
1955 }
1956 return setError(EGL_BAD_PARAMETER, (const char *)0);
1957}
1958
1959// ----------------------------------------------------------------------------
1960// EGL 1.1
1961// ----------------------------------------------------------------------------
1962
1963EGLBoolean eglSurfaceAttrib(
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001964 EGLDisplay dpy, EGLSurface /*surface*/, EGLint /*attribute*/, EGLint /*value*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001965{
1966 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1967 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1968 // TODO: eglSurfaceAttrib()
1969 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1970}
1971
1972EGLBoolean eglBindTexImage(
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001973 EGLDisplay dpy, EGLSurface /*surface*/, EGLint /*buffer*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001974{
1975 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1976 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1977 // TODO: eglBindTexImage()
1978 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1979}
1980
1981EGLBoolean eglReleaseTexImage(
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001982 EGLDisplay dpy, EGLSurface /*surface*/, EGLint /*buffer*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001983{
1984 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1985 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1986 // TODO: eglReleaseTexImage()
1987 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1988}
1989
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001990EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint /*interval*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001991{
1992 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1993 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1994 // TODO: eglSwapInterval()
Ari Hirvonen551dc262010-10-01 19:00:54 +03001995 return EGL_TRUE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001996}
1997
1998// ----------------------------------------------------------------------------
1999// EGL 1.2
2000// ----------------------------------------------------------------------------
2001
2002EGLBoolean eglBindAPI(EGLenum api)
2003{
2004 if (api != EGL_OPENGL_ES_API)
2005 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2006 return EGL_TRUE;
2007}
2008
2009EGLenum eglQueryAPI(void)
2010{
2011 return EGL_OPENGL_ES_API;
2012}
2013
2014EGLBoolean eglWaitClient(void)
2015{
2016 glFinish();
2017 return EGL_TRUE;
2018}
2019
2020EGLBoolean eglReleaseThread(void)
2021{
2022 // TODO: eglReleaseThread()
2023 return EGL_TRUE;
2024}
2025
2026EGLSurface eglCreatePbufferFromClientBuffer(
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002027 EGLDisplay dpy, EGLenum /*buftype*/, EGLClientBuffer /*buffer*/,
2028 EGLConfig /*config*/, const EGLint* /*attrib_list*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002029{
2030 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2031 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
2032 // TODO: eglCreatePbufferFromClientBuffer()
2033 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
2034}
2035
2036// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002037// EGL_EGLEXT_VERSION 3
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002038// ----------------------------------------------------------------------------
2039
2040void (*eglGetProcAddress (const char *procname))()
2041{
2042 extention_map_t const * const map = gExtentionMap;
2043 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
2044 if (!strcmp(procname, map[i].name)) {
2045 return map[i].address;
2046 }
2047 }
2048 return NULL;
2049}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002050
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002051EGLBoolean eglLockSurfaceKHR(EGLDisplay /*dpy*/, EGLSurface /*surface*/,
2052 const EGLint* /*attrib_list*/)
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002053{
2054 EGLBoolean result = EGL_FALSE;
2055 return result;
2056}
2057
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002058EGLBoolean eglUnlockSurfaceKHR(EGLDisplay /*dpy*/, EGLSurface /*surface*/)
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002059{
2060 EGLBoolean result = EGL_FALSE;
2061 return result;
2062}
2063
2064EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002065 EGLClientBuffer buffer, const EGLint* /*attrib_list*/)
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002066{
2067 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2068 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
2069 }
2070 if (ctx != EGL_NO_CONTEXT) {
2071 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
2072 }
2073 if (target != EGL_NATIVE_BUFFER_ANDROID) {
2074 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2075 }
2076
Iliyan Malchev697526b2011-05-01 11:33:26 -07002077 ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002078
2079 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2080 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2081
Iliyan Malchev697526b2011-05-01 11:33:26 -07002082 if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002083 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
Mathias Agopian8dccb262010-02-04 17:04:53 -08002084
2085 switch (native_buffer->format) {
2086 case HAL_PIXEL_FORMAT_RGBA_8888:
2087 case HAL_PIXEL_FORMAT_RGBX_8888:
2088 case HAL_PIXEL_FORMAT_RGB_888:
2089 case HAL_PIXEL_FORMAT_RGB_565:
2090 case HAL_PIXEL_FORMAT_BGRA_8888:
Mathias Agopian8dccb262010-02-04 17:04:53 -08002091 break;
2092 default:
2093 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2094 }
2095
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002096 native_buffer->common.incRef(&native_buffer->common);
2097 return (EGLImageKHR)native_buffer;
2098}
2099
2100EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2101{
2102 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2103 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2104 }
2105
Iliyan Malchev697526b2011-05-01 11:33:26 -07002106 ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002107
2108 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2109 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2110
Iliyan Malchev697526b2011-05-01 11:33:26 -07002111 if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002112 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2113
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002114 native_buffer->common.decRef(&native_buffer->common);
2115
2116 return EGL_TRUE;
2117}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002118
2119// ----------------------------------------------------------------------------
Jesse Hall83e7c8c2012-05-22 10:42:56 -07002120// EGL_KHR_fence_sync
2121// ----------------------------------------------------------------------------
2122
2123#define FENCE_SYNC_HANDLE ((EGLSyncKHR)0xFE4CE)
2124
2125EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
2126 const EGLint *attrib_list)
2127{
2128 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2129 return setError(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
2130 }
2131
2132 if (type != EGL_SYNC_FENCE_KHR ||
2133 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
2134 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
2135 }
2136
2137 if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
2138 return setError(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
2139 }
2140
2141 // AGL is synchronous; nothing to do here.
2142
2143 return FENCE_SYNC_HANDLE;
2144}
2145
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002146EGLBoolean eglDestroySyncKHR(EGLDisplay /*dpy*/, EGLSyncKHR sync)
Jesse Hall83e7c8c2012-05-22 10:42:56 -07002147{
2148 if (sync != FENCE_SYNC_HANDLE) {
2149 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2150 }
2151
2152 return EGL_TRUE;
2153}
2154
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002155EGLint eglClientWaitSyncKHR(EGLDisplay /*dpy*/, EGLSyncKHR sync, EGLint /*flags*/,
2156 EGLTimeKHR /*timeout*/)
Jesse Hall83e7c8c2012-05-22 10:42:56 -07002157{
2158 if (sync != FENCE_SYNC_HANDLE) {
2159 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2160 }
2161
2162 return EGL_CONDITION_SATISFIED_KHR;
2163}
2164
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07002165EGLBoolean eglGetSyncAttribKHR(EGLDisplay /*dpy*/, EGLSyncKHR sync,
Jesse Hall83e7c8c2012-05-22 10:42:56 -07002166 EGLint attribute, EGLint *value)
2167{
2168 if (sync != FENCE_SYNC_HANDLE) {
2169 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2170 }
2171
2172 switch (attribute) {
2173 case EGL_SYNC_TYPE_KHR:
2174 *value = EGL_SYNC_FENCE_KHR;
2175 return EGL_TRUE;
2176 case EGL_SYNC_STATUS_KHR:
2177 *value = EGL_SIGNALED_KHR;
2178 return EGL_TRUE;
2179 case EGL_SYNC_CONDITION_KHR:
2180 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
2181 return EGL_TRUE;
2182 default:
2183 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
2184 }
2185}
2186
2187// ----------------------------------------------------------------------------
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002188// ANDROID extensions
2189// ----------------------------------------------------------------------------
2190
2191EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2192 EGLint left, EGLint top, EGLint width, EGLint height)
2193{
2194 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2195 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2196
2197 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
Mathias Agopian0696a572009-08-20 00:12:56 -07002198 if (!d->isValid())
2199 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002200 if (d->dpy != dpy)
2201 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2202
2203 // post the surface
2204 d->setSwapRectangle(left, top, width, height);
2205
2206 return EGL_TRUE;
2207}