blob: ba771c3fba33f43d3b0b77139bcec6d55a005910 [file] [log] [blame]
David Liaa1f54d2011-03-01 16:54:04 -08001/*
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002 **
3 ** Copyright 2007 The Android Open Source Project
4 **
5 ** Licensed under the Apache License Version 2.0(the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing software
12 ** distributed under the License is distributed on an "AS IS" BASIS
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
David Liaa1f54d2011-03-01 16:54:04 -080017
18#include <errno.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <sys/ioctl.h>
25#include <sys/types.h>
26#include <sys/mman.h>
27
28#include <cutils/atomic.h>
29
30
31#include <private/ui/android_natives_priv.h>
32
David Liaa1f54d2011-03-01 16:54:04 -080033#include "gles2context.h"
34
35// ----------------------------------------------------------------------------
36namespace android
37{
38// ----------------------------------------------------------------------------
39
40const unsigned int NUM_DISPLAYS = 1;
41
42static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
43static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
44static pthread_key_t gEGLErrorKey = -1;
45#ifndef HAVE_ANDROID_OS
46namespace gl {
47pthread_key_t gGLKey = -1;
48}; // namespace gl
49#endif
50
51template<typename T>
52static T setError(GLint error, T returnValue)
53{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070054 if (ggl_unlikely(gEGLErrorKey == -1)) {
55 pthread_mutex_lock(&gErrorKeyMutex);
56 if (gEGLErrorKey == -1)
57 pthread_key_create(&gEGLErrorKey, NULL);
58 pthread_mutex_unlock(&gErrorKeyMutex);
59 }
60 pthread_setspecific(gEGLErrorKey, (void*)error);
61 return returnValue;
David Liaa1f54d2011-03-01 16:54:04 -080062}
63
64static GLint getError()
65{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070066 if (ggl_unlikely(gEGLErrorKey == -1))
67 return EGL_SUCCESS;
68 GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
69 if (error == 0) {
70 // The TLS key has been created by another thread, but the value for
71 // this thread has not been initialized.
72 return EGL_SUCCESS;
73 }
74 pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
75 return error;
David Liaa1f54d2011-03-01 16:54:04 -080076}
77
78// ----------------------------------------------------------------------------
79
80struct egl_display_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070081 egl_display_t() : type(0), initialized(0) { }
David Liaa1f54d2011-03-01 16:54:04 -080082
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070083 static egl_display_t& get_display(EGLDisplay dpy);
David Liaa1f54d2011-03-01 16:54:04 -080084
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070085 static EGLBoolean is_valid(EGLDisplay dpy) {
86 return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
87 }
David Liaa1f54d2011-03-01 16:54:04 -080088
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070089 NativeDisplayType type;
90 volatile int32_t initialized;
David Liaa1f54d2011-03-01 16:54:04 -080091};
92
93static egl_display_t gDisplays[NUM_DISPLAYS];
94
95egl_display_t& egl_display_t::get_display(EGLDisplay dpy)
96{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -070097 return gDisplays[uintptr_t(dpy)-1U];
David Liaa1f54d2011-03-01 16:54:04 -080098}
99
100// ----------------------------------------------------------------------------
101
102struct egl_surface_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700103 enum {
104 PAGE_FLIP = 0x00000001,
105 MAGIC = 0x31415265
106 };
David Liaa1f54d2011-03-01 16:54:04 -0800107
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700108 uint32_t magic;
109 EGLDisplay dpy;
110 EGLConfig config;
111 EGLContext ctx;
David Liaa1f54d2011-03-01 16:54:04 -0800112
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700113 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
114 virtual ~egl_surface_t();
115 bool isValid() const;
116 virtual bool initCheck() const = 0;
David Liaa1f54d2011-03-01 16:54:04 -0800117
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700118 virtual EGLBoolean bindDrawSurface(GLES2Context* gl) = 0;
119 virtual EGLBoolean bindReadSurface(GLES2Context* gl) = 0;
120 virtual EGLBoolean connect() {
121 return EGL_TRUE;
122 }
123 virtual void disconnect() {}
124 virtual EGLint getWidth() const = 0;
125 virtual EGLint getHeight() const = 0;
David Liaa1f54d2011-03-01 16:54:04 -0800126
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700127 virtual EGLint getHorizontalResolution() const;
128 virtual EGLint getVerticalResolution() const;
129 virtual EGLint getRefreshRate() const;
130 virtual EGLint getSwapBehavior() const;
131 virtual EGLBoolean swapBuffers();
132 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
David Liaa1f54d2011-03-01 16:54:04 -0800133protected:
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700134 GGLSurface depth;
David Liaa1f54d2011-03-01 16:54:04 -0800135};
136
137egl_surface_t::egl_surface_t(EGLDisplay dpy,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700138 EGLConfig config,
139 int32_t depthFormat)
140: magic(MAGIC), dpy(dpy), config(config), ctx(0)
David Liaa1f54d2011-03-01 16:54:04 -0800141{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700142 depth.version = sizeof(GGLSurface);
143 depth.data = 0;
144 depth.format = (GGLPixelFormat)depthFormat;
David Liaa1f54d2011-03-01 16:54:04 -0800145}
146egl_surface_t::~egl_surface_t()
147{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700148 magic = 0;
149 free(depth.data);
David Liaa1f54d2011-03-01 16:54:04 -0800150}
151bool egl_surface_t::isValid() const
152{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700153 LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
154 return magic == MAGIC;
David Liaa1f54d2011-03-01 16:54:04 -0800155}
156
157EGLBoolean egl_surface_t::swapBuffers()
158{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700159 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -0800160}
161EGLint egl_surface_t::getHorizontalResolution() const
162{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700163 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaa1f54d2011-03-01 16:54:04 -0800164}
165EGLint egl_surface_t::getVerticalResolution() const
166{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700167 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaa1f54d2011-03-01 16:54:04 -0800168}
169EGLint egl_surface_t::getRefreshRate() const
170{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700171 return (60 * EGL_DISPLAY_SCALING);
David Liaa1f54d2011-03-01 16:54:04 -0800172}
173EGLint egl_surface_t::getSwapBehavior() const
174{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700175 return EGL_BUFFER_PRESERVED;
David Liaa1f54d2011-03-01 16:54:04 -0800176}
177EGLBoolean egl_surface_t::setSwapRectangle(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700178 EGLint l, EGLint t, EGLint w, EGLint h)
David Liaa1f54d2011-03-01 16:54:04 -0800179{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700180 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -0800181}
182
183// ----------------------------------------------------------------------------
184
185struct egl_window_surface_v2_t : public egl_surface_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700186 egl_window_surface_v2_t(
187 EGLDisplay dpy, EGLConfig config,
188 int32_t depthFormat,
189 ANativeWindow* window);
David Liaa1f54d2011-03-01 16:54:04 -0800190
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700191 ~egl_window_surface_v2_t();
David Liaa1f54d2011-03-01 16:54:04 -0800192
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700193 virtual bool initCheck() const {
194 return true; // TODO: report failure if ctor fails
195 }
196 virtual EGLBoolean swapBuffers();
197 virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
198 virtual EGLBoolean bindReadSurface(GLES2Context* gl);
199 virtual EGLBoolean connect();
200 virtual void disconnect();
201 virtual EGLint getWidth() const {
202 return width;
203 }
204 virtual EGLint getHeight() const {
205 return height;
206 }
207 virtual EGLint getHorizontalResolution() const;
208 virtual EGLint getVerticalResolution() const;
209 virtual EGLint getRefreshRate() const;
210 virtual EGLint getSwapBehavior() const;
211 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
David Liaa1f54d2011-03-01 16:54:04 -0800212
213private:
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700214 status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
215 status_t unlock(android_native_buffer_t* buf);
216 ANativeWindow* nativeWindow;
217 android_native_buffer_t* buffer;
218 android_native_buffer_t* previousBuffer;
219 gralloc_module_t const* module;
220 int width;
221 int height;
222 void* bits;
223 GGLFormat const* pixelFormatTable;
David Liaa1f54d2011-03-01 16:54:04 -0800224
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700225 struct Rect {
226 inline Rect() { };
227 inline Rect(int32_t w, int32_t h)
228 : left(0), top(0), right(w), bottom(h) { }
229 inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
230 : left(l), top(t), right(r), bottom(b) { }
231 Rect& andSelf(const Rect& r) {
232 left = max(left, r.left);
233 top = max(top, r.top);
234 right = min(right, r.right);
235 bottom = min(bottom, r.bottom);
236 return *this;
237 }
238 bool isEmpty() const {
239 return (left>=right || top>=bottom);
240 }
241 void dump(char const* what) {
242 LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
243 what, left, top, right-left, bottom-top);
244 }
David Liaa1f54d2011-03-01 16:54:04 -0800245
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700246 int32_t left;
247 int32_t top;
248 int32_t right;
249 int32_t bottom;
250 };
David Liaa1f54d2011-03-01 16:54:04 -0800251
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700252 struct Region {
253 inline Region() : count(0) { }
254 typedef Rect const* const_iterator;
255 const_iterator begin() const {
256 return storage;
257 }
258 const_iterator end() const {
259 return storage+count;
260 }
261 static Region subtract(const Rect& lhs, const Rect& rhs) {
262 Region reg;
263 Rect* storage = reg.storage;
264 if (!lhs.isEmpty()) {
265 if (lhs.top < rhs.top) { // top rect
266 storage->left = lhs.left;
267 storage->top = lhs.top;
268 storage->right = lhs.right;
269 storage->bottom = rhs.top;
270 storage++;
271 }
272 const int32_t top = max(lhs.top, rhs.top);
273 const int32_t bot = min(lhs.bottom, rhs.bottom);
274 if (top < bot) {
275 if (lhs.left < rhs.left) { // left-side rect
276 storage->left = lhs.left;
277 storage->top = top;
278 storage->right = rhs.left;
279 storage->bottom = bot;
280 storage++;
281 }
282 if (lhs.right > rhs.right) { // right-side rect
283 storage->left = rhs.right;
284 storage->top = top;
285 storage->right = lhs.right;
286 storage->bottom = bot;
287 storage++;
288 }
289 }
290 if (lhs.bottom > rhs.bottom) { // bottom rect
291 storage->left = lhs.left;
292 storage->top = rhs.bottom;
293 storage->right = lhs.right;
294 storage->bottom = lhs.bottom;
295 storage++;
296 }
297 reg.count = storage - reg.storage;
David Liaa1f54d2011-03-01 16:54:04 -0800298 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700299 return reg;
300 }
301 bool isEmpty() const {
302 return count<=0;
303 }
304 private:
305 Rect storage[4];
306 ssize_t count;
307 };
David Liaa1f54d2011-03-01 16:54:04 -0800308
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700309 void copyBlt(
310 android_native_buffer_t* dst, void* dst_vaddr,
311 android_native_buffer_t* src, void const* src_vaddr,
312 const Region& clip);
David Liaa1f54d2011-03-01 16:54:04 -0800313
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700314 Rect dirtyRegion;
315 Rect oldDirtyRegion;
David Liaa1f54d2011-03-01 16:54:04 -0800316};
317
318egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700319 EGLConfig config,
320 int32_t depthFormat,
321 ANativeWindow* window)
322: egl_surface_t(dpy, config, depthFormat),
323 nativeWindow(window), buffer(0), previousBuffer(0), module(0),
324 bits(NULL)
David Liaa1f54d2011-03-01 16:54:04 -0800325{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700326 pixelFormatTable = gglGetPixelFormatTable();
David Liaa1f54d2011-03-01 16:54:04 -0800327
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700328 // keep a reference on the window
329 nativeWindow->common.incRef(&nativeWindow->common);
330 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
331 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
332 int format = 0;
333 nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format);
334 LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format);
335 // assert(0);
David Liaa1f54d2011-03-01 16:54:04 -0800336}
337
338egl_window_surface_v2_t::~egl_window_surface_v2_t()
339{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700340 if (buffer) {
341 buffer->common.decRef(&buffer->common);
342 }
343 if (previousBuffer) {
344 previousBuffer->common.decRef(&previousBuffer->common);
345 }
346 nativeWindow->common.decRef(&nativeWindow->common);
David Liaa1f54d2011-03-01 16:54:04 -0800347}
348
349EGLBoolean egl_window_surface_v2_t::connect()
350{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700351 // we're intending to do software rendering
352 native_window_set_usage(nativeWindow,
353 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
David Liaa1f54d2011-03-01 16:54:04 -0800354
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700355 // dequeue a buffer
356 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
357 return setError(EGL_BAD_ALLOC, EGL_FALSE);
358 }
David Liaa1f54d2011-03-01 16:54:04 -0800359
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700360 // allocate a corresponding depth-buffer
361 width = buffer->width;
362 height = buffer->height;
363 if (depth.format) {
364 depth.width = width;
365 depth.height = height;
366 depth.stride = depth.width; // use the width here
367 assert(GGL_PIXEL_FORMAT_Z_32 == depth.format);
368 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*4);
369 if (depth.data == 0) {
370 return setError(EGL_BAD_ALLOC, EGL_FALSE);
371 }
372 }
David Liaa1f54d2011-03-01 16:54:04 -0800373
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700374 // keep a reference on the buffer
375 buffer->common.incRef(&buffer->common);
David Liaa1f54d2011-03-01 16:54:04 -0800376
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700377 // Lock the buffer
378 nativeWindow->lockBuffer(nativeWindow, buffer);
379 // pin the buffer down
380 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
David Liaa1f54d2011-03-01 16:54:04 -0800381 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700382 LOGE("connect() failed to lock buffer %p (%ux%u)",
383 buffer, buffer->width, buffer->height);
384 return setError(EGL_BAD_ACCESS, EGL_FALSE);
385 // FIXME: we should make sure we're not accessing the buffer anymore
386 }
387 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800388}
389
390void egl_window_surface_v2_t::disconnect()
391{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700392 if (buffer && bits) {
393 bits = NULL;
394 unlock(buffer);
395 }
396 // enqueue the last frame
397 if (buffer)
398 nativeWindow->queueBuffer(nativeWindow, buffer);
399 if (buffer) {
400 buffer->common.decRef(&buffer->common);
401 buffer = 0;
402 }
403 if (previousBuffer) {
404 previousBuffer->common.decRef(&previousBuffer->common);
405 previousBuffer = 0;
406 }
David Liaa1f54d2011-03-01 16:54:04 -0800407}
408
409status_t egl_window_surface_v2_t::lock(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700410 android_native_buffer_t* buf, int usage, void** vaddr)
David Liaa1f54d2011-03-01 16:54:04 -0800411{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700412 int err;
David Liaa1f54d2011-03-01 16:54:04 -0800413
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700414 err = module->lock(module, buf->handle,
415 usage, 0, 0, buf->width, buf->height, vaddr);
David Liaa1f54d2011-03-01 16:54:04 -0800416
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700417 return err;
David Liaa1f54d2011-03-01 16:54:04 -0800418}
419
420status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
421{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700422 if (!buf) return BAD_VALUE;
423 int err = NO_ERROR;
David Liaa1f54d2011-03-01 16:54:04 -0800424
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700425 err = module->unlock(module, buf->handle);
David Liaa1f54d2011-03-01 16:54:04 -0800426
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700427 return err;
David Liaa1f54d2011-03-01 16:54:04 -0800428}
429
430void egl_window_surface_v2_t::copyBlt(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700431 android_native_buffer_t* dst, void* dst_vaddr,
432 android_native_buffer_t* src, void const* src_vaddr,
433 const Region& clip)
David Liaa1f54d2011-03-01 16:54:04 -0800434{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700435 // FIXME: use copybit if possible
436 // NOTE: dst and src must be the same format
David Liaa1f54d2011-03-01 16:54:04 -0800437
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700438 Region::const_iterator cur = clip.begin();
439 Region::const_iterator end = clip.end();
David Liaa1f54d2011-03-01 16:54:04 -0800440
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700441 const size_t bpp = pixelFormatTable[src->format].size;
442 const size_t dbpr = dst->stride * bpp;
443 const size_t sbpr = src->stride * bpp;
David Liaa1f54d2011-03-01 16:54:04 -0800444
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700445 uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
446 uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
David Liaa1f54d2011-03-01 16:54:04 -0800447
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700448 while (cur != end) {
449 const Rect& r(*cur++);
450 ssize_t w = r.right - r.left;
451 ssize_t h = r.bottom - r.top;
452 if (w <= 0 || h<=0) continue;
453 size_t size = w * bpp;
454 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
455 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
456 if (dbpr==sbpr && size==sbpr) {
David Liaa1f54d2011-03-01 16:54:04 -0800457 size *= h;
458 h = 1;
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700459 }
460 do {
David Liaa1f54d2011-03-01 16:54:04 -0800461 memcpy(d, s, size);
462 d += dbpr;
463 s += sbpr;
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700464 } while (--h > 0);
465 }
David Liaa1f54d2011-03-01 16:54:04 -0800466}
467
468EGLBoolean egl_window_surface_v2_t::swapBuffers()
469{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700470 if (!buffer) {
471 return setError(EGL_BAD_ACCESS, EGL_FALSE);
472 }
David Liaa1f54d2011-03-01 16:54:04 -0800473
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700474 /*
475 * Handle eglSetSwapRectangleANDROID()
476 * We copyback from the front buffer
477 */
478 if (!dirtyRegion.isEmpty()) {
479 dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
480 if (previousBuffer) {
481 // This was const Region copyBack, but that causes an
482 // internal compile error on simulator builds
483 /*const*/
484 Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
485 if (!copyBack.isEmpty()) {
486 void* prevBits;
487 if (lock(previousBuffer,
488 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
489 // copy from previousBuffer to buffer
490 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
491 unlock(previousBuffer);
492 }
David Liaa1f54d2011-03-01 16:54:04 -0800493 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700494 }
495 oldDirtyRegion = dirtyRegion;
496 }
David Liaa1f54d2011-03-01 16:54:04 -0800497
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700498 if (previousBuffer) {
499 previousBuffer->common.decRef(&previousBuffer->common);
500 previousBuffer = 0;
501 }
David Liaa1f54d2011-03-01 16:54:04 -0800502
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700503 unlock(buffer);
504 previousBuffer = buffer;
505 nativeWindow->queueBuffer(nativeWindow, buffer);
506 buffer = 0;
David Liaa1f54d2011-03-01 16:54:04 -0800507
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700508 // dequeue a new buffer
509 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
David Liaa1f54d2011-03-01 16:54:04 -0800510
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700511 // TODO: lockBuffer should rather be executed when the very first
512 // direct rendering occurs.
513 nativeWindow->lockBuffer(nativeWindow, buffer);
David Liaa1f54d2011-03-01 16:54:04 -0800514
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700515 // reallocate the depth-buffer if needed
516 if ((width != buffer->width) || (height != buffer->height)) {
517 // TODO: we probably should reset the swap rect here
518 // if the window size has changed
519 width = buffer->width;
520 height = buffer->height;
521 if (depth.data) {
522 free(depth.data);
523 depth.width = width;
524 depth.height = height;
525 depth.stride = buffer->stride;
526 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
527 if (depth.data == 0) {
528 setError(EGL_BAD_ALLOC, EGL_FALSE);
529 return EGL_FALSE;
530 }
David Liaa1f54d2011-03-01 16:54:04 -0800531 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700532 }
David Liaa1f54d2011-03-01 16:54:04 -0800533
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700534 // keep a reference on the buffer
535 buffer->common.incRef(&buffer->common);
David Liaa1f54d2011-03-01 16:54:04 -0800536
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700537 // finally pin the buffer down
538 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
539 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
540 LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
541 buffer, buffer->width, buffer->height);
542 return setError(EGL_BAD_ACCESS, EGL_FALSE);
543 // FIXME: we should make sure we're not accessing the buffer anymore
544 }
545 } else {
546 return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
547 }
David Liaa1f54d2011-03-01 16:54:04 -0800548
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700549 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800550}
551
552EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700553 EGLint l, EGLint t, EGLint w, EGLint h)
David Liaa1f54d2011-03-01 16:54:04 -0800554{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700555 dirtyRegion = Rect(l, t, l+w, t+h);
556 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800557}
558
559EGLBoolean egl_window_surface_v2_t::bindDrawSurface(GLES2Context* gl)
560{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700561 GGLSurface buffer;
562 buffer.version = sizeof(GGLSurface);
563 buffer.width = this->buffer->width;
564 buffer.height = this->buffer->height;
565 buffer.stride = this->buffer->stride;
566 buffer.data = (GGLubyte*)bits;
567 buffer.format = (GGLPixelFormat)this->buffer->format;
568 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
569 if (depth.data != gl->rasterizer.depthSurface.data)
570 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
David Liaa1f54d2011-03-01 16:54:04 -0800571
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700572 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800573}
574EGLBoolean egl_window_surface_v2_t::bindReadSurface(GLES2Context* gl)
575{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700576 GGLSurface buffer;
577 buffer.version = sizeof(GGLSurface);
578 buffer.width = this->buffer->width;
579 buffer.height = this->buffer->height;
580 buffer.stride = this->buffer->stride;
581 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
582 buffer.format = (GGLPixelFormat)this->buffer->format;
583 puts("agl2: readBuffer not implemented");
584 //gl->rasterizer.interface.readBuffer(gl, &buffer);
585 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800586}
587EGLint egl_window_surface_v2_t::getHorizontalResolution() const
588{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700589 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaa1f54d2011-03-01 16:54:04 -0800590}
591EGLint egl_window_surface_v2_t::getVerticalResolution() const
592{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700593 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaa1f54d2011-03-01 16:54:04 -0800594}
595EGLint egl_window_surface_v2_t::getRefreshRate() const
596{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700597 return (60 * EGL_DISPLAY_SCALING); // FIXME
David Liaa1f54d2011-03-01 16:54:04 -0800598}
599EGLint egl_window_surface_v2_t::getSwapBehavior() const
600{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700601 /*
602 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
603 * the content of the swapped buffer.
604 *
605 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
606 *
607 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
608 * only applies to the area specified by eglSetSwapRectangleANDROID(), that
609 * is, everything outside of this area is preserved.
610 *
611 * This implementation of EGL assumes the later case.
612 *
613 */
David Liaa1f54d2011-03-01 16:54:04 -0800614
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700615 return EGL_BUFFER_DESTROYED;
David Liaa1f54d2011-03-01 16:54:04 -0800616}
617
618// ----------------------------------------------------------------------------
619
620struct egl_pixmap_surface_t : public egl_surface_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700621 egl_pixmap_surface_t(
622 EGLDisplay dpy, EGLConfig config,
623 int32_t depthFormat,
624 egl_native_pixmap_t const * pixmap);
David Liaa1f54d2011-03-01 16:54:04 -0800625
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700626 virtual ~egl_pixmap_surface_t() { }
David Liaa1f54d2011-03-01 16:54:04 -0800627
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700628 virtual bool initCheck() const {
629 return !depth.format || depth.data!=0;
630 }
631 virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
632 virtual EGLBoolean bindReadSurface(GLES2Context* gl);
633 virtual EGLint getWidth() const {
634 return nativePixmap.width;
635 }
636 virtual EGLint getHeight() const {
637 return nativePixmap.height;
638 }
David Liaa1f54d2011-03-01 16:54:04 -0800639private:
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700640 egl_native_pixmap_t nativePixmap;
David Liaa1f54d2011-03-01 16:54:04 -0800641};
642
643egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700644 EGLConfig config,
645 int32_t depthFormat,
646 egl_native_pixmap_t const * pixmap)
647: egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
David Liaa1f54d2011-03-01 16:54:04 -0800648{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700649 if (depthFormat) {
650 depth.width = pixmap->width;
651 depth.height = pixmap->height;
652 depth.stride = depth.width; // use the width here
653 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
654 if (depth.data == 0) {
655 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
656 }
657 }
David Liaa1f54d2011-03-01 16:54:04 -0800658}
659EGLBoolean egl_pixmap_surface_t::bindDrawSurface(GLES2Context* gl)
660{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700661 GGLSurface buffer;
662 buffer.version = sizeof(GGLSurface);
663 buffer.width = nativePixmap.width;
664 buffer.height = nativePixmap.height;
665 buffer.stride = nativePixmap.stride;
666 buffer.data = nativePixmap.data;
667 buffer.format = (GGLPixelFormat)nativePixmap.format;
David Liaa1f54d2011-03-01 16:54:04 -0800668
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700669 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
670 if (depth.data != gl->rasterizer.depthSurface.data)
671 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
672 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800673}
674EGLBoolean egl_pixmap_surface_t::bindReadSurface(GLES2Context* gl)
675{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700676 GGLSurface buffer;
677 buffer.version = sizeof(GGLSurface);
678 buffer.width = nativePixmap.width;
679 buffer.height = nativePixmap.height;
680 buffer.stride = nativePixmap.stride;
681 buffer.data = nativePixmap.data;
682 buffer.format = (GGLPixelFormat)nativePixmap.format;
683 puts("agl2: readBuffer not implemented");
684 //gl->rasterizer.interface.readBuffer(gl, &buffer);
685 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800686}
687
688// ----------------------------------------------------------------------------
689
690struct egl_pbuffer_surface_t : public egl_surface_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700691 egl_pbuffer_surface_t(
692 EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
693 int32_t w, int32_t h, int32_t f);
David Liaa1f54d2011-03-01 16:54:04 -0800694
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700695 virtual ~egl_pbuffer_surface_t();
David Liaa1f54d2011-03-01 16:54:04 -0800696
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700697 virtual bool initCheck() const {
698 return pbuffer.data != 0;
699 }
700 virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
701 virtual EGLBoolean bindReadSurface(GLES2Context* gl);
702 virtual EGLint getWidth() const {
703 return pbuffer.width;
704 }
705 virtual EGLint getHeight() const {
706 return pbuffer.height;
707 }
David Liaa1f54d2011-03-01 16:54:04 -0800708private:
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700709 GGLSurface pbuffer;
David Liaa1f54d2011-03-01 16:54:04 -0800710};
711
712egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700713 EGLConfig config, int32_t depthFormat,
714 int32_t w, int32_t h, int32_t f)
715: egl_surface_t(dpy, config, depthFormat)
David Liaa1f54d2011-03-01 16:54:04 -0800716{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700717 size_t size = w*h;
718 switch (f) {
719 case GGL_PIXEL_FORMAT_A_8:
720 size *= 1;
721 break;
722 case GGL_PIXEL_FORMAT_RGB_565:
723 size *= 2;
724 break;
725 case GGL_PIXEL_FORMAT_RGBA_8888:
726 size *= 4;
727 break;
728 case GGL_PIXEL_FORMAT_RGBX_8888:
729 size *= 4;
730 break;
731 default:
732 LOGE("incompatible pixel format for pbuffer (format=%d)", f);
733 pbuffer.data = 0;
734 break;
735 }
736 pbuffer.version = sizeof(GGLSurface);
737 pbuffer.width = w;
738 pbuffer.height = h;
739 pbuffer.stride = w;
740 pbuffer.data = (GGLubyte*)malloc(size);
741 pbuffer.format = (GGLPixelFormat)f;
David Liaa1f54d2011-03-01 16:54:04 -0800742
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700743 if (depthFormat) {
744 depth.width = pbuffer.width;
745 depth.height = pbuffer.height;
746 depth.stride = depth.width; // use the width here
747 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
748 if (depth.data == 0) {
749 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
750 return;
751 }
752 }
David Liaa1f54d2011-03-01 16:54:04 -0800753}
754egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
755{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700756 free(pbuffer.data);
David Liaa1f54d2011-03-01 16:54:04 -0800757}
758EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(GLES2Context* gl)
759{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700760 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer);
761 if (depth.data != gl->rasterizer.depthSurface.data)
762 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
763 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800764}
765EGLBoolean egl_pbuffer_surface_t::bindReadSurface(GLES2Context* gl)
766{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700767 puts("agl2: readBuffer not implemented");
768 //gl->rasterizer.interface.readBuffer(gl, &pbuffer);
769 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -0800770}
771
772// ----------------------------------------------------------------------------
773
774struct config_pair_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700775 GLint key;
776 GLint value;
David Liaa1f54d2011-03-01 16:54:04 -0800777};
778
779struct configs_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700780 const config_pair_t* array;
781 int size;
David Liaa1f54d2011-03-01 16:54:04 -0800782};
783
784struct config_management_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700785 GLint key;
786 bool (*match)(GLint reqValue, GLint confValue);
787 static bool atLeast(GLint reqValue, GLint confValue) {
788 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
789 }
790 static bool exact(GLint reqValue, GLint confValue) {
791 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
792 }
793 static bool mask(GLint reqValue, GLint confValue) {
794 return (confValue & reqValue) == reqValue;
795 }
796 static bool ignore(GLint reqValue, GLint confValue) {
797 return true;
798 }
David Liaa1f54d2011-03-01 16:54:04 -0800799};
800
801// ----------------------------------------------------------------------------
802
803#define VERSION_MAJOR 1
804#define VERSION_MINOR 2
805static char const * const gVendorString = "Google Inc.";
806static char const * const gVersionString = "0.0 Android Driver 0.0.0";
807static char const * const gClientApiString = "OpenGL ES2";
808static char const * const gExtensionsString =
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700809 //"EGL_KHR_image_base "
810 // "KHR_image_pixmap "
811 //"EGL_ANDROID_image_native_buffer "
812 //"EGL_ANDROID_swap_rectangle "
813 "";
David Liaa1f54d2011-03-01 16:54:04 -0800814
815// ----------------------------------------------------------------------------
816
817struct extention_map_t {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700818 const char * const name;
819 __eglMustCastToProperFunctionPointerType address;
David Liaa1f54d2011-03-01 16:54:04 -0800820};
821
822static const extention_map_t gExtentionMap[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700823 // { "glDrawTexsOES",
824 // (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
825 // { "glDrawTexiOES",
826 // (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
827 // { "glDrawTexfOES",
828 // (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
829 // { "glDrawTexxOES",
830 // (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
831 // { "glDrawTexsvOES",
832 // (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
833 // { "glDrawTexivOES",
834 // (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
835 // { "glDrawTexfvOES",
836 // (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
837 // { "glDrawTexxvOES",
838 // (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
839 // { "glQueryMatrixxOES",
840 // (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
841 // { "glEGLImageTargetTexture2DOES",
842 // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
843 // { "glEGLImageTargetRenderbufferStorageOES",
844 // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
845 // { "glClipPlanef",
846 // (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
847 // { "glClipPlanex",
848 // (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
849 // { "glBindBuffer",
850 // (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
851 // { "glBufferData",
852 // (__eglMustCastToProperFunctionPointerType)&glBufferData },
853 // { "glBufferSubData",
854 // (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
855 // { "glDeleteBuffers",
856 // (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
857 // { "glGenBuffers",
858 // (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
859 // { "eglCreateImageKHR",
860 // (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
861 // { "eglDestroyImageKHR",
862 // (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
863 // { "eglSetSwapRectangleANDROID",
864 // (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
David Liaa1f54d2011-03-01 16:54:04 -0800865};
866
867/*
868 * In the lists below, attributes names MUST be sorted.
869 * Additionally, all configs must be sorted according to
870 * the EGL specification.
871 */
872
873static config_pair_t const config_base_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700874 { EGL_STENCIL_SIZE, 0 },
875 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
876 { EGL_LEVEL, 0 },
877 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
878 { EGL_MAX_PBUFFER_PIXELS,
879 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
880 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
881 { EGL_NATIVE_RENDERABLE, EGL_TRUE },
882 { EGL_NATIVE_VISUAL_ID, 0 },
883 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGBA_8888 },
884 { EGL_SAMPLES, 0 },
885 { EGL_SAMPLE_BUFFERS, 0 },
886 { EGL_TRANSPARENT_TYPE, EGL_NONE },
887 { EGL_TRANSPARENT_BLUE_VALUE, 0 },
888 { EGL_TRANSPARENT_GREEN_VALUE, 0 },
889 { EGL_TRANSPARENT_RED_VALUE, 0 },
890 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
891 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
892 { EGL_MIN_SWAP_INTERVAL, 1 },
893 { EGL_MAX_SWAP_INTERVAL, 1 },
894 { EGL_LUMINANCE_SIZE, 0 },
895 { EGL_ALPHA_MASK_SIZE, 0 },
896 { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER },
897 { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT },
898 { EGL_CONFORMANT, 0 }
David Liaa1f54d2011-03-01 16:54:04 -0800899};
900
901// These configs can override the base attribute list
902// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
903
904// 565 configs
905static config_pair_t const config_0_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700906 { EGL_BUFFER_SIZE, 16 },
907 { EGL_ALPHA_SIZE, 0 },
908 { EGL_BLUE_SIZE, 5 },
909 { EGL_GREEN_SIZE, 6 },
910 { EGL_RED_SIZE, 5 },
911 { EGL_DEPTH_SIZE, 0 },
912 { EGL_CONFIG_ID, 0 },
913 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
914 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800915};
916
917static config_pair_t const config_1_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700918 { EGL_BUFFER_SIZE, 16 },
919 { EGL_ALPHA_SIZE, 0 },
920 { EGL_BLUE_SIZE, 5 },
921 { EGL_GREEN_SIZE, 6 },
922 { EGL_RED_SIZE, 5 },
923 { EGL_DEPTH_SIZE, 16 },
924 { EGL_CONFIG_ID, 1 },
925 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
926 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800927};
928
929// RGB 888 configs
930static config_pair_t const config_2_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700931 { EGL_BUFFER_SIZE, 32 },
932 { EGL_ALPHA_SIZE, 0 },
933 { EGL_BLUE_SIZE, 8 },
934 { EGL_GREEN_SIZE, 8 },
935 { EGL_RED_SIZE, 8 },
936 { EGL_DEPTH_SIZE, 0 },
937 { EGL_CONFIG_ID, 6 },
938 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
939 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800940};
941
942static config_pair_t const config_3_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700943 { EGL_BUFFER_SIZE, 32 },
944 { EGL_ALPHA_SIZE, 0 },
945 { EGL_BLUE_SIZE, 8 },
946 { EGL_GREEN_SIZE, 8 },
947 { EGL_RED_SIZE, 8 },
948 { EGL_DEPTH_SIZE, 16 },
949 { EGL_CONFIG_ID, 7 },
950 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
951 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800952};
953
954// 8888 configs
955static config_pair_t const config_4_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700956 { EGL_BUFFER_SIZE, 32 },
957 { EGL_ALPHA_SIZE, 8 },
958 { EGL_BLUE_SIZE, 8 },
959 { EGL_GREEN_SIZE, 8 },
960 { EGL_RED_SIZE, 8 },
961 { EGL_DEPTH_SIZE, 0 },
962 { EGL_CONFIG_ID, 2 },
963 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
964 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800965};
966
967static config_pair_t const config_5_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700968 { EGL_BUFFER_SIZE, 32 },
969 { EGL_ALPHA_SIZE, 8 },
970 { EGL_BLUE_SIZE, 8 },
971 { EGL_GREEN_SIZE, 8 },
972 { EGL_RED_SIZE, 8 },
973 { EGL_DEPTH_SIZE, 16 },
974 { EGL_CONFIG_ID, 3 },
975 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
976 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800977};
978
979// A8 configs
980static config_pair_t const config_6_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700981 { EGL_BUFFER_SIZE, 8 },
982 { EGL_ALPHA_SIZE, 8 },
983 { EGL_BLUE_SIZE, 0 },
984 { EGL_GREEN_SIZE, 0 },
985 { EGL_RED_SIZE, 0 },
986 { EGL_DEPTH_SIZE, 0 },
987 { EGL_CONFIG_ID, 4 },
988 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
989 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -0800990};
991
992static config_pair_t const config_7_attribute_list[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -0700993 { EGL_BUFFER_SIZE, 8 },
994 { EGL_ALPHA_SIZE, 8 },
995 { EGL_BLUE_SIZE, 0 },
996 { EGL_GREEN_SIZE, 0 },
997 { EGL_RED_SIZE, 0 },
998 { EGL_DEPTH_SIZE, 16 },
999 { EGL_CONFIG_ID, 5 },
1000 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
1001 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaa1f54d2011-03-01 16:54:04 -08001002};
1003
1004static configs_t const gConfigs[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001005 { config_0_attribute_list, NELEM(config_0_attribute_list) },
1006 { config_1_attribute_list, NELEM(config_1_attribute_list) },
1007 { config_2_attribute_list, NELEM(config_2_attribute_list) },
1008 { config_3_attribute_list, NELEM(config_3_attribute_list) },
1009 { config_4_attribute_list, NELEM(config_4_attribute_list) },
1010 { config_5_attribute_list, NELEM(config_5_attribute_list) },
1011 // { config_6_attribute_list, NELEM(config_6_attribute_list) },
1012 // { config_7_attribute_list, NELEM(config_7_attribute_list) },
David Liaa1f54d2011-03-01 16:54:04 -08001013};
1014
1015static config_management_t const gConfigManagement[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001016 { EGL_BUFFER_SIZE, config_management_t::atLeast },
1017 { EGL_ALPHA_SIZE, config_management_t::atLeast },
1018 { EGL_BLUE_SIZE, config_management_t::atLeast },
1019 { EGL_GREEN_SIZE, config_management_t::atLeast },
1020 { EGL_RED_SIZE, config_management_t::atLeast },
1021 { EGL_DEPTH_SIZE, config_management_t::atLeast },
1022 { EGL_STENCIL_SIZE, config_management_t::atLeast },
1023 { EGL_CONFIG_CAVEAT, config_management_t::exact },
1024 { EGL_CONFIG_ID, config_management_t::exact },
1025 { EGL_LEVEL, config_management_t::exact },
1026 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore },
1027 { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore },
1028 { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore },
1029 { EGL_NATIVE_RENDERABLE, config_management_t::exact },
1030 { EGL_NATIVE_VISUAL_ID, config_management_t::ignore },
1031 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
1032 { EGL_SAMPLES, config_management_t::exact },
1033 { EGL_SAMPLE_BUFFERS, config_management_t::exact },
1034 { EGL_SURFACE_TYPE, config_management_t::mask },
1035 { EGL_TRANSPARENT_TYPE, config_management_t::exact },
1036 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
1037 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
1038 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
1039 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
1040 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
1041 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
1042 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
1043 { EGL_LUMINANCE_SIZE, config_management_t::atLeast },
1044 { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast },
1045 { EGL_COLOR_BUFFER_TYPE, config_management_t::exact },
1046 { EGL_RENDERABLE_TYPE, config_management_t::mask },
1047 { EGL_CONFORMANT, config_management_t::mask }
David Liaa1f54d2011-03-01 16:54:04 -08001048};
1049
1050
1051static config_pair_t const config_defaults[] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001052 // attributes that are not specified are simply ignored, if a particular
1053 // one needs not be ignored, it must be specified here, eg:
1054 // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
David Liaa1f54d2011-03-01 16:54:04 -08001055};
1056
1057// ----------------------------------------------------------------------------
1058
1059static status_t getConfigFormatInfo(EGLint configID,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001060 int32_t& pixelFormat, int32_t& depthFormat)
David Liaa1f54d2011-03-01 16:54:04 -08001061{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001062 switch (configID) {
1063 case 0:
1064 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1065 depthFormat = 0;
1066 break;
1067 case 1:
1068 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1069 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1070 break;
1071 case 2:
1072 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1073 depthFormat = 0;
1074 break;
1075 case 3:
1076 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1077 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1078 break;
1079 case 4:
1080 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1081 depthFormat = 0;
1082 break;
1083 case 5:
1084 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1085 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1086 break;
1087 case 6:
1088 pixelFormat = GGL_PIXEL_FORMAT_A_8;
1089 depthFormat = 0;
1090 break;
1091 case 7:
1092 pixelFormat = GGL_PIXEL_FORMAT_A_8;
1093 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1094 break;
1095 default:
1096 return NAME_NOT_FOUND;
1097 }
1098 return NO_ERROR;
David Liaa1f54d2011-03-01 16:54:04 -08001099}
1100
1101// ----------------------------------------------------------------------------
1102
1103template<typename T>
1104static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
1105{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001106 while (first <= last) {
1107 int mid = (first + last) / 2;
1108 if (key > sortedArray[mid].key) {
1109 first = mid + 1;
1110 } else if (key < sortedArray[mid].key) {
1111 last = mid - 1;
1112 } else {
1113 return mid;
1114 }
1115 }
1116 return -1;
David Liaa1f54d2011-03-01 16:54:04 -08001117}
1118
1119static int isAttributeMatching(int i, EGLint attr, EGLint val)
1120{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001121 // look for the attribute in all of our configs
1122 config_pair_t const* configFound = gConfigs[i].array;
1123 int index = binarySearch<config_pair_t>(
1124 gConfigs[i].array,
1125 0, gConfigs[i].size-1,
1126 attr);
1127 if (index < 0) {
1128 configFound = config_base_attribute_list;
1129 index = binarySearch<config_pair_t>(
1130 config_base_attribute_list,
1131 0, NELEM(config_base_attribute_list)-1,
1132 attr);
1133 }
1134 if (index >= 0) {
1135 // attribute found, check if this config could match
1136 int cfgMgtIndex = binarySearch<config_management_t>(
1137 gConfigManagement,
1138 0, NELEM(gConfigManagement)-1,
1139 attr);
1140 if (cfgMgtIndex >= 0) {
1141 bool match = gConfigManagement[cfgMgtIndex].match(
1142 val, configFound[index].value);
1143 if (match) {
1144 // this config matches
1145 return 1;
1146 }
1147 } else {
1148 // attribute not found. this should NEVER happen.
1149 }
1150 } else {
1151 // error, this attribute doesn't exist
1152 }
1153 return 0;
David Liaa1f54d2011-03-01 16:54:04 -08001154}
1155
1156static int makeCurrent(GLES2Context* gl)
1157{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001158 GLES2Context* current = (GLES2Context*)getGlThreadSpecific();
1159 if (gl) {
1160 egl_context_t* c = egl_context_t::context(gl);
1161 if (c->flags & egl_context_t::IS_CURRENT) {
1162 if (current != gl) {
1163 // it is an error to set a context current, if it's already
1164 // current to another thread
1165 return -1;
1166 }
1167 } else {
1168 if (current) {
1169 // mark the current context as not current, and flush
1170 glFlush();
1171 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1172 }
1173 }
1174 if (!(c->flags & egl_context_t::IS_CURRENT)) {
1175 // The context is not current, make it current!
1176 setGlThreadSpecific(gl);
1177 c->flags |= egl_context_t::IS_CURRENT;
1178 }
1179 } else {
1180 if (current) {
David Liaa1f54d2011-03-01 16:54:04 -08001181 // mark the current context as not current, and flush
1182 glFlush();
1183 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001184 }
1185 // this thread has no context attached to it
1186 setGlThreadSpecific(0);
1187 }
1188 return 0;
David Liaa1f54d2011-03-01 16:54:04 -08001189}
1190
1191static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001192 EGLint attribute, EGLint *value)
David Liaa1f54d2011-03-01 16:54:04 -08001193{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001194 size_t numConfigs = NELEM(gConfigs);
1195 int index = (int)config;
1196 if (uint32_t(index) >= numConfigs)
1197 return setError(EGL_BAD_CONFIG, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001198
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001199 int attrIndex;
1200 attrIndex = binarySearch<config_pair_t>(
1201 gConfigs[index].array,
1202 0, gConfigs[index].size-1,
1203 attribute);
1204 if (attrIndex>=0) {
1205 *value = gConfigs[index].array[attrIndex].value;
1206 return EGL_TRUE;
1207 }
David Liaa1f54d2011-03-01 16:54:04 -08001208
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001209 attrIndex = binarySearch<config_pair_t>(
1210 config_base_attribute_list,
1211 0, NELEM(config_base_attribute_list)-1,
1212 attribute);
1213 if (attrIndex>=0) {
1214 *value = config_base_attribute_list[attrIndex].value;
1215 return EGL_TRUE;
1216 }
1217 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001218}
1219
1220static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001221 NativeWindowType window, const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001222{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001223 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1224 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1225 if (window == 0)
1226 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001227
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001228 EGLint surfaceType;
1229 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1230 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001231
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001232 if (!(surfaceType & EGL_WINDOW_BIT))
1233 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001234
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001235 if (reinterpret_cast<ANativeWindow*>(window)->common.magic !=
1236 ANDROID_NATIVE_WINDOW_MAGIC) {
1237 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
1238 }
David Liaa1f54d2011-03-01 16:54:04 -08001239
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001240 EGLint configID;
1241 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1242 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001243
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001244 int32_t depthFormat;
1245 int32_t pixelFormat;
1246 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
1247 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1248 }
David Liaa1f54d2011-03-01 16:54:04 -08001249
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001250 // FIXME: we don't have access to the pixelFormat here just yet.
1251 // (it's possible that the surface is not fully initialized)
1252 // maybe this should be done after the page-flip
1253 //if (EGLint(info.format) != pixelFormat)
1254 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001255
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001256 egl_surface_t* surface;
1257 surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
1258 reinterpret_cast<ANativeWindow*>(window));
David Liaa1f54d2011-03-01 16:54:04 -08001259
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001260 if (!surface->initCheck()) {
1261 // there was a problem in the ctor, the error
1262 // flag has been set.
1263 delete surface;
1264 surface = 0;
1265 }
1266 return surface;
David Liaa1f54d2011-03-01 16:54:04 -08001267}
1268
1269static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001270 NativePixmapType pixmap, const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001271{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001272 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1273 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1274 if (pixmap == 0)
1275 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001276
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001277 EGLint surfaceType;
1278 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1279 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001280
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001281 if (!(surfaceType & EGL_PIXMAP_BIT))
1282 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001283
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001284 if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version !=
1285 sizeof(egl_native_pixmap_t)) {
1286 return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1287 }
David Liaa1f54d2011-03-01 16:54:04 -08001288
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001289 EGLint configID;
1290 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1291 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001292
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001293 int32_t depthFormat;
1294 int32_t pixelFormat;
1295 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
1296 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1297 }
David Liaa1f54d2011-03-01 16:54:04 -08001298
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001299 if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat)
1300 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001301
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001302 egl_surface_t* surface =
1303 new egl_pixmap_surface_t(dpy, config, depthFormat,
1304 reinterpret_cast<egl_native_pixmap_t*>(pixmap));
David Liaa1f54d2011-03-01 16:54:04 -08001305
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001306 if (!surface->initCheck()) {
1307 // there was a problem in the ctor, the error
1308 // flag has been set.
1309 delete surface;
1310 surface = 0;
1311 }
1312 return surface;
David Liaa1f54d2011-03-01 16:54:04 -08001313}
1314
1315static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001316 const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001317{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001318 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1319 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001320
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001321 EGLint surfaceType;
1322 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1323 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001324
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001325 if (!(surfaceType & EGL_PBUFFER_BIT))
1326 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001327
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001328 EGLint configID;
1329 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1330 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001331
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001332 int32_t depthFormat;
1333 int32_t pixelFormat;
1334 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
1335 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1336 }
David Liaa1f54d2011-03-01 16:54:04 -08001337
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001338 int32_t w = 0;
1339 int32_t h = 0;
1340 while (attrib_list[0]) {
1341 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
1342 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
1343 attrib_list+=2;
1344 }
David Liaa1f54d2011-03-01 16:54:04 -08001345
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001346 egl_surface_t* surface =
1347 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
David Liaa1f54d2011-03-01 16:54:04 -08001348
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001349 if (!surface->initCheck()) {
1350 // there was a problem in the ctor, the error
1351 // flag has been set.
1352 delete surface;
1353 surface = 0;
1354 }
1355 return surface;
David Liaa1f54d2011-03-01 16:54:04 -08001356}
1357
1358// ----------------------------------------------------------------------------
1359}; // namespace android
1360// ----------------------------------------------------------------------------
1361
1362using namespace android;
1363
1364// ----------------------------------------------------------------------------
1365// Initialization
1366// ----------------------------------------------------------------------------
1367
1368EGLDisplay eglGetDisplay(NativeDisplayType display)
1369{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001370 puts("agl2:eglGetDisplay");
David Liaa1f54d2011-03-01 16:54:04 -08001371#ifndef HAVE_ANDROID_OS
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001372 // this just needs to be done once
1373 if (gGLKey == -1) {
1374 pthread_mutex_lock(&gInitMutex);
1375 if (gGLKey == -1)
1376 pthread_key_create(&gGLKey, NULL);
1377 pthread_mutex_unlock(&gInitMutex);
1378 }
David Liaa1f54d2011-03-01 16:54:04 -08001379#endif
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001380 if (display == EGL_DEFAULT_DISPLAY) {
1381 EGLDisplay dpy = (EGLDisplay)1;
1382 egl_display_t& d = egl_display_t::get_display(dpy);
1383 d.type = display;
1384 return dpy;
1385 }
1386 return EGL_NO_DISPLAY;
David Liaa1f54d2011-03-01 16:54:04 -08001387}
1388
1389EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
1390{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001391 puts("agl2:eglInitialize");
1392 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1393 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001394
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001395 EGLBoolean res = EGL_TRUE;
1396 egl_display_t& d = egl_display_t::get_display(dpy);
David Liaa1f54d2011-03-01 16:54:04 -08001397
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001398 if (android_atomic_inc(&d.initialized) == 0) {
1399 // initialize stuff here if needed
1400 //pthread_mutex_lock(&gInitMutex);
1401 //pthread_mutex_unlock(&gInitMutex);
1402 }
David Liaa1f54d2011-03-01 16:54:04 -08001403
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001404 if (res == EGL_TRUE) {
1405 if (major != NULL) *major = VERSION_MAJOR;
1406 if (minor != NULL) *minor = VERSION_MINOR;
1407 }
1408 return res;
David Liaa1f54d2011-03-01 16:54:04 -08001409}
1410
1411EGLBoolean eglTerminate(EGLDisplay dpy)
1412{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001413 puts("agl2:eglTerminate");
1414 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1415 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001416
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001417 EGLBoolean res = EGL_TRUE;
1418 egl_display_t& d = egl_display_t::get_display(dpy);
1419 if (android_atomic_dec(&d.initialized) == 1) {
1420 // TODO: destroy all resources (surfaces, contexts, etc...)
1421 //pthread_mutex_lock(&gInitMutex);
1422 //pthread_mutex_unlock(&gInitMutex);
1423 }
1424 return res;
David Liaa1f54d2011-03-01 16:54:04 -08001425}
1426
1427// ----------------------------------------------------------------------------
1428// configuration
1429// ----------------------------------------------------------------------------
1430
1431EGLBoolean eglGetConfigs( EGLDisplay dpy,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001432 EGLConfig *configs,
1433 EGLint config_size, EGLint *num_config)
David Liaa1f54d2011-03-01 16:54:04 -08001434{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001435 puts("agl2:eglGetConfigs");
1436 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1437 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001438
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001439 GLint numConfigs = NELEM(gConfigs);
1440 if (!configs) {
1441 *num_config = numConfigs;
1442 return EGL_TRUE;
1443 }
1444 GLint i;
1445 for (i=0 ; i<numConfigs && i<config_size ; i++) {
1446 *configs++ = (EGLConfig)i;
1447 }
1448 *num_config = i;
1449 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001450}
1451
1452static const char * ATTRIBUTE_NAMES [] = {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001453 "EGL_BUFFER_SIZE",
1454 "EGL_ALPHA_SIZE",
1455 "EGL_BLUE_SIZE",
1456 "EGL_GREEN_SIZE",
1457 "EGL_RED_SIZE",
1458 "EGL_DEPTH_SIZE",
1459 "EGL_STENCIL_SIZE",
1460 "EGL_CONFIG_CAVEAT",
1461 "EGL_CONFIG_ID",
1462 "EGL_LEVEL",
1463 "EGL_MAX_PBUFFER_HEIGHT",
1464 "EGL_MAX_PBUFFER_PIXELS",
1465 "EGL_MAX_PBUFFER_WIDTH",
1466 "EGL_NATIVE_RENDERABLE",
1467 "EGL_NATIVE_VISUAL_ID",
1468 "EGL_NATIVE_VISUAL_TYPE",
1469 "EGL_PRESERVED_RESOURCES",
1470 "EGL_SAMPLES",
1471 "EGL_SAMPLE_BUFFERS",
1472 "EGL_SURFACE_TYPE",
1473 "EGL_TRANSPARENT_TYPE",
1474 "EGL_TRANSPARENT_BLUE_VALUE",
1475 "EGL_TRANSPARENT_GREEN_VALUE",
1476 "EGL_TRANSPARENT_RED_VALUE",
1477 "EGL_NONE", /* Attrib list terminator */
1478 "EGL_BIND_TO_TEXTURE_RGB",
1479 "EGL_BIND_TO_TEXTURE_RGBA",
1480 "EGL_MIN_SWAP_INTERVAL",
1481 "EGL_MAX_SWAP_INTERVAL",
1482 "EGL_LUMINANCE_SIZE",
1483 "EGL_ALPHA_MASK_SIZE",
1484 "EGL_COLOR_BUFFER_TYPE",
1485 "EGL_RENDERABLE_TYPE",
1486 "EGL_MATCH_NATIVE_PIXMAP", /* Pseudo-attribute (not queryable) */
1487 "EGL_CONFORMANT",
David Liaa1f54d2011-03-01 16:54:04 -08001488};
1489
1490EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001491 EGLConfig *configs, EGLint config_size,
1492 EGLint *num_config)
David Liaa1f54d2011-03-01 16:54:04 -08001493{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001494 puts("agl2:eglChooseConfig");
1495 LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n");
1496 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1497 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001498
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001499 if (ggl_unlikely(num_config==0)) {
1500 LOGD("\n***\n***\n num_config==0 \n***\n***\n");
1501 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1502 }
David Liaa1f54d2011-03-01 16:54:04 -08001503
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001504 if (ggl_unlikely(attrib_list==0)) {
1505 /*
1506 * A NULL attrib_list should be treated as though it was an empty
1507 * one (terminated with EGL_NONE) as defined in
1508 * section 3.4.1 "Querying Configurations" in the EGL specification.
1509 */
1510 LOGD("\n***\n***\n attrib_list==0 \n***\n***\n");
1511 static const EGLint dummy = EGL_NONE;
1512 attrib_list = &dummy;
1513 }
David Liaa1f54d2011-03-01 16:54:04 -08001514
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001515 for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) {
1516 LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]);
1517 if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0])
1518 LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]);
1519 }
David Liaa1f54d2011-03-01 16:54:04 -08001520
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001521 int numAttributes = 0;
1522 int numConfigs = NELEM(gConfigs);
1523 uint32_t possibleMatch = (1<<numConfigs)-1;
1524 while (possibleMatch && *attrib_list != EGL_NONE) {
1525 numAttributes++;
1526 EGLint attr = *attrib_list++;
1527 EGLint val = *attrib_list++;
1528 for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
David Liaa1f54d2011-03-01 16:54:04 -08001529 if (!(possibleMatch & (1<<i)))
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001530 continue;
1531 if (isAttributeMatching(i, attr, val) == 0) {
1532 LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val);
1533 possibleMatch &= ~(1<<i);
David Liaa1f54d2011-03-01 16:54:04 -08001534 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001535 }
1536 }
David Liaa1f54d2011-03-01 16:54:04 -08001537
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001538 LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch);
1539
1540 // now, handle the attributes which have a useful default value
1541 for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
1542 // see if this attribute was specified, if not, apply its
1543 // default value
1544 if (binarySearch<config_pair_t>(
1545 (config_pair_t const*)attrib_list,
1546 0, numAttributes-1,
1547 config_defaults[j].key) < 0) {
1548 for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
1549 if (!(possibleMatch & (1<<i)))
1550 continue;
1551 if (isAttributeMatching(i,
1552 config_defaults[j].key,
1553 config_defaults[j].value) == 0) {
1554 possibleMatch &= ~(1<<i);
1555 }
David Liaa1f54d2011-03-01 16:54:04 -08001556 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001557 }
1558 }
1559
1560 // return the configurations found
1561 int n=0;
1562 if (possibleMatch) {
1563 if (configs) {
1564 for (int i=0 ; config_size && i<numConfigs ; i++) {
1565 if (possibleMatch & (1<<i)) {
1566 *configs++ = (EGLConfig)i;
1567 config_size--;
1568 n++;
1569 }
David Liaa1f54d2011-03-01 16:54:04 -08001570 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001571 } else {
1572 for (int i=0 ; i<numConfigs ; i++) {
1573 if (possibleMatch & (1<<i)) {
1574 n++;
1575 }
1576 }
1577 }
1578 }
1579 *num_config = n;
1580 LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config);
1581 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001582}
1583
1584EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001585 EGLint attribute, EGLint *value)
David Liaa1f54d2011-03-01 16:54:04 -08001586{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001587 puts("agl2:eglGetConfigAttrib");
1588 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1589 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001590
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001591 return getConfigAttrib(dpy, config, attribute, value);
David Liaa1f54d2011-03-01 16:54:04 -08001592}
1593
1594// ----------------------------------------------------------------------------
1595// surfaces
1596// ----------------------------------------------------------------------------
1597
1598EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001599 NativeWindowType window,
1600 const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001601{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001602 puts("agl2:eglCreateWindowSurface");
1603 return createWindowSurface(dpy, config, window, attrib_list);
David Liaa1f54d2011-03-01 16:54:04 -08001604}
1605
1606EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001607 NativePixmapType pixmap,
1608 const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001609{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001610 puts("agl2:eglCreatePixmapSurface");
1611 return createPixmapSurface(dpy, config, pixmap, attrib_list);
David Liaa1f54d2011-03-01 16:54:04 -08001612}
1613
1614EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001615 const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001616{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001617 puts("agl2:eglCreatePbufferSurface");
1618 return createPbufferSurface(dpy, config, attrib_list);
David Liaa1f54d2011-03-01 16:54:04 -08001619}
1620
1621EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1622{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001623 puts("agl2:eglDestroySurface");
1624 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1625 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1626 if (eglSurface != EGL_NO_SURFACE) {
1627 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1628 if (!surface->isValid())
1629 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1630 if (surface->dpy != dpy)
1631 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1632 if (surface->ctx) {
1633 // FIXME: this surface is current check what the spec says
1634 surface->disconnect();
1635 surface->ctx = 0;
1636 }
1637 delete surface;
1638 }
1639 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001640}
1641
1642EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001643 EGLint attribute, EGLint *value)
David Liaa1f54d2011-03-01 16:54:04 -08001644{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001645 puts("agl2:eglQuerySurface");
1646 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1647 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1648 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
1649 if (!surface->isValid())
1650 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1651 if (surface->dpy != dpy)
1652 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001653
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001654 EGLBoolean ret = EGL_TRUE;
1655 switch (attribute) {
1656 case EGL_CONFIG_ID:
1657 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
1658 break;
1659 case EGL_WIDTH:
1660 *value = surface->getWidth();
1661 break;
1662 case EGL_HEIGHT:
1663 *value = surface->getHeight();
1664 break;
1665 case EGL_LARGEST_PBUFFER:
1666 // not modified for a window or pixmap surface
1667 break;
1668 case EGL_TEXTURE_FORMAT:
1669 *value = EGL_NO_TEXTURE;
1670 break;
1671 case EGL_TEXTURE_TARGET:
1672 *value = EGL_NO_TEXTURE;
1673 break;
1674 case EGL_MIPMAP_TEXTURE:
1675 *value = EGL_FALSE;
1676 break;
1677 case EGL_MIPMAP_LEVEL:
1678 *value = 0;
1679 break;
1680 case EGL_RENDER_BUFFER:
1681 // TODO: return the real RENDER_BUFFER here
1682 *value = EGL_BACK_BUFFER;
1683 break;
1684 case EGL_HORIZONTAL_RESOLUTION:
1685 // pixel/mm * EGL_DISPLAY_SCALING
1686 *value = surface->getHorizontalResolution();
1687 break;
1688 case EGL_VERTICAL_RESOLUTION:
1689 // pixel/mm * EGL_DISPLAY_SCALING
1690 *value = surface->getVerticalResolution();
1691 break;
1692 case EGL_PIXEL_ASPECT_RATIO: {
1693 // w/h * EGL_DISPLAY_SCALING
1694 int wr = surface->getHorizontalResolution();
1695 int hr = surface->getVerticalResolution();
1696 *value = (wr * EGL_DISPLAY_SCALING) / hr;
1697 }
1698 break;
1699 case EGL_SWAP_BEHAVIOR:
1700 *value = surface->getSwapBehavior();
1701 break;
1702 default:
1703 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1704 }
1705 return ret;
David Liaa1f54d2011-03-01 16:54:04 -08001706}
1707
1708EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001709 EGLContext share_list, const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08001710{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001711 puts("agl2:eglCreateContext");
1712 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1713 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001714
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001715 GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t));
1716 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
David Liaa1f54d2011-03-01 16:54:04 -08001717
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001718 //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
1719 egl_context_t * c = &gl->egl;
1720 c->flags = egl_context_t::NEVER_CURRENT;
1721 c->dpy = dpy;
1722 c->config = config;
1723 c->read = 0;
1724 c->draw = 0;
1725
1726 c->frame = 0;
1727 c->lastSwapTime = clock();
1728 c->accumulateSeconds = 0;
1729 return (EGLContext)gl;
David Liaa1f54d2011-03-01 16:54:04 -08001730}
1731
1732EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1733{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001734 puts("agl2:eglDestroyContext");
1735 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1736 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1737 egl_context_t* c = egl_context_t::context(ctx);
1738 if (c->flags & egl_context_t::IS_CURRENT)
1739 setGlThreadSpecific(0);
1740 //ogles_uninit((GLES2Context*)ctx);
1741 delete (GLES2Context*)ctx;
1742 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001743}
1744
1745EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001746 EGLSurface read, EGLContext ctx)
David Liaa1f54d2011-03-01 16:54:04 -08001747{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001748 puts("agl2:eglMakeCurrent");
1749 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1750 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1751 if (draw) {
1752 egl_surface_t* s = (egl_surface_t*)draw;
1753 if (!s->isValid())
1754 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1755 if (s->dpy != dpy)
1756 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1757 // TODO: check that draw is compatible with the context
1758 }
1759 if (read && read!=draw) {
1760 egl_surface_t* s = (egl_surface_t*)read;
1761 if (!s->isValid())
1762 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1763 if (s->dpy != dpy)
1764 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1765 // TODO: check that read is compatible with the context
1766 }
David Liaa1f54d2011-03-01 16:54:04 -08001767
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001768 EGLContext current_ctx = EGL_NO_CONTEXT;
David Liaa1f54d2011-03-01 16:54:04 -08001769
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001770 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1771 return setError(EGL_BAD_MATCH, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001772
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001773 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1774 return setError(EGL_BAD_MATCH, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001775
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001776 if (ctx == EGL_NO_CONTEXT) {
1777 // if we're detaching, we need the current context
1778 current_ctx = (EGLContext)getGlThreadSpecific();
1779 } else {
1780 egl_context_t* c = egl_context_t::context(ctx);
1781 egl_surface_t* d = (egl_surface_t*)draw;
1782 egl_surface_t* r = (egl_surface_t*)read;
1783 if ((d && d->ctx && d->ctx != ctx) ||
1784 (r && r->ctx && r->ctx != ctx)) {
1785 // one of the surface is bound to a context in another thread
1786 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1787 }
1788 }
David Liaa1f54d2011-03-01 16:54:04 -08001789
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001790 GLES2Context* gl = (GLES2Context*)ctx;
1791 if (makeCurrent(gl) == 0) {
1792 if (ctx) {
1793 egl_context_t* c = egl_context_t::context(ctx);
1794 egl_surface_t* d = (egl_surface_t*)draw;
1795 egl_surface_t* r = (egl_surface_t*)read;
David Liaa1f54d2011-03-01 16:54:04 -08001796
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001797 if (c->draw) {
1798 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
1799 s->disconnect();
David Liaa1f54d2011-03-01 16:54:04 -08001800 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001801 if (c->read) {
1802 // FIXME: unlock/disconnect the read surface too
David Liaa1f54d2011-03-01 16:54:04 -08001803 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001804
1805 c->draw = draw;
1806 c->read = read;
1807
1808 if (c->flags & egl_context_t::NEVER_CURRENT) {
1809 c->flags &= ~egl_context_t::NEVER_CURRENT;
1810 GLint w = 0;
1811 GLint h = 0;
1812 if (draw) {
1813 w = d->getWidth();
1814 h = d->getHeight();
1815 }
1816 gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h);
1817 //ogles_surfaceport(gl, 0, 0);
1818 //ogles_viewport(gl, 0, 0, w, h);
1819 //ogles_scissor(gl, 0, 0, w, h);
1820 }
David Liaa1f54d2011-03-01 16:54:04 -08001821 if (d) {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001822 if (d->connect() == EGL_FALSE) {
1823 return EGL_FALSE;
1824 }
1825 d->ctx = ctx;
1826 d->bindDrawSurface(gl);
David Liaa1f54d2011-03-01 16:54:04 -08001827 }
1828 if (r) {
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001829 // FIXME: lock/connect the read surface too
1830 r->ctx = ctx;
1831 r->bindReadSurface(gl);
David Liaa1f54d2011-03-01 16:54:04 -08001832 }
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001833 } else {
1834 // if surfaces were bound to the context bound to this thread
1835 // mark then as unbound.
1836 if (current_ctx) {
1837 egl_context_t* c = egl_context_t::context(current_ctx);
1838 egl_surface_t* d = (egl_surface_t*)c->draw;
1839 egl_surface_t* r = (egl_surface_t*)c->read;
1840 if (d) {
1841 c->draw = 0;
1842 d->ctx = EGL_NO_CONTEXT;
1843 d->disconnect();
1844 }
1845 if (r) {
1846 c->read = 0;
1847 r->ctx = EGL_NO_CONTEXT;
1848 // FIXME: unlock/disconnect the read surface too
1849 }
1850 }
1851 }
1852 return EGL_TRUE;
1853 }
1854 return setError(EGL_BAD_ACCESS, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001855}
1856
1857EGLContext eglGetCurrentContext(void)
1858{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001859 // eglGetCurrentContext returns the current EGL rendering context,
1860 // as specified by eglMakeCurrent. If no context is current,
1861 // EGL_NO_CONTEXT is returned.
1862 return (EGLContext)getGlThreadSpecific();
David Liaa1f54d2011-03-01 16:54:04 -08001863}
1864
1865EGLSurface eglGetCurrentSurface(EGLint readdraw)
1866{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001867 // eglGetCurrentSurface returns the read or draw surface attached
1868 // to the current EGL rendering context, as specified by eglMakeCurrent.
1869 // If no context is current, EGL_NO_SURFACE is returned.
1870 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1871 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
1872 egl_context_t* c = egl_context_t::context(ctx);
1873 if (readdraw == EGL_READ) {
1874 return c->read;
1875 } else if (readdraw == EGL_DRAW) {
1876 return c->draw;
1877 }
1878 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08001879}
1880
1881EGLDisplay eglGetCurrentDisplay(void)
1882{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001883 // eglGetCurrentDisplay returns the current EGL display connection
1884 // for the current EGL rendering context, as specified by eglMakeCurrent.
1885 // If no context is current, EGL_NO_DISPLAY is returned.
1886 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1887 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
1888 egl_context_t* c = egl_context_t::context(ctx);
1889 return c->dpy;
David Liaa1f54d2011-03-01 16:54:04 -08001890}
1891
1892EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001893 EGLint attribute, EGLint *value)
David Liaa1f54d2011-03-01 16:54:04 -08001894{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001895 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1896 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1897 egl_context_t* c = egl_context_t::context(ctx);
1898 switch (attribute) {
1899 case EGL_CONFIG_ID:
1900 // Returns the ID of the EGL frame buffer configuration with
1901 // respect to which the context was created
1902 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
1903 }
1904 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001905}
1906
1907EGLBoolean eglWaitGL(void)
1908{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001909 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001910}
1911
1912EGLBoolean eglWaitNative(EGLint engine)
1913{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001914 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001915}
1916
1917EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1918{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001919 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1920 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001921
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001922 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
1923 if (!d->isValid())
1924 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1925 if (d->dpy != dpy)
1926 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08001927
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001928 // post the surface
1929 d->swapBuffers();
David Liaa1f54d2011-03-01 16:54:04 -08001930
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001931 // if it's bound to a context, update the buffer
1932 if (d->ctx != EGL_NO_CONTEXT) {
1933 d->bindDrawSurface((GLES2Context*)d->ctx);
1934 // if this surface is also the read surface of the context
1935 // it is bound to, make sure to update the read buffer as well.
1936 // The EGL spec is a little unclear about this.
1937 egl_context_t* c = egl_context_t::context(d->ctx);
1938 if (c->read == draw) {
1939 d->bindReadSurface((GLES2Context*)d->ctx);
1940 }
1941 clock_t time = clock();
1942 float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC;
1943 c->accumulateSeconds += elapsed;
1944 c->frame++;
1945 // LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000);
1946 if (20 == c->frame) {
1947 float avg = c->accumulateSeconds / c->frame;
1948 LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*",
1949 c->frame, 1 / avg, avg * 1000);
1950 c->frame = 0;
1951 c->accumulateSeconds = 0;
1952 }
1953 c->lastSwapTime = time;
1954 }
David Liaa1f54d2011-03-01 16:54:04 -08001955
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001956 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08001957}
1958
1959EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001960 NativePixmapType target)
David Liaa1f54d2011-03-01 16:54:04 -08001961{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001962 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1963 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1964 // TODO: eglCopyBuffers()
1965 return EGL_FALSE;
David Liaa1f54d2011-03-01 16:54:04 -08001966}
1967
1968EGLint eglGetError(void)
1969{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001970 return getError();
David Liaa1f54d2011-03-01 16:54:04 -08001971}
1972
1973const char* eglQueryString(EGLDisplay dpy, EGLint name)
1974{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001975 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1976 return setError(EGL_BAD_DISPLAY, (const char*)0);
David Liaa1f54d2011-03-01 16:54:04 -08001977
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001978 switch (name) {
1979 case EGL_VENDOR:
1980 return gVendorString;
1981 case EGL_VERSION:
1982 return gVersionString;
1983 case EGL_EXTENSIONS:
1984 return gExtensionsString;
1985 case EGL_CLIENT_APIS:
1986 return gClientApiString;
1987 }
1988 return setError(EGL_BAD_PARAMETER, (const char *)0);
David Liaa1f54d2011-03-01 16:54:04 -08001989}
1990
1991// ----------------------------------------------------------------------------
1992// EGL 1.1
1993// ----------------------------------------------------------------------------
1994
1995EGLBoolean eglSurfaceAttrib(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001996 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
David Liaa1f54d2011-03-01 16:54:04 -08001997{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07001998 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1999 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2000 // TODO: eglSurfaceAttrib()
2001 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002002}
2003
2004EGLBoolean eglBindTexImage(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002005 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
David Liaa1f54d2011-03-01 16:54:04 -08002006{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002007 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2008 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2009 // TODO: eglBindTexImage()
2010 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002011}
2012
2013EGLBoolean eglReleaseTexImage(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002014 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
David Liaa1f54d2011-03-01 16:54:04 -08002015{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002016 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2017 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2018 // TODO: eglReleaseTexImage()
2019 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002020}
2021
2022EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
2023{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002024 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2025 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2026 // TODO: eglSwapInterval()
2027 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08002028}
2029
2030// ----------------------------------------------------------------------------
2031// EGL 1.2
2032// ----------------------------------------------------------------------------
2033
2034EGLBoolean eglBindAPI(EGLenum api)
2035{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002036 if (api != EGL_OPENGL_ES_API)
2037 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2038 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08002039}
2040
2041EGLenum eglQueryAPI(void)
2042{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002043 return EGL_OPENGL_ES_API;
David Liaa1f54d2011-03-01 16:54:04 -08002044}
2045
2046EGLBoolean eglWaitClient(void)
2047{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002048 glFinish();
2049 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08002050}
2051
2052EGLBoolean eglReleaseThread(void)
2053{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002054 // TODO: eglReleaseThread()
2055 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08002056}
2057
2058EGLSurface eglCreatePbufferFromClientBuffer(
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002059 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
2060 EGLConfig config, const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08002061{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002062 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2063 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
2064 // TODO: eglCreatePbufferFromClientBuffer()
2065 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
David Liaa1f54d2011-03-01 16:54:04 -08002066}
2067
2068// ----------------------------------------------------------------------------
2069// EGL_EGLEXT_VERSION 3
2070// ----------------------------------------------------------------------------
2071
2072void (*eglGetProcAddress (const char *procname))()
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002073 {
2074 extention_map_t const * const map = gExtentionMap;
2075 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
2076 if (!strcmp(procname, map[i].name)) {
2077 return map[i].address;
2078 }
2079 }
2080 return NULL;
2081 }
David Liaa1f54d2011-03-01 16:54:04 -08002082
2083EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002084 const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08002085{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002086 EGLBoolean result = EGL_FALSE;
2087 return result;
David Liaa1f54d2011-03-01 16:54:04 -08002088}
2089
2090EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
2091{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002092 EGLBoolean result = EGL_FALSE;
2093 return result;
David Liaa1f54d2011-03-01 16:54:04 -08002094}
2095
2096EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002097 EGLClientBuffer buffer, const EGLint *attrib_list)
David Liaa1f54d2011-03-01 16:54:04 -08002098{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002099 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2100 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
2101 }
2102 if (ctx != EGL_NO_CONTEXT) {
2103 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
2104 }
2105 if (target != EGL_NATIVE_BUFFER_ANDROID) {
2106 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2107 }
David Liaa1f54d2011-03-01 16:54:04 -08002108
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002109 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
David Liaa1f54d2011-03-01 16:54:04 -08002110
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002111 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2112 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
David Liaa1f54d2011-03-01 16:54:04 -08002113
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002114 if (native_buffer->common.version != sizeof(android_native_buffer_t))
2115 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
David Liaa1f54d2011-03-01 16:54:04 -08002116
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002117 switch (native_buffer->format) {
2118 case HAL_PIXEL_FORMAT_RGBA_8888:
2119 case HAL_PIXEL_FORMAT_RGBX_8888:
2120 case HAL_PIXEL_FORMAT_RGB_888:
2121 case HAL_PIXEL_FORMAT_RGB_565:
2122 case HAL_PIXEL_FORMAT_BGRA_8888:
2123 case HAL_PIXEL_FORMAT_RGBA_5551:
2124 case HAL_PIXEL_FORMAT_RGBA_4444:
2125 break;
2126 default:
2127 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2128 }
David Liaa1f54d2011-03-01 16:54:04 -08002129
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002130 native_buffer->common.incRef(&native_buffer->common);
2131 return (EGLImageKHR)native_buffer;
David Liaa1f54d2011-03-01 16:54:04 -08002132}
2133
2134EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2135{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002136 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2137 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2138 }
David Liaa1f54d2011-03-01 16:54:04 -08002139
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002140 android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
David Liaa1f54d2011-03-01 16:54:04 -08002141
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002142 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2143 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002144
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002145 if (native_buffer->common.version != sizeof(android_native_buffer_t))
2146 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002147
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002148 native_buffer->common.decRef(&native_buffer->common);
David Liaa1f54d2011-03-01 16:54:04 -08002149
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002150 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08002151}
2152
2153// ----------------------------------------------------------------------------
2154// ANDROID extensions
2155// ----------------------------------------------------------------------------
2156
2157EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002158 EGLint left, EGLint top, EGLint width, EGLint height)
David Liaa1f54d2011-03-01 16:54:04 -08002159{
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002160 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2161 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002162
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002163 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
2164 if (!d->isValid())
2165 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2166 if (d->dpy != dpy)
2167 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaa1f54d2011-03-01 16:54:04 -08002168
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002169 // post the surface
2170 d->setSwapRectangle(left, top, width, height);
David Liaa1f54d2011-03-01 16:54:04 -08002171
Mathias Agopian9cdb01d2011-04-28 19:50:21 -07002172 return EGL_TRUE;
David Liaa1f54d2011-03-01 16:54:04 -08002173}