blob: 0d02ce66bbc513c99aec56fbae445c0eeaf2c556 [file] [log] [blame]
David Liaf94ceb2011-03-01 16:54:04 -08001/*
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-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 Liaf94ceb2011-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 Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -080062}
63
64static GLint getError()
65{
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -080076}
77
78// ----------------------------------------------------------------------------
79
80struct egl_display_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -070081 egl_display_t() : type(0), initialized(0) { }
David Liaf94ceb2011-03-01 16:54:04 -080082
Mathias Agopian8e86a7a2011-04-28 19:50:21 -070083 static egl_display_t& get_display(EGLDisplay dpy);
David Liaf94ceb2011-03-01 16:54:04 -080084
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -080088
Mathias Agopian8e86a7a2011-04-28 19:50:21 -070089 NativeDisplayType type;
90 volatile int32_t initialized;
David Liaf94ceb2011-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 Agopian8e86a7a2011-04-28 19:50:21 -070097 return gDisplays[uintptr_t(dpy)-1U];
David Liaf94ceb2011-03-01 16:54:04 -080098}
99
100// ----------------------------------------------------------------------------
101
102struct egl_surface_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700103 enum {
104 PAGE_FLIP = 0x00000001,
105 MAGIC = 0x31415265
106 };
David Liaf94ceb2011-03-01 16:54:04 -0800107
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700108 uint32_t magic;
109 EGLDisplay dpy;
110 EGLConfig config;
111 EGLContext ctx;
David Liaf94ceb2011-03-01 16:54:04 -0800112
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800117
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800126
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800133protected:
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700134 GGLSurface depth;
David Liaf94ceb2011-03-01 16:54:04 -0800135};
136
137egl_surface_t::egl_surface_t(EGLDisplay dpy,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700138 EGLConfig config,
139 int32_t depthFormat)
140: magic(MAGIC), dpy(dpy), config(config), ctx(0)
David Liaf94ceb2011-03-01 16:54:04 -0800141{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700142 depth.version = sizeof(GGLSurface);
143 depth.data = 0;
144 depth.format = (GGLPixelFormat)depthFormat;
David Liaf94ceb2011-03-01 16:54:04 -0800145}
146egl_surface_t::~egl_surface_t()
147{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700148 magic = 0;
149 free(depth.data);
David Liaf94ceb2011-03-01 16:54:04 -0800150}
151bool egl_surface_t::isValid() const
152{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700153 LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
154 return magic == MAGIC;
David Liaf94ceb2011-03-01 16:54:04 -0800155}
156
157EGLBoolean egl_surface_t::swapBuffers()
158{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700159 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -0800160}
161EGLint egl_surface_t::getHorizontalResolution() const
162{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700163 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaf94ceb2011-03-01 16:54:04 -0800164}
165EGLint egl_surface_t::getVerticalResolution() const
166{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700167 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaf94ceb2011-03-01 16:54:04 -0800168}
169EGLint egl_surface_t::getRefreshRate() const
170{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700171 return (60 * EGL_DISPLAY_SCALING);
David Liaf94ceb2011-03-01 16:54:04 -0800172}
173EGLint egl_surface_t::getSwapBehavior() const
174{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700175 return EGL_BUFFER_PRESERVED;
David Liaf94ceb2011-03-01 16:54:04 -0800176}
177EGLBoolean egl_surface_t::setSwapRectangle(
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700178 EGLint l, EGLint t, EGLint w, EGLint h)
David Liaf94ceb2011-03-01 16:54:04 -0800179{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700180 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -0800181}
182
183// ----------------------------------------------------------------------------
184
185struct egl_window_surface_v2_t : public egl_surface_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700186 egl_window_surface_v2_t(
187 EGLDisplay dpy, EGLConfig config,
188 int32_t depthFormat,
189 ANativeWindow* window);
David Liaf94ceb2011-03-01 16:54:04 -0800190
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700191 ~egl_window_surface_v2_t();
David Liaf94ceb2011-03-01 16:54:04 -0800192
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800212
213private:
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700214 status_t lock(ANativeWindowBuffer* buf, int usage, void** vaddr);
215 status_t unlock(ANativeWindowBuffer* buf);
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700216 ANativeWindow* nativeWindow;
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700217 ANativeWindowBuffer* buffer;
218 ANativeWindowBuffer* previousBuffer;
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700219 gralloc_module_t const* module;
220 int width;
221 int height;
222 void* bits;
223 GGLFormat const* pixelFormatTable;
David Liaf94ceb2011-03-01 16:54:04 -0800224
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800245
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700246 int32_t left;
247 int32_t top;
248 int32_t right;
249 int32_t bottom;
250 };
David Liaf94ceb2011-03-01 16:54:04 -0800251
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800298 }
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800308
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700309 void copyBlt(
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700310 ANativeWindowBuffer* dst, void* dst_vaddr,
311 ANativeWindowBuffer* src, void const* src_vaddr,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700312 const Region& clip);
David Liaf94ceb2011-03-01 16:54:04 -0800313
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700314 Rect dirtyRegion;
315 Rect oldDirtyRegion;
David Liaf94ceb2011-03-01 16:54:04 -0800316};
317
318egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800325{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700326 pixelFormatTable = gglGetPixelFormatTable();
David Liaf94ceb2011-03-01 16:54:04 -0800327
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800336}
337
338egl_window_surface_v2_t::~egl_window_surface_v2_t()
339{
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800347}
348
349EGLBoolean egl_window_surface_v2_t::connect()
350{
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800354
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800359
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800373
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700374 // keep a reference on the buffer
375 buffer->common.incRef(&buffer->common);
David Liaf94ceb2011-03-01 16:54:04 -0800376
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800381 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800388}
389
390void egl_window_surface_v2_t::disconnect()
391{
Mathias Agopian8e86a7a2011-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 Liaf94ceb2011-03-01 16:54:04 -0800407}
408
409status_t egl_window_surface_v2_t::lock(
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700410 ANativeWindowBuffer* buf, int usage, void** vaddr)
David Liaf94ceb2011-03-01 16:54:04 -0800411{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700412 int err;
David Liaf94ceb2011-03-01 16:54:04 -0800413
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700414 err = module->lock(module, buf->handle,
415 usage, 0, 0, buf->width, buf->height, vaddr);
David Liaf94ceb2011-03-01 16:54:04 -0800416
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700417 return err;
David Liaf94ceb2011-03-01 16:54:04 -0800418}
419
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700420status_t egl_window_surface_v2_t::unlock(ANativeWindowBuffer* buf)
David Liaf94ceb2011-03-01 16:54:04 -0800421{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700422 if (!buf) return BAD_VALUE;
423 int err = NO_ERROR;
David Liaf94ceb2011-03-01 16:54:04 -0800424
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700425 err = module->unlock(module, buf->handle);
David Liaf94ceb2011-03-01 16:54:04 -0800426
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700427 return err;
David Liaf94ceb2011-03-01 16:54:04 -0800428}
429
430void egl_window_surface_v2_t::copyBlt(
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700431 ANativeWindowBuffer* dst, void* dst_vaddr,
432 ANativeWindowBuffer* src, void const* src_vaddr,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700433 const Region& clip)
David Liaf94ceb2011-03-01 16:54:04 -0800434{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700435 // NOTE: dst and src must be the same format
David Liaf94ceb2011-03-01 16:54:04 -0800436
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700437 Region::const_iterator cur = clip.begin();
438 Region::const_iterator end = clip.end();
David Liaf94ceb2011-03-01 16:54:04 -0800439
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700440 const size_t bpp = pixelFormatTable[src->format].size;
441 const size_t dbpr = dst->stride * bpp;
442 const size_t sbpr = src->stride * bpp;
David Liaf94ceb2011-03-01 16:54:04 -0800443
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700444 uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
445 uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
David Liaf94ceb2011-03-01 16:54:04 -0800446
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700447 while (cur != end) {
448 const Rect& r(*cur++);
449 ssize_t w = r.right - r.left;
450 ssize_t h = r.bottom - r.top;
451 if (w <= 0 || h<=0) continue;
452 size_t size = w * bpp;
453 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
454 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
455 if (dbpr==sbpr && size==sbpr) {
David Liaf94ceb2011-03-01 16:54:04 -0800456 size *= h;
457 h = 1;
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700458 }
459 do {
David Liaf94ceb2011-03-01 16:54:04 -0800460 memcpy(d, s, size);
461 d += dbpr;
462 s += sbpr;
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700463 } while (--h > 0);
464 }
David Liaf94ceb2011-03-01 16:54:04 -0800465}
466
467EGLBoolean egl_window_surface_v2_t::swapBuffers()
468{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700469 if (!buffer) {
470 return setError(EGL_BAD_ACCESS, EGL_FALSE);
471 }
David Liaf94ceb2011-03-01 16:54:04 -0800472
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700473 /*
474 * Handle eglSetSwapRectangleANDROID()
475 * We copyback from the front buffer
476 */
477 if (!dirtyRegion.isEmpty()) {
478 dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
479 if (previousBuffer) {
480 // This was const Region copyBack, but that causes an
481 // internal compile error on simulator builds
482 /*const*/
483 Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
484 if (!copyBack.isEmpty()) {
485 void* prevBits;
486 if (lock(previousBuffer,
487 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
488 // copy from previousBuffer to buffer
489 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
490 unlock(previousBuffer);
491 }
David Liaf94ceb2011-03-01 16:54:04 -0800492 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700493 }
494 oldDirtyRegion = dirtyRegion;
495 }
David Liaf94ceb2011-03-01 16:54:04 -0800496
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700497 if (previousBuffer) {
498 previousBuffer->common.decRef(&previousBuffer->common);
499 previousBuffer = 0;
500 }
David Liaf94ceb2011-03-01 16:54:04 -0800501
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700502 unlock(buffer);
503 previousBuffer = buffer;
504 nativeWindow->queueBuffer(nativeWindow, buffer);
505 buffer = 0;
David Liaf94ceb2011-03-01 16:54:04 -0800506
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700507 // dequeue a new buffer
508 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
David Liaf94ceb2011-03-01 16:54:04 -0800509
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700510 // TODO: lockBuffer should rather be executed when the very first
511 // direct rendering occurs.
512 nativeWindow->lockBuffer(nativeWindow, buffer);
David Liaf94ceb2011-03-01 16:54:04 -0800513
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700514 // reallocate the depth-buffer if needed
515 if ((width != buffer->width) || (height != buffer->height)) {
516 // TODO: we probably should reset the swap rect here
517 // if the window size has changed
518 width = buffer->width;
519 height = buffer->height;
520 if (depth.data) {
521 free(depth.data);
522 depth.width = width;
523 depth.height = height;
524 depth.stride = buffer->stride;
525 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
526 if (depth.data == 0) {
527 setError(EGL_BAD_ALLOC, EGL_FALSE);
528 return EGL_FALSE;
529 }
David Liaf94ceb2011-03-01 16:54:04 -0800530 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700531 }
David Liaf94ceb2011-03-01 16:54:04 -0800532
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700533 // keep a reference on the buffer
534 buffer->common.incRef(&buffer->common);
David Liaf94ceb2011-03-01 16:54:04 -0800535
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700536 // finally pin the buffer down
537 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
538 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
539 LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
540 buffer, buffer->width, buffer->height);
541 return setError(EGL_BAD_ACCESS, EGL_FALSE);
542 // FIXME: we should make sure we're not accessing the buffer anymore
543 }
544 } else {
545 return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
546 }
David Liaf94ceb2011-03-01 16:54:04 -0800547
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700548 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800549}
550
551EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700552 EGLint l, EGLint t, EGLint w, EGLint h)
David Liaf94ceb2011-03-01 16:54:04 -0800553{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700554 dirtyRegion = Rect(l, t, l+w, t+h);
555 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800556}
557
558EGLBoolean egl_window_surface_v2_t::bindDrawSurface(GLES2Context* gl)
559{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700560 GGLSurface buffer;
561 buffer.version = sizeof(GGLSurface);
562 buffer.width = this->buffer->width;
563 buffer.height = this->buffer->height;
564 buffer.stride = this->buffer->stride;
565 buffer.data = (GGLubyte*)bits;
566 buffer.format = (GGLPixelFormat)this->buffer->format;
567 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
568 if (depth.data != gl->rasterizer.depthSurface.data)
569 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
David Liaf94ceb2011-03-01 16:54:04 -0800570
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700571 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800572}
573EGLBoolean egl_window_surface_v2_t::bindReadSurface(GLES2Context* gl)
574{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700575 GGLSurface buffer;
576 buffer.version = sizeof(GGLSurface);
577 buffer.width = this->buffer->width;
578 buffer.height = this->buffer->height;
579 buffer.stride = this->buffer->stride;
580 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
581 buffer.format = (GGLPixelFormat)this->buffer->format;
582 puts("agl2: readBuffer not implemented");
583 //gl->rasterizer.interface.readBuffer(gl, &buffer);
584 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800585}
586EGLint egl_window_surface_v2_t::getHorizontalResolution() const
587{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700588 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaf94ceb2011-03-01 16:54:04 -0800589}
590EGLint egl_window_surface_v2_t::getVerticalResolution() const
591{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700592 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
David Liaf94ceb2011-03-01 16:54:04 -0800593}
594EGLint egl_window_surface_v2_t::getRefreshRate() const
595{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700596 return (60 * EGL_DISPLAY_SCALING); // FIXME
David Liaf94ceb2011-03-01 16:54:04 -0800597}
598EGLint egl_window_surface_v2_t::getSwapBehavior() const
599{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700600 /*
601 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
602 * the content of the swapped buffer.
603 *
604 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
605 *
606 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
607 * only applies to the area specified by eglSetSwapRectangleANDROID(), that
608 * is, everything outside of this area is preserved.
609 *
610 * This implementation of EGL assumes the later case.
611 *
612 */
David Liaf94ceb2011-03-01 16:54:04 -0800613
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700614 return EGL_BUFFER_DESTROYED;
David Liaf94ceb2011-03-01 16:54:04 -0800615}
616
617// ----------------------------------------------------------------------------
618
619struct egl_pixmap_surface_t : public egl_surface_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700620 egl_pixmap_surface_t(
621 EGLDisplay dpy, EGLConfig config,
622 int32_t depthFormat,
623 egl_native_pixmap_t const * pixmap);
David Liaf94ceb2011-03-01 16:54:04 -0800624
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700625 virtual ~egl_pixmap_surface_t() { }
David Liaf94ceb2011-03-01 16:54:04 -0800626
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700627 virtual bool initCheck() const {
628 return !depth.format || depth.data!=0;
629 }
630 virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
631 virtual EGLBoolean bindReadSurface(GLES2Context* gl);
632 virtual EGLint getWidth() const {
633 return nativePixmap.width;
634 }
635 virtual EGLint getHeight() const {
636 return nativePixmap.height;
637 }
David Liaf94ceb2011-03-01 16:54:04 -0800638private:
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700639 egl_native_pixmap_t nativePixmap;
David Liaf94ceb2011-03-01 16:54:04 -0800640};
641
642egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700643 EGLConfig config,
644 int32_t depthFormat,
645 egl_native_pixmap_t const * pixmap)
646: egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
David Liaf94ceb2011-03-01 16:54:04 -0800647{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700648 if (depthFormat) {
649 depth.width = pixmap->width;
650 depth.height = pixmap->height;
651 depth.stride = depth.width; // use the width here
652 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
653 if (depth.data == 0) {
654 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
655 }
656 }
David Liaf94ceb2011-03-01 16:54:04 -0800657}
658EGLBoolean egl_pixmap_surface_t::bindDrawSurface(GLES2Context* gl)
659{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700660 GGLSurface buffer;
661 buffer.version = sizeof(GGLSurface);
662 buffer.width = nativePixmap.width;
663 buffer.height = nativePixmap.height;
664 buffer.stride = nativePixmap.stride;
665 buffer.data = nativePixmap.data;
666 buffer.format = (GGLPixelFormat)nativePixmap.format;
David Liaf94ceb2011-03-01 16:54:04 -0800667
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700668 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
669 if (depth.data != gl->rasterizer.depthSurface.data)
670 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
671 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800672}
673EGLBoolean egl_pixmap_surface_t::bindReadSurface(GLES2Context* gl)
674{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700675 GGLSurface buffer;
676 buffer.version = sizeof(GGLSurface);
677 buffer.width = nativePixmap.width;
678 buffer.height = nativePixmap.height;
679 buffer.stride = nativePixmap.stride;
680 buffer.data = nativePixmap.data;
681 buffer.format = (GGLPixelFormat)nativePixmap.format;
682 puts("agl2: readBuffer not implemented");
683 //gl->rasterizer.interface.readBuffer(gl, &buffer);
684 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800685}
686
687// ----------------------------------------------------------------------------
688
689struct egl_pbuffer_surface_t : public egl_surface_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700690 egl_pbuffer_surface_t(
691 EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
692 int32_t w, int32_t h, int32_t f);
David Liaf94ceb2011-03-01 16:54:04 -0800693
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700694 virtual ~egl_pbuffer_surface_t();
David Liaf94ceb2011-03-01 16:54:04 -0800695
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700696 virtual bool initCheck() const {
697 return pbuffer.data != 0;
698 }
699 virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
700 virtual EGLBoolean bindReadSurface(GLES2Context* gl);
701 virtual EGLint getWidth() const {
702 return pbuffer.width;
703 }
704 virtual EGLint getHeight() const {
705 return pbuffer.height;
706 }
David Liaf94ceb2011-03-01 16:54:04 -0800707private:
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700708 GGLSurface pbuffer;
David Liaf94ceb2011-03-01 16:54:04 -0800709};
710
711egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700712 EGLConfig config, int32_t depthFormat,
713 int32_t w, int32_t h, int32_t f)
714: egl_surface_t(dpy, config, depthFormat)
David Liaf94ceb2011-03-01 16:54:04 -0800715{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700716 size_t size = w*h;
717 switch (f) {
718 case GGL_PIXEL_FORMAT_A_8:
719 size *= 1;
720 break;
721 case GGL_PIXEL_FORMAT_RGB_565:
722 size *= 2;
723 break;
724 case GGL_PIXEL_FORMAT_RGBA_8888:
725 size *= 4;
726 break;
727 case GGL_PIXEL_FORMAT_RGBX_8888:
728 size *= 4;
729 break;
730 default:
731 LOGE("incompatible pixel format for pbuffer (format=%d)", f);
732 pbuffer.data = 0;
733 break;
734 }
735 pbuffer.version = sizeof(GGLSurface);
736 pbuffer.width = w;
737 pbuffer.height = h;
738 pbuffer.stride = w;
739 pbuffer.data = (GGLubyte*)malloc(size);
740 pbuffer.format = (GGLPixelFormat)f;
David Liaf94ceb2011-03-01 16:54:04 -0800741
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700742 if (depthFormat) {
743 depth.width = pbuffer.width;
744 depth.height = pbuffer.height;
745 depth.stride = depth.width; // use the width here
746 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
747 if (depth.data == 0) {
748 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
749 return;
750 }
751 }
David Liaf94ceb2011-03-01 16:54:04 -0800752}
753egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
754{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700755 free(pbuffer.data);
David Liaf94ceb2011-03-01 16:54:04 -0800756}
757EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(GLES2Context* gl)
758{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700759 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer);
760 if (depth.data != gl->rasterizer.depthSurface.data)
761 gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
762 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800763}
764EGLBoolean egl_pbuffer_surface_t::bindReadSurface(GLES2Context* gl)
765{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700766 puts("agl2: readBuffer not implemented");
767 //gl->rasterizer.interface.readBuffer(gl, &pbuffer);
768 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -0800769}
770
771// ----------------------------------------------------------------------------
772
773struct config_pair_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700774 GLint key;
775 GLint value;
David Liaf94ceb2011-03-01 16:54:04 -0800776};
777
778struct configs_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700779 const config_pair_t* array;
780 int size;
David Liaf94ceb2011-03-01 16:54:04 -0800781};
782
783struct config_management_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700784 GLint key;
785 bool (*match)(GLint reqValue, GLint confValue);
786 static bool atLeast(GLint reqValue, GLint confValue) {
787 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
788 }
789 static bool exact(GLint reqValue, GLint confValue) {
790 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
791 }
792 static bool mask(GLint reqValue, GLint confValue) {
793 return (confValue & reqValue) == reqValue;
794 }
795 static bool ignore(GLint reqValue, GLint confValue) {
796 return true;
797 }
David Liaf94ceb2011-03-01 16:54:04 -0800798};
799
800// ----------------------------------------------------------------------------
801
802#define VERSION_MAJOR 1
803#define VERSION_MINOR 2
804static char const * const gVendorString = "Google Inc.";
805static char const * const gVersionString = "0.0 Android Driver 0.0.0";
806static char const * const gClientApiString = "OpenGL ES2";
807static char const * const gExtensionsString =
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700808 //"EGL_KHR_image_base "
809 // "KHR_image_pixmap "
810 //"EGL_ANDROID_image_native_buffer "
811 //"EGL_ANDROID_swap_rectangle "
812 "";
David Liaf94ceb2011-03-01 16:54:04 -0800813
814// ----------------------------------------------------------------------------
815
816struct extention_map_t {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700817 const char * const name;
818 __eglMustCastToProperFunctionPointerType address;
David Liaf94ceb2011-03-01 16:54:04 -0800819};
820
821static const extention_map_t gExtentionMap[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700822 // { "glDrawTexsOES",
823 // (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
824 // { "glDrawTexiOES",
825 // (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
826 // { "glDrawTexfOES",
827 // (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
828 // { "glDrawTexxOES",
829 // (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
830 // { "glDrawTexsvOES",
831 // (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
832 // { "glDrawTexivOES",
833 // (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
834 // { "glDrawTexfvOES",
835 // (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
836 // { "glDrawTexxvOES",
837 // (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
838 // { "glQueryMatrixxOES",
839 // (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
840 // { "glEGLImageTargetTexture2DOES",
841 // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
842 // { "glEGLImageTargetRenderbufferStorageOES",
843 // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
844 // { "glClipPlanef",
845 // (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
846 // { "glClipPlanex",
847 // (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
848 // { "glBindBuffer",
849 // (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
850 // { "glBufferData",
851 // (__eglMustCastToProperFunctionPointerType)&glBufferData },
852 // { "glBufferSubData",
853 // (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
854 // { "glDeleteBuffers",
855 // (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
856 // { "glGenBuffers",
857 // (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
858 // { "eglCreateImageKHR",
859 // (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
860 // { "eglDestroyImageKHR",
861 // (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
862 // { "eglSetSwapRectangleANDROID",
863 // (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
David Liaf94ceb2011-03-01 16:54:04 -0800864};
865
866/*
867 * In the lists below, attributes names MUST be sorted.
868 * Additionally, all configs must be sorted according to
869 * the EGL specification.
870 */
871
872static config_pair_t const config_base_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700873 { EGL_STENCIL_SIZE, 0 },
874 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
875 { EGL_LEVEL, 0 },
876 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
877 { EGL_MAX_PBUFFER_PIXELS,
878 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
879 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
880 { EGL_NATIVE_RENDERABLE, EGL_TRUE },
881 { EGL_NATIVE_VISUAL_ID, 0 },
882 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGBA_8888 },
883 { EGL_SAMPLES, 0 },
884 { EGL_SAMPLE_BUFFERS, 0 },
885 { EGL_TRANSPARENT_TYPE, EGL_NONE },
886 { EGL_TRANSPARENT_BLUE_VALUE, 0 },
887 { EGL_TRANSPARENT_GREEN_VALUE, 0 },
888 { EGL_TRANSPARENT_RED_VALUE, 0 },
889 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
890 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
891 { EGL_MIN_SWAP_INTERVAL, 1 },
892 { EGL_MAX_SWAP_INTERVAL, 1 },
893 { EGL_LUMINANCE_SIZE, 0 },
894 { EGL_ALPHA_MASK_SIZE, 0 },
895 { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER },
896 { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT },
897 { EGL_CONFORMANT, 0 }
David Liaf94ceb2011-03-01 16:54:04 -0800898};
899
900// These configs can override the base attribute list
901// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
902
903// 565 configs
904static config_pair_t const config_0_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700905 { EGL_BUFFER_SIZE, 16 },
906 { EGL_ALPHA_SIZE, 0 },
907 { EGL_BLUE_SIZE, 5 },
908 { EGL_GREEN_SIZE, 6 },
909 { EGL_RED_SIZE, 5 },
910 { EGL_DEPTH_SIZE, 0 },
911 { EGL_CONFIG_ID, 0 },
912 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
913 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800914};
915
916static config_pair_t const config_1_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700917 { EGL_BUFFER_SIZE, 16 },
918 { EGL_ALPHA_SIZE, 0 },
919 { EGL_BLUE_SIZE, 5 },
920 { EGL_GREEN_SIZE, 6 },
921 { EGL_RED_SIZE, 5 },
922 { EGL_DEPTH_SIZE, 16 },
923 { EGL_CONFIG_ID, 1 },
924 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
925 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800926};
927
928// RGB 888 configs
929static config_pair_t const config_2_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700930 { EGL_BUFFER_SIZE, 32 },
931 { EGL_ALPHA_SIZE, 0 },
932 { EGL_BLUE_SIZE, 8 },
933 { EGL_GREEN_SIZE, 8 },
934 { EGL_RED_SIZE, 8 },
935 { EGL_DEPTH_SIZE, 0 },
936 { EGL_CONFIG_ID, 6 },
937 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
938 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800939};
940
941static config_pair_t const config_3_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700942 { EGL_BUFFER_SIZE, 32 },
943 { EGL_ALPHA_SIZE, 0 },
944 { EGL_BLUE_SIZE, 8 },
945 { EGL_GREEN_SIZE, 8 },
946 { EGL_RED_SIZE, 8 },
947 { EGL_DEPTH_SIZE, 16 },
948 { EGL_CONFIG_ID, 7 },
949 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
950 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800951};
952
953// 8888 configs
954static config_pair_t const config_4_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700955 { EGL_BUFFER_SIZE, 32 },
956 { EGL_ALPHA_SIZE, 8 },
957 { EGL_BLUE_SIZE, 8 },
958 { EGL_GREEN_SIZE, 8 },
959 { EGL_RED_SIZE, 8 },
960 { EGL_DEPTH_SIZE, 0 },
961 { EGL_CONFIG_ID, 2 },
962 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
963 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800964};
965
966static config_pair_t const config_5_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700967 { EGL_BUFFER_SIZE, 32 },
968 { EGL_ALPHA_SIZE, 8 },
969 { EGL_BLUE_SIZE, 8 },
970 { EGL_GREEN_SIZE, 8 },
971 { EGL_RED_SIZE, 8 },
972 { EGL_DEPTH_SIZE, 16 },
973 { EGL_CONFIG_ID, 3 },
974 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
975 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800976};
977
978// A8 configs
979static config_pair_t const config_6_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700980 { EGL_BUFFER_SIZE, 8 },
981 { EGL_ALPHA_SIZE, 8 },
982 { EGL_BLUE_SIZE, 0 },
983 { EGL_GREEN_SIZE, 0 },
984 { EGL_RED_SIZE, 0 },
985 { EGL_DEPTH_SIZE, 0 },
986 { EGL_CONFIG_ID, 4 },
987 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
988 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -0800989};
990
991static config_pair_t const config_7_attribute_list[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -0700992 { EGL_BUFFER_SIZE, 8 },
993 { EGL_ALPHA_SIZE, 8 },
994 { EGL_BLUE_SIZE, 0 },
995 { EGL_GREEN_SIZE, 0 },
996 { EGL_RED_SIZE, 0 },
997 { EGL_DEPTH_SIZE, 16 },
998 { EGL_CONFIG_ID, 5 },
999 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
1000 { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
David Liaf94ceb2011-03-01 16:54:04 -08001001};
1002
1003static configs_t const gConfigs[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001004 { config_0_attribute_list, NELEM(config_0_attribute_list) },
1005 { config_1_attribute_list, NELEM(config_1_attribute_list) },
1006 { config_2_attribute_list, NELEM(config_2_attribute_list) },
1007 { config_3_attribute_list, NELEM(config_3_attribute_list) },
1008 { config_4_attribute_list, NELEM(config_4_attribute_list) },
1009 { config_5_attribute_list, NELEM(config_5_attribute_list) },
1010 // { config_6_attribute_list, NELEM(config_6_attribute_list) },
1011 // { config_7_attribute_list, NELEM(config_7_attribute_list) },
David Liaf94ceb2011-03-01 16:54:04 -08001012};
1013
1014static config_management_t const gConfigManagement[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001015 { EGL_BUFFER_SIZE, config_management_t::atLeast },
1016 { EGL_ALPHA_SIZE, config_management_t::atLeast },
1017 { EGL_BLUE_SIZE, config_management_t::atLeast },
1018 { EGL_GREEN_SIZE, config_management_t::atLeast },
1019 { EGL_RED_SIZE, config_management_t::atLeast },
1020 { EGL_DEPTH_SIZE, config_management_t::atLeast },
1021 { EGL_STENCIL_SIZE, config_management_t::atLeast },
1022 { EGL_CONFIG_CAVEAT, config_management_t::exact },
1023 { EGL_CONFIG_ID, config_management_t::exact },
1024 { EGL_LEVEL, config_management_t::exact },
1025 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore },
1026 { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore },
1027 { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore },
1028 { EGL_NATIVE_RENDERABLE, config_management_t::exact },
1029 { EGL_NATIVE_VISUAL_ID, config_management_t::ignore },
1030 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
1031 { EGL_SAMPLES, config_management_t::exact },
1032 { EGL_SAMPLE_BUFFERS, config_management_t::exact },
1033 { EGL_SURFACE_TYPE, config_management_t::mask },
1034 { EGL_TRANSPARENT_TYPE, config_management_t::exact },
1035 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
1036 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
1037 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
1038 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
1039 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
1040 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
1041 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
1042 { EGL_LUMINANCE_SIZE, config_management_t::atLeast },
1043 { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast },
1044 { EGL_COLOR_BUFFER_TYPE, config_management_t::exact },
1045 { EGL_RENDERABLE_TYPE, config_management_t::mask },
1046 { EGL_CONFORMANT, config_management_t::mask }
David Liaf94ceb2011-03-01 16:54:04 -08001047};
1048
1049
1050static config_pair_t const config_defaults[] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001051 // attributes that are not specified are simply ignored, if a particular
1052 // one needs not be ignored, it must be specified here, eg:
1053 // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
David Liaf94ceb2011-03-01 16:54:04 -08001054};
1055
1056// ----------------------------------------------------------------------------
1057
1058static status_t getConfigFormatInfo(EGLint configID,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001059 int32_t& pixelFormat, int32_t& depthFormat)
David Liaf94ceb2011-03-01 16:54:04 -08001060{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001061 switch (configID) {
1062 case 0:
1063 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1064 depthFormat = 0;
1065 break;
1066 case 1:
1067 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
1068 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1069 break;
1070 case 2:
1071 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1072 depthFormat = 0;
1073 break;
1074 case 3:
1075 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1076 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1077 break;
1078 case 4:
1079 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1080 depthFormat = 0;
1081 break;
1082 case 5:
1083 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
1084 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1085 break;
1086 case 6:
1087 pixelFormat = GGL_PIXEL_FORMAT_A_8;
1088 depthFormat = 0;
1089 break;
1090 case 7:
1091 pixelFormat = GGL_PIXEL_FORMAT_A_8;
1092 depthFormat = GGL_PIXEL_FORMAT_Z_32;
1093 break;
1094 default:
1095 return NAME_NOT_FOUND;
1096 }
1097 return NO_ERROR;
David Liaf94ceb2011-03-01 16:54:04 -08001098}
1099
1100// ----------------------------------------------------------------------------
1101
1102template<typename T>
1103static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
1104{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001105 while (first <= last) {
1106 int mid = (first + last) / 2;
1107 if (key > sortedArray[mid].key) {
1108 first = mid + 1;
1109 } else if (key < sortedArray[mid].key) {
1110 last = mid - 1;
1111 } else {
1112 return mid;
1113 }
1114 }
1115 return -1;
David Liaf94ceb2011-03-01 16:54:04 -08001116}
1117
1118static int isAttributeMatching(int i, EGLint attr, EGLint val)
1119{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001120 // look for the attribute in all of our configs
1121 config_pair_t const* configFound = gConfigs[i].array;
1122 int index = binarySearch<config_pair_t>(
1123 gConfigs[i].array,
1124 0, gConfigs[i].size-1,
1125 attr);
1126 if (index < 0) {
1127 configFound = config_base_attribute_list;
1128 index = binarySearch<config_pair_t>(
1129 config_base_attribute_list,
1130 0, NELEM(config_base_attribute_list)-1,
1131 attr);
1132 }
1133 if (index >= 0) {
1134 // attribute found, check if this config could match
1135 int cfgMgtIndex = binarySearch<config_management_t>(
1136 gConfigManagement,
1137 0, NELEM(gConfigManagement)-1,
1138 attr);
1139 if (cfgMgtIndex >= 0) {
1140 bool match = gConfigManagement[cfgMgtIndex].match(
1141 val, configFound[index].value);
1142 if (match) {
1143 // this config matches
1144 return 1;
1145 }
1146 } else {
1147 // attribute not found. this should NEVER happen.
1148 }
1149 } else {
1150 // error, this attribute doesn't exist
1151 }
1152 return 0;
David Liaf94ceb2011-03-01 16:54:04 -08001153}
1154
1155static int makeCurrent(GLES2Context* gl)
1156{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001157 GLES2Context* current = (GLES2Context*)getGlThreadSpecific();
1158 if (gl) {
1159 egl_context_t* c = egl_context_t::context(gl);
1160 if (c->flags & egl_context_t::IS_CURRENT) {
1161 if (current != gl) {
1162 // it is an error to set a context current, if it's already
1163 // current to another thread
1164 return -1;
1165 }
1166 } else {
1167 if (current) {
1168 // mark the current context as not current, and flush
1169 glFlush();
1170 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1171 }
1172 }
1173 if (!(c->flags & egl_context_t::IS_CURRENT)) {
1174 // The context is not current, make it current!
1175 setGlThreadSpecific(gl);
1176 c->flags |= egl_context_t::IS_CURRENT;
1177 }
1178 } else {
1179 if (current) {
David Liaf94ceb2011-03-01 16:54:04 -08001180 // mark the current context as not current, and flush
1181 glFlush();
1182 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001183 }
1184 // this thread has no context attached to it
1185 setGlThreadSpecific(0);
1186 }
1187 return 0;
David Liaf94ceb2011-03-01 16:54:04 -08001188}
1189
1190static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001191 EGLint attribute, EGLint *value)
David Liaf94ceb2011-03-01 16:54:04 -08001192{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001193 size_t numConfigs = NELEM(gConfigs);
1194 int index = (int)config;
1195 if (uint32_t(index) >= numConfigs)
1196 return setError(EGL_BAD_CONFIG, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001197
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001198 int attrIndex;
1199 attrIndex = binarySearch<config_pair_t>(
1200 gConfigs[index].array,
1201 0, gConfigs[index].size-1,
1202 attribute);
1203 if (attrIndex>=0) {
1204 *value = gConfigs[index].array[attrIndex].value;
1205 return EGL_TRUE;
1206 }
David Liaf94ceb2011-03-01 16:54:04 -08001207
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001208 attrIndex = binarySearch<config_pair_t>(
1209 config_base_attribute_list,
1210 0, NELEM(config_base_attribute_list)-1,
1211 attribute);
1212 if (attrIndex>=0) {
1213 *value = config_base_attribute_list[attrIndex].value;
1214 return EGL_TRUE;
1215 }
1216 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001217}
1218
1219static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001220 NativeWindowType window, const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001221{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001222 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1223 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1224 if (window == 0)
1225 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001226
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001227 EGLint surfaceType;
1228 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1229 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001230
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001231 if (!(surfaceType & EGL_WINDOW_BIT))
1232 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001233
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001234 if (reinterpret_cast<ANativeWindow*>(window)->common.magic !=
1235 ANDROID_NATIVE_WINDOW_MAGIC) {
1236 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
1237 }
David Liaf94ceb2011-03-01 16:54:04 -08001238
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001239 EGLint configID;
1240 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1241 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001242
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001243 int32_t depthFormat;
1244 int32_t pixelFormat;
1245 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
1246 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1247 }
David Liaf94ceb2011-03-01 16:54:04 -08001248
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001249 // FIXME: we don't have access to the pixelFormat here just yet.
1250 // (it's possible that the surface is not fully initialized)
1251 // maybe this should be done after the page-flip
1252 //if (EGLint(info.format) != pixelFormat)
1253 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001254
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001255 egl_surface_t* surface;
1256 surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
1257 reinterpret_cast<ANativeWindow*>(window));
David Liaf94ceb2011-03-01 16:54:04 -08001258
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001259 if (!surface->initCheck()) {
1260 // there was a problem in the ctor, the error
1261 // flag has been set.
1262 delete surface;
1263 surface = 0;
1264 }
1265 return surface;
David Liaf94ceb2011-03-01 16:54:04 -08001266}
1267
1268static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001269 NativePixmapType pixmap, const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001270{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001271 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1272 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1273 if (pixmap == 0)
1274 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001275
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001276 EGLint surfaceType;
1277 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1278 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001279
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001280 if (!(surfaceType & EGL_PIXMAP_BIT))
1281 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001282
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001283 if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version !=
1284 sizeof(egl_native_pixmap_t)) {
1285 return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1286 }
David Liaf94ceb2011-03-01 16:54:04 -08001287
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001288 EGLint configID;
1289 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1290 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001291
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001292 int32_t depthFormat;
1293 int32_t pixelFormat;
1294 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
1295 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1296 }
David Liaf94ceb2011-03-01 16:54:04 -08001297
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001298 if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat)
1299 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001300
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001301 egl_surface_t* surface =
1302 new egl_pixmap_surface_t(dpy, config, depthFormat,
1303 reinterpret_cast<egl_native_pixmap_t*>(pixmap));
David Liaf94ceb2011-03-01 16:54:04 -08001304
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001305 if (!surface->initCheck()) {
1306 // there was a problem in the ctor, the error
1307 // flag has been set.
1308 delete surface;
1309 surface = 0;
1310 }
1311 return surface;
David Liaf94ceb2011-03-01 16:54:04 -08001312}
1313
1314static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001315 const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001316{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001317 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1318 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001319
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001320 EGLint surfaceType;
1321 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1322 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001323
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001324 if (!(surfaceType & EGL_PBUFFER_BIT))
1325 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001326
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001327 EGLint configID;
1328 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1329 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001330
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001331 int32_t depthFormat;
1332 int32_t pixelFormat;
1333 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
1334 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1335 }
David Liaf94ceb2011-03-01 16:54:04 -08001336
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001337 int32_t w = 0;
1338 int32_t h = 0;
1339 while (attrib_list[0]) {
1340 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
1341 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
1342 attrib_list+=2;
1343 }
David Liaf94ceb2011-03-01 16:54:04 -08001344
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001345 egl_surface_t* surface =
1346 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
David Liaf94ceb2011-03-01 16:54:04 -08001347
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001348 if (!surface->initCheck()) {
1349 // there was a problem in the ctor, the error
1350 // flag has been set.
1351 delete surface;
1352 surface = 0;
1353 }
1354 return surface;
David Liaf94ceb2011-03-01 16:54:04 -08001355}
1356
1357// ----------------------------------------------------------------------------
1358}; // namespace android
1359// ----------------------------------------------------------------------------
1360
1361using namespace android;
1362
1363// ----------------------------------------------------------------------------
1364// Initialization
1365// ----------------------------------------------------------------------------
1366
1367EGLDisplay eglGetDisplay(NativeDisplayType display)
1368{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001369 puts("agl2:eglGetDisplay");
David Liaf94ceb2011-03-01 16:54:04 -08001370#ifndef HAVE_ANDROID_OS
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001371 // this just needs to be done once
1372 if (gGLKey == -1) {
1373 pthread_mutex_lock(&gInitMutex);
1374 if (gGLKey == -1)
1375 pthread_key_create(&gGLKey, NULL);
1376 pthread_mutex_unlock(&gInitMutex);
1377 }
David Liaf94ceb2011-03-01 16:54:04 -08001378#endif
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001379 if (display == EGL_DEFAULT_DISPLAY) {
1380 EGLDisplay dpy = (EGLDisplay)1;
1381 egl_display_t& d = egl_display_t::get_display(dpy);
1382 d.type = display;
1383 return dpy;
1384 }
1385 return EGL_NO_DISPLAY;
David Liaf94ceb2011-03-01 16:54:04 -08001386}
1387
1388EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
1389{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001390 puts("agl2:eglInitialize");
1391 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1392 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001393
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001394 EGLBoolean res = EGL_TRUE;
1395 egl_display_t& d = egl_display_t::get_display(dpy);
David Liaf94ceb2011-03-01 16:54:04 -08001396
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001397 if (android_atomic_inc(&d.initialized) == 0) {
1398 // initialize stuff here if needed
1399 //pthread_mutex_lock(&gInitMutex);
1400 //pthread_mutex_unlock(&gInitMutex);
1401 }
David Liaf94ceb2011-03-01 16:54:04 -08001402
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001403 if (res == EGL_TRUE) {
1404 if (major != NULL) *major = VERSION_MAJOR;
1405 if (minor != NULL) *minor = VERSION_MINOR;
1406 }
1407 return res;
David Liaf94ceb2011-03-01 16:54:04 -08001408}
1409
1410EGLBoolean eglTerminate(EGLDisplay dpy)
1411{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001412 puts("agl2:eglTerminate");
1413 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1414 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001415
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001416 EGLBoolean res = EGL_TRUE;
1417 egl_display_t& d = egl_display_t::get_display(dpy);
1418 if (android_atomic_dec(&d.initialized) == 1) {
1419 // TODO: destroy all resources (surfaces, contexts, etc...)
1420 //pthread_mutex_lock(&gInitMutex);
1421 //pthread_mutex_unlock(&gInitMutex);
1422 }
1423 return res;
David Liaf94ceb2011-03-01 16:54:04 -08001424}
1425
1426// ----------------------------------------------------------------------------
1427// configuration
1428// ----------------------------------------------------------------------------
1429
1430EGLBoolean eglGetConfigs( EGLDisplay dpy,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001431 EGLConfig *configs,
1432 EGLint config_size, EGLint *num_config)
David Liaf94ceb2011-03-01 16:54:04 -08001433{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001434 puts("agl2:eglGetConfigs");
1435 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1436 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001437
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001438 GLint numConfigs = NELEM(gConfigs);
1439 if (!configs) {
1440 *num_config = numConfigs;
1441 return EGL_TRUE;
1442 }
1443 GLint i;
1444 for (i=0 ; i<numConfigs && i<config_size ; i++) {
1445 *configs++ = (EGLConfig)i;
1446 }
1447 *num_config = i;
1448 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001449}
1450
1451static const char * ATTRIBUTE_NAMES [] = {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001452 "EGL_BUFFER_SIZE",
1453 "EGL_ALPHA_SIZE",
1454 "EGL_BLUE_SIZE",
1455 "EGL_GREEN_SIZE",
1456 "EGL_RED_SIZE",
1457 "EGL_DEPTH_SIZE",
1458 "EGL_STENCIL_SIZE",
1459 "EGL_CONFIG_CAVEAT",
1460 "EGL_CONFIG_ID",
1461 "EGL_LEVEL",
1462 "EGL_MAX_PBUFFER_HEIGHT",
1463 "EGL_MAX_PBUFFER_PIXELS",
1464 "EGL_MAX_PBUFFER_WIDTH",
1465 "EGL_NATIVE_RENDERABLE",
1466 "EGL_NATIVE_VISUAL_ID",
1467 "EGL_NATIVE_VISUAL_TYPE",
1468 "EGL_PRESERVED_RESOURCES",
1469 "EGL_SAMPLES",
1470 "EGL_SAMPLE_BUFFERS",
1471 "EGL_SURFACE_TYPE",
1472 "EGL_TRANSPARENT_TYPE",
1473 "EGL_TRANSPARENT_BLUE_VALUE",
1474 "EGL_TRANSPARENT_GREEN_VALUE",
1475 "EGL_TRANSPARENT_RED_VALUE",
1476 "EGL_NONE", /* Attrib list terminator */
1477 "EGL_BIND_TO_TEXTURE_RGB",
1478 "EGL_BIND_TO_TEXTURE_RGBA",
1479 "EGL_MIN_SWAP_INTERVAL",
1480 "EGL_MAX_SWAP_INTERVAL",
1481 "EGL_LUMINANCE_SIZE",
1482 "EGL_ALPHA_MASK_SIZE",
1483 "EGL_COLOR_BUFFER_TYPE",
1484 "EGL_RENDERABLE_TYPE",
1485 "EGL_MATCH_NATIVE_PIXMAP", /* Pseudo-attribute (not queryable) */
1486 "EGL_CONFORMANT",
David Liaf94ceb2011-03-01 16:54:04 -08001487};
1488
1489EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001490 EGLConfig *configs, EGLint config_size,
1491 EGLint *num_config)
David Liaf94ceb2011-03-01 16:54:04 -08001492{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001493 puts("agl2:eglChooseConfig");
1494 LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n");
1495 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1496 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001497
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001498 if (ggl_unlikely(num_config==0)) {
1499 LOGD("\n***\n***\n num_config==0 \n***\n***\n");
1500 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1501 }
David Liaf94ceb2011-03-01 16:54:04 -08001502
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001503 if (ggl_unlikely(attrib_list==0)) {
1504 /*
1505 * A NULL attrib_list should be treated as though it was an empty
1506 * one (terminated with EGL_NONE) as defined in
1507 * section 3.4.1 "Querying Configurations" in the EGL specification.
1508 */
1509 LOGD("\n***\n***\n attrib_list==0 \n***\n***\n");
1510 static const EGLint dummy = EGL_NONE;
1511 attrib_list = &dummy;
1512 }
David Liaf94ceb2011-03-01 16:54:04 -08001513
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001514 for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) {
1515 LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]);
1516 if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0])
1517 LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]);
1518 }
David Liaf94ceb2011-03-01 16:54:04 -08001519
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001520 int numAttributes = 0;
1521 int numConfigs = NELEM(gConfigs);
1522 uint32_t possibleMatch = (1<<numConfigs)-1;
1523 while (possibleMatch && *attrib_list != EGL_NONE) {
1524 numAttributes++;
1525 EGLint attr = *attrib_list++;
1526 EGLint val = *attrib_list++;
1527 for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
David Liaf94ceb2011-03-01 16:54:04 -08001528 if (!(possibleMatch & (1<<i)))
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001529 continue;
1530 if (isAttributeMatching(i, attr, val) == 0) {
1531 LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val);
1532 possibleMatch &= ~(1<<i);
David Liaf94ceb2011-03-01 16:54:04 -08001533 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001534 }
1535 }
David Liaf94ceb2011-03-01 16:54:04 -08001536
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001537 LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch);
1538
1539 // now, handle the attributes which have a useful default value
1540 for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
1541 // see if this attribute was specified, if not, apply its
1542 // default value
1543 if (binarySearch<config_pair_t>(
1544 (config_pair_t const*)attrib_list,
1545 0, numAttributes-1,
1546 config_defaults[j].key) < 0) {
1547 for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
1548 if (!(possibleMatch & (1<<i)))
1549 continue;
1550 if (isAttributeMatching(i,
1551 config_defaults[j].key,
1552 config_defaults[j].value) == 0) {
1553 possibleMatch &= ~(1<<i);
1554 }
David Liaf94ceb2011-03-01 16:54:04 -08001555 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001556 }
1557 }
1558
1559 // return the configurations found
1560 int n=0;
1561 if (possibleMatch) {
1562 if (configs) {
1563 for (int i=0 ; config_size && i<numConfigs ; i++) {
1564 if (possibleMatch & (1<<i)) {
1565 *configs++ = (EGLConfig)i;
1566 config_size--;
1567 n++;
1568 }
David Liaf94ceb2011-03-01 16:54:04 -08001569 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001570 } else {
1571 for (int i=0 ; i<numConfigs ; i++) {
1572 if (possibleMatch & (1<<i)) {
1573 n++;
1574 }
1575 }
1576 }
1577 }
1578 *num_config = n;
1579 LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config);
1580 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001581}
1582
1583EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001584 EGLint attribute, EGLint *value)
David Liaf94ceb2011-03-01 16:54:04 -08001585{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001586 puts("agl2:eglGetConfigAttrib");
1587 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1588 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001589
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001590 return getConfigAttrib(dpy, config, attribute, value);
David Liaf94ceb2011-03-01 16:54:04 -08001591}
1592
1593// ----------------------------------------------------------------------------
1594// surfaces
1595// ----------------------------------------------------------------------------
1596
1597EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001598 NativeWindowType window,
1599 const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001600{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001601 puts("agl2:eglCreateWindowSurface");
1602 return createWindowSurface(dpy, config, window, attrib_list);
David Liaf94ceb2011-03-01 16:54:04 -08001603}
1604
1605EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001606 NativePixmapType pixmap,
1607 const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001608{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001609 puts("agl2:eglCreatePixmapSurface");
1610 return createPixmapSurface(dpy, config, pixmap, attrib_list);
David Liaf94ceb2011-03-01 16:54:04 -08001611}
1612
1613EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001614 const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001615{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001616 puts("agl2:eglCreatePbufferSurface");
1617 return createPbufferSurface(dpy, config, attrib_list);
David Liaf94ceb2011-03-01 16:54:04 -08001618}
1619
1620EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1621{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001622 puts("agl2:eglDestroySurface");
1623 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1624 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1625 if (eglSurface != EGL_NO_SURFACE) {
1626 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1627 if (!surface->isValid())
1628 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1629 if (surface->dpy != dpy)
1630 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1631 if (surface->ctx) {
1632 // FIXME: this surface is current check what the spec says
1633 surface->disconnect();
1634 surface->ctx = 0;
1635 }
1636 delete surface;
1637 }
1638 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001639}
1640
1641EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001642 EGLint attribute, EGLint *value)
David Liaf94ceb2011-03-01 16:54:04 -08001643{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001644 puts("agl2:eglQuerySurface");
1645 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1646 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1647 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
1648 if (!surface->isValid())
1649 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1650 if (surface->dpy != dpy)
1651 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001652
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001653 EGLBoolean ret = EGL_TRUE;
1654 switch (attribute) {
1655 case EGL_CONFIG_ID:
1656 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
1657 break;
1658 case EGL_WIDTH:
1659 *value = surface->getWidth();
1660 break;
1661 case EGL_HEIGHT:
1662 *value = surface->getHeight();
1663 break;
1664 case EGL_LARGEST_PBUFFER:
1665 // not modified for a window or pixmap surface
1666 break;
1667 case EGL_TEXTURE_FORMAT:
1668 *value = EGL_NO_TEXTURE;
1669 break;
1670 case EGL_TEXTURE_TARGET:
1671 *value = EGL_NO_TEXTURE;
1672 break;
1673 case EGL_MIPMAP_TEXTURE:
1674 *value = EGL_FALSE;
1675 break;
1676 case EGL_MIPMAP_LEVEL:
1677 *value = 0;
1678 break;
1679 case EGL_RENDER_BUFFER:
1680 // TODO: return the real RENDER_BUFFER here
1681 *value = EGL_BACK_BUFFER;
1682 break;
1683 case EGL_HORIZONTAL_RESOLUTION:
1684 // pixel/mm * EGL_DISPLAY_SCALING
1685 *value = surface->getHorizontalResolution();
1686 break;
1687 case EGL_VERTICAL_RESOLUTION:
1688 // pixel/mm * EGL_DISPLAY_SCALING
1689 *value = surface->getVerticalResolution();
1690 break;
1691 case EGL_PIXEL_ASPECT_RATIO: {
1692 // w/h * EGL_DISPLAY_SCALING
1693 int wr = surface->getHorizontalResolution();
1694 int hr = surface->getVerticalResolution();
1695 *value = (wr * EGL_DISPLAY_SCALING) / hr;
1696 }
1697 break;
1698 case EGL_SWAP_BEHAVIOR:
1699 *value = surface->getSwapBehavior();
1700 break;
1701 default:
1702 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1703 }
1704 return ret;
David Liaf94ceb2011-03-01 16:54:04 -08001705}
1706
1707EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001708 EGLContext share_list, const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08001709{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001710 puts("agl2:eglCreateContext");
1711 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1712 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001713
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001714 GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t));
1715 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
David Liaf94ceb2011-03-01 16:54:04 -08001716
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001717 //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
1718 egl_context_t * c = &gl->egl;
1719 c->flags = egl_context_t::NEVER_CURRENT;
1720 c->dpy = dpy;
1721 c->config = config;
1722 c->read = 0;
1723 c->draw = 0;
1724
1725 c->frame = 0;
1726 c->lastSwapTime = clock();
1727 c->accumulateSeconds = 0;
1728 return (EGLContext)gl;
David Liaf94ceb2011-03-01 16:54:04 -08001729}
1730
1731EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1732{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001733 puts("agl2:eglDestroyContext");
1734 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1735 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1736 egl_context_t* c = egl_context_t::context(ctx);
1737 if (c->flags & egl_context_t::IS_CURRENT)
1738 setGlThreadSpecific(0);
1739 //ogles_uninit((GLES2Context*)ctx);
1740 delete (GLES2Context*)ctx;
1741 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001742}
1743
1744EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001745 EGLSurface read, EGLContext ctx)
David Liaf94ceb2011-03-01 16:54:04 -08001746{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001747 puts("agl2:eglMakeCurrent");
1748 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1749 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1750 if (draw) {
1751 egl_surface_t* s = (egl_surface_t*)draw;
1752 if (!s->isValid())
1753 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1754 if (s->dpy != dpy)
1755 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1756 // TODO: check that draw is compatible with the context
1757 }
1758 if (read && read!=draw) {
1759 egl_surface_t* s = (egl_surface_t*)read;
1760 if (!s->isValid())
1761 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1762 if (s->dpy != dpy)
1763 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1764 // TODO: check that read is compatible with the context
1765 }
David Liaf94ceb2011-03-01 16:54:04 -08001766
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001767 EGLContext current_ctx = EGL_NO_CONTEXT;
David Liaf94ceb2011-03-01 16:54:04 -08001768
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001769 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1770 return setError(EGL_BAD_MATCH, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001771
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001772 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1773 return setError(EGL_BAD_MATCH, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001774
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001775 if (ctx == EGL_NO_CONTEXT) {
1776 // if we're detaching, we need the current context
1777 current_ctx = (EGLContext)getGlThreadSpecific();
1778 } else {
1779 egl_context_t* c = egl_context_t::context(ctx);
1780 egl_surface_t* d = (egl_surface_t*)draw;
1781 egl_surface_t* r = (egl_surface_t*)read;
1782 if ((d && d->ctx && d->ctx != ctx) ||
1783 (r && r->ctx && r->ctx != ctx)) {
1784 // one of the surface is bound to a context in another thread
1785 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1786 }
1787 }
David Liaf94ceb2011-03-01 16:54:04 -08001788
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001789 GLES2Context* gl = (GLES2Context*)ctx;
1790 if (makeCurrent(gl) == 0) {
1791 if (ctx) {
1792 egl_context_t* c = egl_context_t::context(ctx);
1793 egl_surface_t* d = (egl_surface_t*)draw;
1794 egl_surface_t* r = (egl_surface_t*)read;
David Liaf94ceb2011-03-01 16:54:04 -08001795
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001796 if (c->draw) {
1797 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
1798 s->disconnect();
David Liaf94ceb2011-03-01 16:54:04 -08001799 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001800 if (c->read) {
1801 // FIXME: unlock/disconnect the read surface too
David Liaf94ceb2011-03-01 16:54:04 -08001802 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001803
1804 c->draw = draw;
1805 c->read = read;
1806
1807 if (c->flags & egl_context_t::NEVER_CURRENT) {
1808 c->flags &= ~egl_context_t::NEVER_CURRENT;
1809 GLint w = 0;
1810 GLint h = 0;
1811 if (draw) {
1812 w = d->getWidth();
1813 h = d->getHeight();
1814 }
1815 gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h);
1816 //ogles_surfaceport(gl, 0, 0);
1817 //ogles_viewport(gl, 0, 0, w, h);
1818 //ogles_scissor(gl, 0, 0, w, h);
1819 }
David Liaf94ceb2011-03-01 16:54:04 -08001820 if (d) {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001821 if (d->connect() == EGL_FALSE) {
1822 return EGL_FALSE;
1823 }
1824 d->ctx = ctx;
1825 d->bindDrawSurface(gl);
David Liaf94ceb2011-03-01 16:54:04 -08001826 }
1827 if (r) {
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001828 // FIXME: lock/connect the read surface too
1829 r->ctx = ctx;
1830 r->bindReadSurface(gl);
David Liaf94ceb2011-03-01 16:54:04 -08001831 }
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001832 } else {
1833 // if surfaces were bound to the context bound to this thread
1834 // mark then as unbound.
1835 if (current_ctx) {
1836 egl_context_t* c = egl_context_t::context(current_ctx);
1837 egl_surface_t* d = (egl_surface_t*)c->draw;
1838 egl_surface_t* r = (egl_surface_t*)c->read;
1839 if (d) {
1840 c->draw = 0;
1841 d->ctx = EGL_NO_CONTEXT;
1842 d->disconnect();
1843 }
1844 if (r) {
1845 c->read = 0;
1846 r->ctx = EGL_NO_CONTEXT;
1847 // FIXME: unlock/disconnect the read surface too
1848 }
1849 }
1850 }
1851 return EGL_TRUE;
1852 }
1853 return setError(EGL_BAD_ACCESS, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001854}
1855
1856EGLContext eglGetCurrentContext(void)
1857{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001858 // eglGetCurrentContext returns the current EGL rendering context,
1859 // as specified by eglMakeCurrent. If no context is current,
1860 // EGL_NO_CONTEXT is returned.
1861 return (EGLContext)getGlThreadSpecific();
David Liaf94ceb2011-03-01 16:54:04 -08001862}
1863
1864EGLSurface eglGetCurrentSurface(EGLint readdraw)
1865{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001866 // eglGetCurrentSurface returns the read or draw surface attached
1867 // to the current EGL rendering context, as specified by eglMakeCurrent.
1868 // If no context is current, EGL_NO_SURFACE is returned.
1869 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1870 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
1871 egl_context_t* c = egl_context_t::context(ctx);
1872 if (readdraw == EGL_READ) {
1873 return c->read;
1874 } else if (readdraw == EGL_DRAW) {
1875 return c->draw;
1876 }
1877 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08001878}
1879
1880EGLDisplay eglGetCurrentDisplay(void)
1881{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001882 // eglGetCurrentDisplay returns the current EGL display connection
1883 // for the current EGL rendering context, as specified by eglMakeCurrent.
1884 // If no context is current, EGL_NO_DISPLAY is returned.
1885 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1886 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
1887 egl_context_t* c = egl_context_t::context(ctx);
1888 return c->dpy;
David Liaf94ceb2011-03-01 16:54:04 -08001889}
1890
1891EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001892 EGLint attribute, EGLint *value)
David Liaf94ceb2011-03-01 16:54:04 -08001893{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001894 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1895 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1896 egl_context_t* c = egl_context_t::context(ctx);
1897 switch (attribute) {
1898 case EGL_CONFIG_ID:
1899 // Returns the ID of the EGL frame buffer configuration with
1900 // respect to which the context was created
1901 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
1902 }
1903 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001904}
1905
1906EGLBoolean eglWaitGL(void)
1907{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001908 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001909}
1910
1911EGLBoolean eglWaitNative(EGLint engine)
1912{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001913 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001914}
1915
1916EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1917{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001918 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1919 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001920
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001921 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
1922 if (!d->isValid())
1923 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1924 if (d->dpy != dpy)
1925 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08001926
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001927 // post the surface
1928 d->swapBuffers();
David Liaf94ceb2011-03-01 16:54:04 -08001929
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001930 // if it's bound to a context, update the buffer
1931 if (d->ctx != EGL_NO_CONTEXT) {
1932 d->bindDrawSurface((GLES2Context*)d->ctx);
1933 // if this surface is also the read surface of the context
1934 // it is bound to, make sure to update the read buffer as well.
1935 // The EGL spec is a little unclear about this.
1936 egl_context_t* c = egl_context_t::context(d->ctx);
1937 if (c->read == draw) {
1938 d->bindReadSurface((GLES2Context*)d->ctx);
1939 }
1940 clock_t time = clock();
1941 float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC;
1942 c->accumulateSeconds += elapsed;
1943 c->frame++;
1944 // LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000);
1945 if (20 == c->frame) {
1946 float avg = c->accumulateSeconds / c->frame;
1947 LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*",
1948 c->frame, 1 / avg, avg * 1000);
1949 c->frame = 0;
1950 c->accumulateSeconds = 0;
1951 }
1952 c->lastSwapTime = time;
1953 }
David Liaf94ceb2011-03-01 16:54:04 -08001954
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001955 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08001956}
1957
1958EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001959 NativePixmapType target)
David Liaf94ceb2011-03-01 16:54:04 -08001960{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001961 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1962 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1963 // TODO: eglCopyBuffers()
1964 return EGL_FALSE;
David Liaf94ceb2011-03-01 16:54:04 -08001965}
1966
1967EGLint eglGetError(void)
1968{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001969 return getError();
David Liaf94ceb2011-03-01 16:54:04 -08001970}
1971
1972const char* eglQueryString(EGLDisplay dpy, EGLint name)
1973{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001974 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1975 return setError(EGL_BAD_DISPLAY, (const char*)0);
David Liaf94ceb2011-03-01 16:54:04 -08001976
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001977 switch (name) {
1978 case EGL_VENDOR:
1979 return gVendorString;
1980 case EGL_VERSION:
1981 return gVersionString;
1982 case EGL_EXTENSIONS:
1983 return gExtensionsString;
1984 case EGL_CLIENT_APIS:
1985 return gClientApiString;
1986 }
1987 return setError(EGL_BAD_PARAMETER, (const char *)0);
David Liaf94ceb2011-03-01 16:54:04 -08001988}
1989
1990// ----------------------------------------------------------------------------
1991// EGL 1.1
1992// ----------------------------------------------------------------------------
1993
1994EGLBoolean eglSurfaceAttrib(
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001995 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
David Liaf94ceb2011-03-01 16:54:04 -08001996{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07001997 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1998 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1999 // TODO: eglSurfaceAttrib()
2000 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002001}
2002
2003EGLBoolean eglBindTexImage(
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002004 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
David Liaf94ceb2011-03-01 16:54:04 -08002005{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002006 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2007 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2008 // TODO: eglBindTexImage()
2009 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002010}
2011
2012EGLBoolean eglReleaseTexImage(
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002013 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
David Liaf94ceb2011-03-01 16:54:04 -08002014{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002015 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2016 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2017 // TODO: eglReleaseTexImage()
2018 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002019}
2020
2021EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
2022{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002023 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2024 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2025 // TODO: eglSwapInterval()
2026 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08002027}
2028
2029// ----------------------------------------------------------------------------
2030// EGL 1.2
2031// ----------------------------------------------------------------------------
2032
2033EGLBoolean eglBindAPI(EGLenum api)
2034{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002035 if (api != EGL_OPENGL_ES_API)
2036 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2037 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08002038}
2039
2040EGLenum eglQueryAPI(void)
2041{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002042 return EGL_OPENGL_ES_API;
David Liaf94ceb2011-03-01 16:54:04 -08002043}
2044
2045EGLBoolean eglWaitClient(void)
2046{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002047 glFinish();
2048 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08002049}
2050
2051EGLBoolean eglReleaseThread(void)
2052{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002053 // TODO: eglReleaseThread()
2054 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08002055}
2056
2057EGLSurface eglCreatePbufferFromClientBuffer(
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002058 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
2059 EGLConfig config, const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08002060{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002061 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2062 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
2063 // TODO: eglCreatePbufferFromClientBuffer()
2064 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
David Liaf94ceb2011-03-01 16:54:04 -08002065}
2066
2067// ----------------------------------------------------------------------------
2068// EGL_EGLEXT_VERSION 3
2069// ----------------------------------------------------------------------------
2070
2071void (*eglGetProcAddress (const char *procname))()
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002072 {
2073 extention_map_t const * const map = gExtentionMap;
2074 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
2075 if (!strcmp(procname, map[i].name)) {
2076 return map[i].address;
2077 }
2078 }
2079 return NULL;
2080 }
David Liaf94ceb2011-03-01 16:54:04 -08002081
2082EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002083 const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08002084{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002085 EGLBoolean result = EGL_FALSE;
2086 return result;
David Liaf94ceb2011-03-01 16:54:04 -08002087}
2088
2089EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
2090{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002091 EGLBoolean result = EGL_FALSE;
2092 return result;
David Liaf94ceb2011-03-01 16:54:04 -08002093}
2094
2095EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002096 EGLClientBuffer buffer, const EGLint *attrib_list)
David Liaf94ceb2011-03-01 16:54:04 -08002097{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002098 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2099 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
2100 }
2101 if (ctx != EGL_NO_CONTEXT) {
2102 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
2103 }
2104 if (target != EGL_NATIVE_BUFFER_ANDROID) {
2105 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2106 }
David Liaf94ceb2011-03-01 16:54:04 -08002107
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07002108 ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;
David Liaf94ceb2011-03-01 16:54:04 -08002109
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002110 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2111 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
David Liaf94ceb2011-03-01 16:54:04 -08002112
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07002113 if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002114 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
David Liaf94ceb2011-03-01 16:54:04 -08002115
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002116 switch (native_buffer->format) {
2117 case HAL_PIXEL_FORMAT_RGBA_8888:
2118 case HAL_PIXEL_FORMAT_RGBX_8888:
2119 case HAL_PIXEL_FORMAT_RGB_888:
2120 case HAL_PIXEL_FORMAT_RGB_565:
2121 case HAL_PIXEL_FORMAT_BGRA_8888:
2122 case HAL_PIXEL_FORMAT_RGBA_5551:
2123 case HAL_PIXEL_FORMAT_RGBA_4444:
2124 break;
2125 default:
2126 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2127 }
David Liaf94ceb2011-03-01 16:54:04 -08002128
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002129 native_buffer->common.incRef(&native_buffer->common);
2130 return (EGLImageKHR)native_buffer;
David Liaf94ceb2011-03-01 16:54:04 -08002131}
2132
2133EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2134{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002135 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2136 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2137 }
David Liaf94ceb2011-03-01 16:54:04 -08002138
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07002139 ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img;
David Liaf94ceb2011-03-01 16:54:04 -08002140
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002141 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2142 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002143
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07002144 if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002145 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002146
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002147 native_buffer->common.decRef(&native_buffer->common);
David Liaf94ceb2011-03-01 16:54:04 -08002148
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002149 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08002150}
2151
2152// ----------------------------------------------------------------------------
2153// ANDROID extensions
2154// ----------------------------------------------------------------------------
2155
2156EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002157 EGLint left, EGLint top, EGLint width, EGLint height)
David Liaf94ceb2011-03-01 16:54:04 -08002158{
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002159 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2160 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002161
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002162 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
2163 if (!d->isValid())
2164 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2165 if (d->dpy != dpy)
2166 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
David Liaf94ceb2011-03-01 16:54:04 -08002167
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002168 // post the surface
2169 d->setSwapRectangle(left, top, width, height);
David Liaf94ceb2011-03-01 16:54:04 -08002170
Mathias Agopian8e86a7a2011-04-28 19:50:21 -07002171 return EGL_TRUE;
David Liaf94ceb2011-03-01 16:54:04 -08002172}