blob: b0e54d8f2730dfaa8e858d7b0af545f87a2887e9 [file] [log] [blame]
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08002**
3** Copyright 2007 The Android Open Source Project
4**
Mathias Agopian076b1cc2009-04-10 14:24:30 -07005** Licensed under the Apache License Version 2.0(the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08008**
Mathias Agopian076b1cc2009-04-10 14:24:30 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080010**
Mathias Agopian076b1cc2009-04-10 14:24:30 -070011** Unless required by applicable law or agreed to in writing software
12** distributed under the License is distributed on an "AS IS" BASIS
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080018#include <assert.h>
19#include <errno.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <sys/ioctl.h>
26#include <sys/types.h>
27#include <sys/mman.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31
32#include <utils/threads.h>
33
34#include <EGL/egl.h>
35#include <EGL/eglext.h>
36#include <GLES/gl.h>
37#include <GLES/glext.h>
38
39#include <pixelflinger/format.h>
40#include <pixelflinger/pixelflinger.h>
41
Mathias Agopian58a79f42009-05-05 18:21:32 -070042#include <private/ui/android_natives_priv.h>
Mathias Agopian7189c002009-05-05 18:11:11 -070043
Mathias Agopian240c9fe2009-06-25 15:39:25 -070044#include <hardware/copybit.h>
45
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080046#include "context.h"
47#include "state.h"
48#include "texture.h"
49#include "matrix.h"
50
51#undef NELEM
52#define NELEM(x) (sizeof(x)/sizeof(*(x)))
53
54// ----------------------------------------------------------------------------
55namespace android {
56// ----------------------------------------------------------------------------
57
58const unsigned int NUM_DISPLAYS = 1;
59
60static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
61static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
62static pthread_key_t gEGLErrorKey = -1;
63#ifndef HAVE_ANDROID_OS
64namespace gl {
65pthread_key_t gGLKey = -1;
66}; // namespace gl
67#endif
68
69template<typename T>
70static T setError(GLint error, T returnValue) {
71 if (ggl_unlikely(gEGLErrorKey == -1)) {
72 pthread_mutex_lock(&gErrorKeyMutex);
73 if (gEGLErrorKey == -1)
74 pthread_key_create(&gEGLErrorKey, NULL);
75 pthread_mutex_unlock(&gErrorKeyMutex);
76 }
77 pthread_setspecific(gEGLErrorKey, (void*)error);
78 return returnValue;
79}
80
81static GLint getError() {
82 if (ggl_unlikely(gEGLErrorKey == -1))
83 return EGL_SUCCESS;
84 GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
85 pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
86 return error;
87}
88
89// ----------------------------------------------------------------------------
90
91struct egl_display_t
92{
93 egl_display_t() : type(0), initialized(0) { }
Mathias Agopian076b1cc2009-04-10 14:24:30 -070094
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080095 static egl_display_t& get_display(EGLDisplay dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -070096
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080097 static EGLBoolean is_valid(EGLDisplay dpy) {
98 return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
99 }
100
101 NativeDisplayType type;
102 volatile int32_t initialized;
103};
104
105static egl_display_t gDisplays[NUM_DISPLAYS];
106
107egl_display_t& egl_display_t::get_display(EGLDisplay dpy) {
108 return gDisplays[uintptr_t(dpy)-1U];
109}
110
111struct egl_context_t {
112 enum {
113 IS_CURRENT = 0x00010000,
114 NEVER_CURRENT = 0x00020000
115 };
116 uint32_t flags;
117 EGLDisplay dpy;
118 EGLConfig config;
119 EGLSurface read;
120 EGLSurface draw;
121
122 static inline egl_context_t* context(EGLContext ctx) {
123 ogles_context_t* const gl = static_cast<ogles_context_t*>(ctx);
124 return static_cast<egl_context_t*>(gl->rasterizer.base);
125 }
126};
127
128// ----------------------------------------------------------------------------
129
130struct egl_surface_t
131{
132 enum {
133 PAGE_FLIP = 0x00000001,
134 MAGIC = 0x31415265
135 };
136
137 uint32_t magic;
138 EGLDisplay dpy;
139 EGLConfig config;
140 EGLContext ctx;
141
142 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
143 virtual ~egl_surface_t();
144 virtual bool isValid() const = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700145
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800146 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0;
147 virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700148 virtual void connect() {}
149 virtual void disconnect() {}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800150 virtual EGLint getWidth() const = 0;
151 virtual EGLint getHeight() const = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800152
153 virtual EGLint getHorizontalResolution() const;
154 virtual EGLint getVerticalResolution() const;
155 virtual EGLint getRefreshRate() const;
156 virtual EGLint getSwapBehavior() const;
157 virtual EGLBoolean swapBuffers();
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700158 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700159 virtual EGLClientBuffer getRenderBuffer() const;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800160protected:
161 GGLSurface depth;
162};
163
164egl_surface_t::egl_surface_t(EGLDisplay dpy,
165 EGLConfig config,
166 int32_t depthFormat)
167 : magic(MAGIC), dpy(dpy), config(config), ctx(0)
168{
169 depth.version = sizeof(GGLSurface);
170 depth.data = 0;
171 depth.format = depthFormat;
172}
173egl_surface_t::~egl_surface_t()
174{
175 magic = 0;
176 free(depth.data);
177}
178EGLBoolean egl_surface_t::swapBuffers() {
179 return EGL_FALSE;
180}
181EGLint egl_surface_t::getHorizontalResolution() const {
182 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
183}
184EGLint egl_surface_t::getVerticalResolution() const {
185 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
186}
187EGLint egl_surface_t::getRefreshRate() const {
188 return (60 * EGL_DISPLAY_SCALING);
189}
190EGLint egl_surface_t::getSwapBehavior() const {
191 return EGL_BUFFER_PRESERVED;
192}
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700193EGLBoolean egl_surface_t::setSwapRectangle(
194 EGLint l, EGLint t, EGLint w, EGLint h)
195{
196 return EGL_FALSE;
197}
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700198EGLClientBuffer egl_surface_t::getRenderBuffer() const {
199 return 0;
200}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201
202// ----------------------------------------------------------------------------
203
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700204struct egl_window_surface_v2_t : public egl_surface_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700206 egl_window_surface_v2_t(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800207 EGLDisplay dpy, EGLConfig config,
208 int32_t depthFormat,
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700209 android_native_window_t* window);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700211 ~egl_window_surface_v2_t();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800212
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700213 virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800214 virtual EGLBoolean swapBuffers();
215 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
216 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
Mathias Agopiane71212b2009-05-05 00:37:46 -0700217 virtual void connect();
218 virtual void disconnect();
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700219 virtual EGLint getWidth() const { return width; }
220 virtual EGLint getHeight() const { return height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800221 virtual EGLint getHorizontalResolution() const;
222 virtual EGLint getVerticalResolution() const;
223 virtual EGLint getRefreshRate() const;
224 virtual EGLint getSwapBehavior() const;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700225 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700226 virtual EGLClientBuffer getRenderBuffer() const;
227
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800228private:
Mathias Agopiane71212b2009-05-05 00:37:46 -0700229 status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -0700230 status_t unlock(android_native_buffer_t* buf);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700231 android_native_window_t* nativeWindow;
232 android_native_buffer_t* buffer;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700233 android_native_buffer_t* previousBuffer;
Mathias Agopian0926f502009-05-04 14:17:04 -0700234 gralloc_module_t const* module;
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700235 copybit_device_t* blitengine;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700236 int width;
237 int height;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700238 void* bits;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700239 GGLFormat const* pixelFormatTable;
240
241 struct Rect {
242 inline Rect() { };
243 inline Rect(int32_t w, int32_t h)
244 : left(0), top(0), right(w), bottom(h) { }
245 inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
246 : left(l), top(t), right(r), bottom(b) { }
247 Rect& andSelf(const Rect& r) {
248 left = max(left, r.left);
249 top = max(top, r.top);
250 right = min(right, r.right);
251 bottom = min(bottom, r.bottom);
252 return *this;
253 }
254 bool isEmpty() const {
255 return (left>=right || top>=bottom);
256 }
257 void dump(char const* what) {
258 LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
259 what, left, top, right-left, bottom-top);
260 }
261
262 int32_t left;
263 int32_t top;
264 int32_t right;
265 int32_t bottom;
266 };
267
268 struct Region {
269 inline Region() : count(0) { }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700270 typedef Rect const* const_iterator;
271 const_iterator begin() const { return storage; }
272 const_iterator end() const { return storage+count; }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700273 static Region subtract(const Rect& lhs, const Rect& rhs) {
274 Region reg;
275 Rect* storage = reg.storage;
276 if (!lhs.isEmpty()) {
277 if (lhs.top < rhs.top) { // top rect
278 storage->left = lhs.left;
279 storage->top = lhs.top;
280 storage->right = lhs.right;
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700281 storage->bottom = rhs.top;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700282 storage++;
283 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700284 const int32_t top = max(lhs.top, rhs.top);
285 const int32_t bot = min(lhs.bottom, rhs.bottom);
286 if (top < bot) {
287 if (lhs.left < rhs.left) { // left-side rect
288 storage->left = lhs.left;
289 storage->top = top;
290 storage->right = rhs.left;
291 storage->bottom = bot;
292 storage++;
293 }
294 if (lhs.right > rhs.right) { // right-side rect
295 storage->left = rhs.right;
296 storage->top = top;
297 storage->right = lhs.right;
298 storage->bottom = bot;
299 storage++;
300 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700301 }
302 if (lhs.bottom > rhs.bottom) { // bottom rect
303 storage->left = lhs.left;
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700304 storage->top = rhs.bottom;
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700305 storage->right = lhs.right;
306 storage->bottom = lhs.bottom;
307 storage++;
308 }
309 reg.count = storage - reg.storage;
310 }
311 return reg;
312 }
313 bool isEmpty() const {
314 return count<=0;
315 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700316 private:
317 Rect storage[4];
318 ssize_t count;
319 };
320
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700321 struct region_iterator : public copybit_region_t {
322 region_iterator(const Region& region)
323 : b(region.begin()), e(region.end()) {
324 this->next = iterate;
325 }
326 private:
327 static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
328 region_iterator const* me = static_cast<region_iterator const*>(self);
329 if (me->b != me->e) {
330 *reinterpret_cast<Rect*>(rect) = *me->b++;
331 return 1;
332 }
333 return 0;
334 }
335 mutable Region::const_iterator b;
336 Region::const_iterator const e;
337 };
338
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700339 void copyBlt(
340 android_native_buffer_t* dst, void* dst_vaddr,
341 android_native_buffer_t* src, void const* src_vaddr,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700342 const Region& clip);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700343
344 Rect dirtyRegion;
345 Rect oldDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800346};
347
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700348egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800349 EGLConfig config,
350 int32_t depthFormat,
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700351 android_native_window_t* window)
Mathias Agopian0926f502009-05-04 14:17:04 -0700352 : egl_surface_t(dpy, config, depthFormat),
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700353 nativeWindow(window), buffer(0), previousBuffer(0), module(0),
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700354 blitengine(0), bits(NULL)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800355{
Mathias Agopian0926f502009-05-04 14:17:04 -0700356 hw_module_t const* pModule;
357 hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
358 module = reinterpret_cast<gralloc_module_t const*>(pModule);
359
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700360 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) {
361 copybit_open(pModule, &blitengine);
362 }
363
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700364 pixelFormatTable = gglGetPixelFormatTable();
365
366 // keep a reference on the window
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700367 nativeWindow->common.incRef(&nativeWindow->common);
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700368 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
369 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
Mathias Agopiane71212b2009-05-05 00:37:46 -0700370}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700371
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700372egl_window_surface_v2_t::~egl_window_surface_v2_t() {
373 if (buffer) {
374 buffer->common.decRef(&buffer->common);
375 }
376 if (previousBuffer) {
377 previousBuffer->common.decRef(&previousBuffer->common);
378 }
379 nativeWindow->common.decRef(&nativeWindow->common);
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700380 if (blitengine) {
381 copybit_close(blitengine);
382 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700383}
384
Mathias Agopiane71212b2009-05-05 00:37:46 -0700385void egl_window_surface_v2_t::connect()
386{
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700387 // dequeue a buffer
388 nativeWindow->dequeueBuffer(nativeWindow, &buffer);
389
390 // allocate a corresponding depth-buffer
391 width = buffer->width;
392 height = buffer->height;
393 if (depth.format) {
394 depth.width = width;
395 depth.height = height;
396 depth.stride = depth.width; // use the width here
397 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
398 if (depth.data == 0) {
399 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
400 return;
401 }
402 }
403
404 // keep a reference on the buffer
405 buffer->common.incRef(&buffer->common);
406
Mathias Agopian0926f502009-05-04 14:17:04 -0700407 // Lock the buffer
Mathias Agopiane71212b2009-05-05 00:37:46 -0700408 nativeWindow->lockBuffer(nativeWindow, buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700409 // pin the buffer down
410 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
411 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700412 LOGE("connect() failed to lock buffer %p (%ux%u)",
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700413 buffer, buffer->width, buffer->height);
414 setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
415 // FIXME: we should make sure we're not accessing the buffer anymore
416 }
Mathias Agopiane71212b2009-05-05 00:37:46 -0700417}
418
419void egl_window_surface_v2_t::disconnect()
420{
Mathias Agopian9648c1a2009-06-03 19:00:53 -0700421 if (buffer && bits) {
Mathias Agopiane71212b2009-05-05 00:37:46 -0700422 bits = NULL;
423 unlock(buffer);
424 }
Mathias Agopiancb6b9042009-07-30 18:14:56 -0700425 // enqueue the last frame
426 nativeWindow->queueBuffer(nativeWindow, buffer);
427 if (buffer) {
428 buffer->common.decRef(&buffer->common);
429 buffer = 0;
430 }
431 if (previousBuffer) {
432 previousBuffer->common.decRef(&previousBuffer->common);
433 previousBuffer = 0;
434 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800435}
436
Mathias Agopian0926f502009-05-04 14:17:04 -0700437status_t egl_window_surface_v2_t::lock(
Mathias Agopiane71212b2009-05-05 00:37:46 -0700438 android_native_buffer_t* buf, int usage, void** vaddr)
Mathias Agopian0926f502009-05-04 14:17:04 -0700439{
Mathias Agopian21c59d02009-05-05 00:59:23 -0700440 int err = module->lock(module, buf->handle,
Mathias Agopiane71212b2009-05-05 00:37:46 -0700441 usage, 0, 0, buf->width, buf->height, vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -0700442 return err;
443}
444
445status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
446{
Mathias Agopian21c59d02009-05-05 00:59:23 -0700447 int err = module->unlock(module, buf->handle);
Mathias Agopian0926f502009-05-04 14:17:04 -0700448 return err;
449}
450
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700451void egl_window_surface_v2_t::copyBlt(
452 android_native_buffer_t* dst, void* dst_vaddr,
453 android_native_buffer_t* src, void const* src_vaddr,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700454 const Region& clip)
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700455{
456 // FIXME: use copybit if possible
457 // NOTE: dst and src must be the same format
458
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700459 status_t err = NO_ERROR;
460 copybit_device_t* const copybit = blitengine;
461 if (copybit) {
462 copybit_image_t simg;
463 simg.w = src->width;
464 simg.h = src->height;
465 simg.format = src->format;
466 simg.handle = const_cast<native_handle_t*>(src->handle);
Mathias Agopian0926f502009-05-04 14:17:04 -0700467
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700468 copybit_image_t dimg;
469 dimg.w = dst->width;
470 dimg.h = dst->height;
471 dimg.format = dst->format;
472 dimg.handle = const_cast<native_handle_t*>(dst->handle);
473
474 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
475 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
476 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
477 region_iterator it(clip);
478 err = copybit->blit(copybit, &dimg, &simg, &it);
479 if (err != NO_ERROR) {
480 LOGE("copybit failed (%s)", strerror(err));
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700481 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700482 }
483
484 if (!copybit || err) {
485 Region::const_iterator cur = clip.begin();
486 Region::const_iterator end = clip.end();
487
488 const size_t bpp = pixelFormatTable[src->format].size;
489 const size_t dbpr = dst->stride * bpp;
490 const size_t sbpr = src->stride * bpp;
491
492 uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
493 uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
494
495 while (cur != end) {
496 const Rect& r(*cur++);
497 ssize_t w = r.right - r.left;
498 ssize_t h = r.bottom - r.top;
499 if (w <= 0 || h<=0) continue;
500 size_t size = w * bpp;
501 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
502 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
503 if (dbpr==sbpr && size==sbpr) {
504 size *= h;
505 h = 1;
506 }
507 do {
508 memcpy(d, s, size);
509 d += dbpr;
510 s += sbpr;
511 } while (--h > 0);
512 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700513 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700514}
515
516EGLBoolean egl_window_surface_v2_t::swapBuffers()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800517{
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700518 /*
519 * Handle eglSetSwapRectangleANDROID()
520 * We copyback from the front buffer
521 */
522 if (!dirtyRegion.isEmpty()) {
523 dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
524 if (previousBuffer) {
525 const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
526 if (!copyBack.isEmpty()) {
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700527 void* prevBits;
528 if (lock(previousBuffer,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700529 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
530 // copy from previousBuffer to buffer
531 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700532 unlock(previousBuffer);
533 }
534 }
535 }
536 oldDirtyRegion = dirtyRegion;
537 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700538
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700539 if (previousBuffer) {
540 previousBuffer->common.decRef(&previousBuffer->common);
541 previousBuffer = 0;
542 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700543
Mathias Agopian0926f502009-05-04 14:17:04 -0700544 unlock(buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700545 previousBuffer = buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700546 nativeWindow->queueBuffer(nativeWindow, buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700547 buffer = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700548
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700549 // dequeue a new buffer
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700550 nativeWindow->dequeueBuffer(nativeWindow, &buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700551
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700552 // TODO: lockBuffer should rather be executed when the very first
553 // direct rendering occurs.
554 nativeWindow->lockBuffer(nativeWindow, buffer);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700555
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700556 // reallocate the depth-buffer if needed
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700557 if ((width != buffer->width) || (height != buffer->height)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800558 // TODO: we probably should reset the swap rect here
559 // if the window size has changed
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700560 width = buffer->width;
561 height = buffer->height;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800562 if (depth.data) {
563 free(depth.data);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700564 depth.width = width;
565 depth.height = height;
566 depth.stride = buffer->stride;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800567 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
568 if (depth.data == 0) {
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700569 setError(EGL_BAD_ALLOC, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800570 return EGL_FALSE;
571 }
572 }
573 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700574
575 // keep a reference on the buffer
576 buffer->common.incRef(&buffer->common);
577
578 // finally pin the buffer down
579 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
580 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
581 LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
582 buffer, buffer->width, buffer->height);
583 setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
584 // FIXME: we should make sure we're not accessing the buffer anymore
585 }
586
587 return EGL_TRUE;
588}
589
590EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
591 EGLint l, EGLint t, EGLint w, EGLint h)
592{
593 dirtyRegion = Rect(l, t, l+w, t+h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800594 return EGL_TRUE;
595}
596
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700597EGLClientBuffer egl_window_surface_v2_t::getRenderBuffer() const
598{
599 return buffer;
600}
601
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700602#ifdef LIBAGL_USE_GRALLOC_COPYBITS
603
604static bool supportedCopybitsDestinationFormat(int format) {
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700605 // Hardware supported
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700606 switch (format) {
607 case HAL_PIXEL_FORMAT_RGB_565:
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700608 case HAL_PIXEL_FORMAT_RGBA_8888:
609 case HAL_PIXEL_FORMAT_RGBA_4444:
610 case HAL_PIXEL_FORMAT_RGBA_5551:
611 case HAL_PIXEL_FORMAT_BGRA_8888:
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700612 return true;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700613 }
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700614 return false;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700615}
616#endif
617
618EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800619{
620 GGLSurface buffer;
621 buffer.version = sizeof(GGLSurface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700622 buffer.width = this->buffer->width;
623 buffer.height = this->buffer->height;
624 buffer.stride = this->buffer->stride;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700625 buffer.data = (GGLubyte*)bits;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700626 buffer.format = this->buffer->format;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800627 gl->rasterizer.procs.colorBuffer(gl, &buffer);
628 if (depth.data != gl->rasterizer.state.buffers.depth.data)
629 gl->rasterizer.procs.depthBuffer(gl, &depth);
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700630
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700631#ifdef LIBAGL_USE_GRALLOC_COPYBITS
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700632 gl->copybits.drawSurfaceBuffer = 0;
Mathias Agopianf13901e2009-07-15 18:53:32 -0700633 if (gl->copybits.blitEngine != NULL) {
634 if (supportedCopybitsDestinationFormat(buffer.format)) {
635 buffer_handle_t handle = this->buffer->handle;
636 if (handle != NULL) {
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700637 gl->copybits.drawSurfaceBuffer = handle;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700638 }
639 }
640 }
641#endif // LIBAGL_USE_GRALLOC_COPYBITS
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700642
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800643 return EGL_TRUE;
644}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700645EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800646{
647 GGLSurface buffer;
648 buffer.version = sizeof(GGLSurface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700649 buffer.width = this->buffer->width;
650 buffer.height = this->buffer->height;
651 buffer.stride = this->buffer->stride;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700652 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700653 buffer.format = this->buffer->format;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800654 gl->rasterizer.procs.readBuffer(gl, &buffer);
655 return EGL_TRUE;
656}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700657EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800658 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
659}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700660EGLint egl_window_surface_v2_t::getVerticalResolution() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800661 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
662}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700663EGLint egl_window_surface_v2_t::getRefreshRate() const {
664 return (60 * EGL_DISPLAY_SCALING); // FIXME
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665}
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700666EGLint egl_window_surface_v2_t::getSwapBehavior() const
667{
668 /*
669 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
670 * the content of the swapped buffer.
671 *
672 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
673 *
674 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
675 * only applies to the area specified by eglSetSwapRectangleANDROID(), that
676 * is, everything outside of this area is preserved.
677 *
678 * This implementation of EGL assumes the later case.
679 *
680 */
681
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700682 return EGL_BUFFER_DESTROYED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800683}
684
685// ----------------------------------------------------------------------------
686
687struct egl_pixmap_surface_t : public egl_surface_t
688{
689 egl_pixmap_surface_t(
690 EGLDisplay dpy, EGLConfig config,
691 int32_t depthFormat,
692 egl_native_pixmap_t const * pixmap);
693
694 virtual ~egl_pixmap_surface_t() { }
695
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700696 virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800697 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
698 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
699 virtual EGLint getWidth() const { return nativePixmap.width; }
700 virtual EGLint getHeight() const { return nativePixmap.height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800701private:
702 egl_native_pixmap_t nativePixmap;
703};
704
705egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
706 EGLConfig config,
707 int32_t depthFormat,
708 egl_native_pixmap_t const * pixmap)
709 : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
710{
711 if (depthFormat) {
712 depth.width = pixmap->width;
713 depth.height = pixmap->height;
714 depth.stride = depth.width; // use the width here
715 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
716 if (depth.data == 0) {
717 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
718 return;
719 }
720 }
721}
722EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl)
723{
724 GGLSurface buffer;
725 buffer.version = sizeof(GGLSurface);
726 buffer.width = nativePixmap.width;
727 buffer.height = nativePixmap.height;
728 buffer.stride = nativePixmap.stride;
729 buffer.data = nativePixmap.data;
730 buffer.format = nativePixmap.format;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700731
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800732 gl->rasterizer.procs.colorBuffer(gl, &buffer);
733 if (depth.data != gl->rasterizer.state.buffers.depth.data)
734 gl->rasterizer.procs.depthBuffer(gl, &depth);
735 return EGL_TRUE;
736}
737EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl)
738{
739 GGLSurface buffer;
740 buffer.version = sizeof(GGLSurface);
741 buffer.width = nativePixmap.width;
742 buffer.height = nativePixmap.height;
743 buffer.stride = nativePixmap.stride;
744 buffer.data = nativePixmap.data;
745 buffer.format = nativePixmap.format;
746 gl->rasterizer.procs.readBuffer(gl, &buffer);
747 return EGL_TRUE;
748}
749
750// ----------------------------------------------------------------------------
751
752struct egl_pbuffer_surface_t : public egl_surface_t
753{
754 egl_pbuffer_surface_t(
755 EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
756 int32_t w, int32_t h, int32_t f);
757
758 virtual ~egl_pbuffer_surface_t();
759
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700760 virtual bool isValid() const { return pbuffer.data != 0; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800761 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
762 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
763 virtual EGLint getWidth() const { return pbuffer.width; }
764 virtual EGLint getHeight() const { return pbuffer.height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800765private:
766 GGLSurface pbuffer;
767};
768
769egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
770 EGLConfig config, int32_t depthFormat,
771 int32_t w, int32_t h, int32_t f)
772 : egl_surface_t(dpy, config, depthFormat)
773{
774 size_t size = w*h;
775 switch (f) {
776 case GGL_PIXEL_FORMAT_A_8: size *= 1; break;
777 case GGL_PIXEL_FORMAT_RGB_565: size *= 2; break;
778 case GGL_PIXEL_FORMAT_RGBA_8888: size *= 4; break;
779 default:
780 LOGE("incompatible pixel format for pbuffer (format=%d)", f);
781 pbuffer.data = 0;
782 break;
783 }
784 pbuffer.version = sizeof(GGLSurface);
785 pbuffer.width = w;
786 pbuffer.height = h;
787 pbuffer.stride = w;
788 pbuffer.data = (GGLubyte*)malloc(size);
789 pbuffer.format = f;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700790
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800791 if (depthFormat) {
792 depth.width = pbuffer.width;
793 depth.height = pbuffer.height;
794 depth.stride = depth.width; // use the width here
795 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
796 if (depth.data == 0) {
797 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
798 return;
799 }
800 }
801}
802egl_pbuffer_surface_t::~egl_pbuffer_surface_t() {
803 free(pbuffer.data);
804}
805EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl)
806{
807 gl->rasterizer.procs.colorBuffer(gl, &pbuffer);
808 if (depth.data != gl->rasterizer.state.buffers.depth.data)
809 gl->rasterizer.procs.depthBuffer(gl, &depth);
810 return EGL_TRUE;
811}
812EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl)
813{
814 gl->rasterizer.procs.readBuffer(gl, &pbuffer);
815 return EGL_TRUE;
816}
817
818// ----------------------------------------------------------------------------
819
820struct config_pair_t {
821 GLint key;
822 GLint value;
823};
824
825struct configs_t {
826 const config_pair_t* array;
827 int size;
828};
829
830struct config_management_t {
831 GLint key;
832 bool (*match)(GLint reqValue, GLint confValue);
833 static bool atLeast(GLint reqValue, GLint confValue) {
834 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
835 }
836 static bool exact(GLint reqValue, GLint confValue) {
837 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
838 }
839 static bool mask(GLint reqValue, GLint confValue) {
840 return (confValue & reqValue) == reqValue;
841 }
842};
843
844// ----------------------------------------------------------------------------
845
846#define VERSION_MAJOR 1
847#define VERSION_MINOR 2
848static char const * const gVendorString = "Google Inc.";
849static char const * const gVersionString = "1.2 Android Driver";
850static char const * const gClientApiString = "OpenGL ES";
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700851static char const * const gExtensionsString =
Mathias Agopiane6bf8b32009-05-06 23:47:08 -0700852 "EGL_KHR_image_base "
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700853 // "KHR_image_pixmap "
854 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700855 "EGL_ANDROID_swap_rectangle "
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700856 "EGL_ANDROID_get_render_buffer "
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700857 ;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800858
859// ----------------------------------------------------------------------------
860
861struct extention_map_t {
862 const char * const name;
863 __eglMustCastToProperFunctionPointerType address;
864};
865
866static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700867 { "glDrawTexsOES",
868 (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
869 { "glDrawTexiOES",
870 (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
871 { "glDrawTexfOES",
872 (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
873 { "glDrawTexxOES",
874 (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
875 { "glDrawTexsvOES",
876 (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
877 { "glDrawTexivOES",
878 (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
879 { "glDrawTexfvOES",
880 (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
881 { "glDrawTexxvOES",
882 (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
883 { "glQueryMatrixxOES",
884 (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
885 { "glEGLImageTargetTexture2DOES",
886 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
887 { "glEGLImageTargetRenderbufferStorageOES",
888 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
889 { "glClipPlanef",
890 (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
891 { "glClipPlanex",
892 (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
893 { "glBindBuffer",
894 (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
895 { "glBufferData",
896 (__eglMustCastToProperFunctionPointerType)&glBufferData },
897 { "glBufferSubData",
898 (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
899 { "glDeleteBuffers",
900 (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
901 { "glGenBuffers",
902 (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700903 { "eglCreateImageKHR",
904 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
905 { "eglDestroyImageKHR",
906 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
907 { "eglSetSwapRectangleANDROID",
908 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
909 { "eglGetRenderBufferANDROID",
910 (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800911};
912
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700913/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800914 * In the lists below, attributes names MUST be sorted.
915 * Additionally, all configs must be sorted according to
916 * the EGL specification.
917 */
918
919static config_pair_t const config_base_attribute_list[] = {
920 { EGL_STENCIL_SIZE, 0 },
921 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
922 { EGL_LEVEL, 0 },
923 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700924 { EGL_MAX_PBUFFER_PIXELS,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800925 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
926 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
927 { EGL_NATIVE_RENDERABLE, EGL_TRUE },
928 { EGL_NATIVE_VISUAL_ID, 0 },
929 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGB_565 },
930 { EGL_SAMPLES, 0 },
931 { EGL_SAMPLE_BUFFERS, 0 },
932 { EGL_TRANSPARENT_TYPE, EGL_NONE },
933 { EGL_TRANSPARENT_BLUE_VALUE, 0 },
934 { EGL_TRANSPARENT_GREEN_VALUE, 0 },
935 { EGL_TRANSPARENT_RED_VALUE, 0 },
936 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
937 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
938 { EGL_MIN_SWAP_INTERVAL, 1 },
939 { EGL_MAX_SWAP_INTERVAL, 4 },
940};
941
942// These configs can override the base attribute list
943// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
944
945static config_pair_t const config_0_attribute_list[] = {
946 { EGL_BUFFER_SIZE, 16 },
947 { EGL_ALPHA_SIZE, 0 },
948 { EGL_BLUE_SIZE, 5 },
949 { EGL_GREEN_SIZE, 6 },
950 { EGL_RED_SIZE, 5 },
951 { EGL_DEPTH_SIZE, 0 },
952 { EGL_CONFIG_ID, 0 },
953 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
954};
955
956static config_pair_t const config_1_attribute_list[] = {
957 { EGL_BUFFER_SIZE, 16 },
958 { EGL_ALPHA_SIZE, 0 },
959 { EGL_BLUE_SIZE, 5 },
960 { EGL_GREEN_SIZE, 6 },
961 { EGL_RED_SIZE, 5 },
962 { EGL_DEPTH_SIZE, 16 },
963 { EGL_CONFIG_ID, 1 },
964 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
965};
966
967static config_pair_t const config_2_attribute_list[] = {
968 { EGL_BUFFER_SIZE, 32 },
969 { EGL_ALPHA_SIZE, 8 },
970 { EGL_BLUE_SIZE, 8 },
971 { EGL_GREEN_SIZE, 8 },
972 { EGL_RED_SIZE, 8 },
973 { EGL_DEPTH_SIZE, 0 },
974 { EGL_CONFIG_ID, 2 },
975 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
976};
977
978static config_pair_t const config_3_attribute_list[] = {
979 { EGL_BUFFER_SIZE, 32 },
980 { EGL_ALPHA_SIZE, 8 },
981 { EGL_BLUE_SIZE, 8 },
982 { EGL_GREEN_SIZE, 8 },
983 { EGL_RED_SIZE, 8 },
984 { EGL_DEPTH_SIZE, 16 },
985 { EGL_CONFIG_ID, 3 },
986 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
987};
988
989static config_pair_t const config_4_attribute_list[] = {
990 { EGL_BUFFER_SIZE, 8 },
991 { EGL_ALPHA_SIZE, 8 },
992 { EGL_BLUE_SIZE, 0 },
993 { EGL_GREEN_SIZE, 0 },
994 { EGL_RED_SIZE, 0 },
995 { EGL_DEPTH_SIZE, 0 },
996 { EGL_CONFIG_ID, 4 },
997 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
998};
999
1000static config_pair_t const config_5_attribute_list[] = {
1001 { EGL_BUFFER_SIZE, 8 },
1002 { EGL_ALPHA_SIZE, 8 },
1003 { EGL_BLUE_SIZE, 0 },
1004 { EGL_GREEN_SIZE, 0 },
1005 { EGL_RED_SIZE, 0 },
1006 { EGL_DEPTH_SIZE, 16 },
1007 { EGL_CONFIG_ID, 5 },
1008 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
1009};
1010
1011static configs_t const gConfigs[] = {
1012 { config_0_attribute_list, NELEM(config_0_attribute_list) },
1013 { config_1_attribute_list, NELEM(config_1_attribute_list) },
1014 { config_2_attribute_list, NELEM(config_2_attribute_list) },
1015 { config_3_attribute_list, NELEM(config_3_attribute_list) },
1016 { config_4_attribute_list, NELEM(config_4_attribute_list) },
1017 { config_5_attribute_list, NELEM(config_5_attribute_list) },
1018};
1019
1020static config_management_t const gConfigManagement[] = {
1021 { EGL_BUFFER_SIZE, config_management_t::atLeast },
1022 { EGL_ALPHA_SIZE, config_management_t::atLeast },
1023 { EGL_BLUE_SIZE, config_management_t::atLeast },
1024 { EGL_GREEN_SIZE, config_management_t::atLeast },
1025 { EGL_RED_SIZE, config_management_t::atLeast },
1026 { EGL_DEPTH_SIZE, config_management_t::atLeast },
1027 { EGL_STENCIL_SIZE, config_management_t::atLeast },
1028 { EGL_CONFIG_CAVEAT, config_management_t::exact },
1029 { EGL_CONFIG_ID, config_management_t::exact },
1030 { EGL_LEVEL, config_management_t::exact },
1031 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::exact },
1032 { EGL_MAX_PBUFFER_PIXELS, config_management_t::exact },
1033 { EGL_MAX_PBUFFER_WIDTH, config_management_t::exact },
1034 { EGL_NATIVE_RENDERABLE, config_management_t::exact },
1035 { EGL_NATIVE_VISUAL_ID, config_management_t::exact },
1036 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
1037 { EGL_SAMPLES, config_management_t::exact },
1038 { EGL_SAMPLE_BUFFERS, config_management_t::exact },
1039 { EGL_SURFACE_TYPE, config_management_t::mask },
1040 { EGL_TRANSPARENT_TYPE, config_management_t::exact },
1041 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
1042 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
1043 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
1044 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
1045 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
1046 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
1047 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
1048};
1049
1050static config_pair_t const config_defaults[] = {
1051 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
1052};
1053
1054// ----------------------------------------------------------------------------
1055
1056template<typename T>
1057static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
1058{
1059 while (first <= last) {
1060 int mid = (first + last) / 2;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001061 if (key > sortedArray[mid].key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001062 first = mid + 1;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001063 } else if (key < sortedArray[mid].key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001064 last = mid - 1;
1065 } else {
1066 return mid;
1067 }
1068 }
1069 return -1;
1070}
1071
1072static int isAttributeMatching(int i, EGLint attr, EGLint val)
1073{
1074 // look for the attribute in all of our configs
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001075 config_pair_t const* configFound = gConfigs[i].array;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001076 int index = binarySearch<config_pair_t>(
1077 gConfigs[i].array,
1078 0, gConfigs[i].size-1,
1079 attr);
1080 if (index < 0) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001081 configFound = config_base_attribute_list;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001082 index = binarySearch<config_pair_t>(
1083 config_base_attribute_list,
1084 0, NELEM(config_base_attribute_list)-1,
1085 attr);
1086 }
1087 if (index >= 0) {
1088 // attribute found, check if this config could match
1089 int cfgMgtIndex = binarySearch<config_management_t>(
1090 gConfigManagement,
1091 0, NELEM(gConfigManagement)-1,
1092 attr);
1093 if (index >= 0) {
1094 bool match = gConfigManagement[cfgMgtIndex].match(
1095 val, configFound[index].value);
1096 if (match) {
1097 // this config matches
1098 return 1;
1099 }
1100 } else {
1101 // attribute not found. this should NEVER happen.
1102 }
1103 } else {
1104 // error, this attribute doesn't exist
1105 }
1106 return 0;
1107}
1108
1109static int makeCurrent(ogles_context_t* gl)
1110{
1111 ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific();
1112 if (gl) {
1113 egl_context_t* c = egl_context_t::context(gl);
1114 if (c->flags & egl_context_t::IS_CURRENT) {
1115 if (current != gl) {
1116 // it is an error to set a context current, if it's already
1117 // current to another thread
1118 return -1;
1119 }
1120 } else {
1121 if (current) {
1122 // mark the current context as not current, and flush
1123 glFlush();
1124 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1125 }
1126 }
1127 if (!(c->flags & egl_context_t::IS_CURRENT)) {
1128 // The context is not current, make it current!
1129 setGlThreadSpecific(gl);
1130 c->flags |= egl_context_t::IS_CURRENT;
1131 }
1132 } else {
1133 if (current) {
1134 // mark the current context as not current, and flush
1135 glFlush();
1136 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1137 }
1138 // this thread has no context attached to it
1139 setGlThreadSpecific(0);
1140 }
1141 return 0;
1142}
1143
1144static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
1145 EGLint attribute, EGLint *value)
1146{
1147 size_t numConfigs = NELEM(gConfigs);
1148 int index = (int)config;
1149 if (uint32_t(index) >= numConfigs)
1150 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1151
1152 int attrIndex;
1153 attrIndex = binarySearch<config_pair_t>(
1154 gConfigs[index].array,
1155 0, gConfigs[index].size-1,
1156 attribute);
1157 if (attrIndex>=0) {
1158 *value = gConfigs[index].array[attrIndex].value;
1159 return EGL_TRUE;
1160 }
1161
1162 attrIndex = binarySearch<config_pair_t>(
1163 config_base_attribute_list,
1164 0, NELEM(config_base_attribute_list)-1,
1165 attribute);
1166 if (attrIndex>=0) {
1167 *value = config_base_attribute_list[attrIndex].value;
1168 return EGL_TRUE;
1169 }
1170 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1171}
1172
1173static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
1174 NativeWindowType window, const EGLint *attrib_list)
1175{
1176 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1177 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1178 if (window == 0)
1179 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1180
1181 EGLint surfaceType;
1182 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1183 return EGL_FALSE;
1184
1185 if (!(surfaceType & EGL_WINDOW_BIT))
1186 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1187
1188 EGLint configID;
1189 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1190 return EGL_FALSE;
1191
1192 int32_t depthFormat;
1193 int32_t pixelFormat;
1194 switch(configID) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001195 case 0:
1196 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001197 depthFormat = 0;
1198 break;
1199 case 1:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001200 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001201 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1202 break;
1203 case 2:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001204 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001205 depthFormat = 0;
1206 break;
1207 case 3:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001208 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001209 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1210 break;
1211 case 4:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001212 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001213 depthFormat = 0;
1214 break;
1215 case 5:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001216 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001217 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1218 break;
1219 default:
1220 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1221 }
1222
1223 // FIXME: we don't have access to the pixelFormat here just yet.
1224 // (it's possible that the surface is not fully initialized)
1225 // maybe this should be done after the page-flip
1226 //if (EGLint(info.format) != pixelFormat)
1227 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1228
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001229 egl_surface_t* surface;
1230 surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
1231 static_cast<android_native_window_t*>(window));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001232
1233 if (!surface->isValid()) {
1234 // there was a problem in the ctor, the error
1235 // flag has been set.
1236 delete surface;
1237 surface = 0;
1238 }
1239 return surface;
1240}
1241
1242static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
1243 NativePixmapType pixmap, const EGLint *attrib_list)
1244{
1245 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1246 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1247 if (pixmap == 0)
1248 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1249
1250 EGLint surfaceType;
1251 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1252 return EGL_FALSE;
1253
1254 if (!(surfaceType & EGL_PIXMAP_BIT))
1255 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1256
1257 EGLint configID;
1258 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1259 return EGL_FALSE;
1260
1261 int32_t depthFormat;
1262 int32_t pixelFormat;
1263 switch(configID) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001264 case 0:
1265 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001266 depthFormat = 0;
1267 break;
1268 case 1:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001269 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001270 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1271 break;
1272 case 2:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001273 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001274 depthFormat = 0;
1275 break;
1276 case 3:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001277 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001278 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1279 break;
1280 case 4:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001281 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001282 depthFormat = 0;
1283 break;
1284 case 5:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001285 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001286 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1287 break;
1288 default:
1289 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1290 }
1291
1292 if (pixmap->format != pixelFormat)
1293 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1294
1295 egl_surface_t* surface =
1296 new egl_pixmap_surface_t(dpy, config, depthFormat,
1297 static_cast<egl_native_pixmap_t*>(pixmap));
1298
1299 if (!surface->isValid()) {
1300 // there was a problem in the ctor, the error
1301 // flag has been set.
1302 delete surface;
1303 surface = 0;
1304 }
1305 return surface;
1306}
1307
1308static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
1309 const EGLint *attrib_list)
1310{
1311 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1312 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1313
1314 EGLint surfaceType;
1315 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1316 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001317
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001318 if (!(surfaceType & EGL_PBUFFER_BIT))
1319 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001320
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001321 EGLint configID;
1322 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1323 return EGL_FALSE;
1324
1325 int32_t depthFormat;
1326 int32_t pixelFormat;
1327 switch(configID) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001328 case 0:
1329 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001330 depthFormat = 0;
1331 break;
1332 case 1:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001333 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001334 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1335 break;
1336 case 2:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001337 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001338 depthFormat = 0;
1339 break;
1340 case 3:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001341 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001342 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1343 break;
1344 case 4:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001345 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001346 depthFormat = 0;
1347 break;
1348 case 5:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001349 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001350 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1351 break;
1352 default:
1353 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1354 }
1355
1356 int32_t w = 0;
1357 int32_t h = 0;
1358 while (attrib_list[0]) {
1359 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
1360 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
1361 attrib_list+=2;
1362 }
1363
1364 egl_surface_t* surface =
1365 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
1366
1367 if (!surface->isValid()) {
1368 // there was a problem in the ctor, the error
1369 // flag has been set.
1370 delete surface;
1371 surface = 0;
1372 }
1373 return surface;
1374}
1375
1376// ----------------------------------------------------------------------------
1377}; // namespace android
1378// ----------------------------------------------------------------------------
1379
1380using namespace android;
1381
1382// ----------------------------------------------------------------------------
1383// Initialization
1384// ----------------------------------------------------------------------------
1385
1386EGLDisplay eglGetDisplay(NativeDisplayType display)
1387{
1388#ifndef HAVE_ANDROID_OS
1389 // this just needs to be done once
1390 if (gGLKey == -1) {
1391 pthread_mutex_lock(&gInitMutex);
1392 if (gGLKey == -1)
1393 pthread_key_create(&gGLKey, NULL);
1394 pthread_mutex_unlock(&gInitMutex);
1395 }
1396#endif
1397 if (display == EGL_DEFAULT_DISPLAY) {
1398 EGLDisplay dpy = (EGLDisplay)1;
1399 egl_display_t& d = egl_display_t::get_display(dpy);
1400 d.type = display;
1401 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001402 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001403 return EGL_NO_DISPLAY;
1404}
1405
1406EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
1407{
1408 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1409 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001410
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001411 EGLBoolean res = EGL_TRUE;
1412 egl_display_t& d = egl_display_t::get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001413
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001414 if (android_atomic_inc(&d.initialized) == 0) {
1415 // initialize stuff here if needed
1416 //pthread_mutex_lock(&gInitMutex);
1417 //pthread_mutex_unlock(&gInitMutex);
1418 }
1419
1420 if (res == EGL_TRUE) {
1421 if (major != NULL) *major = VERSION_MAJOR;
1422 if (minor != NULL) *minor = VERSION_MINOR;
1423 }
1424 return res;
1425}
1426
1427EGLBoolean eglTerminate(EGLDisplay dpy)
1428{
1429 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1430 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1431
1432 EGLBoolean res = EGL_TRUE;
1433 egl_display_t& d = egl_display_t::get_display(dpy);
1434 if (android_atomic_dec(&d.initialized) == 1) {
1435 // TODO: destroy all resources (surfaces, contexts, etc...)
1436 //pthread_mutex_lock(&gInitMutex);
1437 //pthread_mutex_unlock(&gInitMutex);
1438 }
1439 return res;
1440}
1441
1442// ----------------------------------------------------------------------------
1443// configuration
1444// ----------------------------------------------------------------------------
1445
1446EGLBoolean eglGetConfigs( EGLDisplay dpy,
1447 EGLConfig *configs,
1448 EGLint config_size, EGLint *num_config)
1449{
1450 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1451 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1452
1453 GLint numConfigs = NELEM(gConfigs);
1454 if (!configs) {
1455 *num_config = numConfigs;
1456 return EGL_TRUE;
1457 }
1458 GLint i;
1459 for (i=0 ; i<numConfigs && i<config_size ; i++) {
1460 *configs++ = (EGLConfig)i;
1461 }
1462 *num_config = i;
1463 return EGL_TRUE;
1464}
1465
1466EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
1467 EGLConfig *configs, EGLint config_size,
1468 EGLint *num_config)
1469{
1470 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1471 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Jack Palevich749c63d2009-03-25 15:12:17 -07001472
1473 if (ggl_unlikely(num_config==0)) {
1474 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1475 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001476
Jack Palevich749c63d2009-03-25 15:12:17 -07001477 if (ggl_unlikely(attrib_list==0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001478 *num_config = 0;
1479 return EGL_TRUE;
1480 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001481
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001482 int numAttributes = 0;
1483 int numConfigs = NELEM(gConfigs);
1484 uint32_t possibleMatch = (1<<numConfigs)-1;
1485 while(possibleMatch && *attrib_list != EGL_NONE) {
1486 numAttributes++;
1487 EGLint attr = *attrib_list++;
1488 EGLint val = *attrib_list++;
1489 for (int i=0 ; i<numConfigs ; i++) {
1490 if (!(possibleMatch & (1<<i)))
1491 continue;
1492 if (isAttributeMatching(i, attr, val) == 0) {
1493 possibleMatch &= ~(1<<i);
1494 }
1495 }
1496 }
1497
1498 // now, handle the attributes which have a useful default value
1499 for (size_t j=0 ; j<NELEM(config_defaults) ; j++) {
1500 // see if this attribute was specified, if not apply its
1501 // default value
1502 if (binarySearch<config_pair_t>(
1503 (config_pair_t const*)attrib_list,
Mathias Agopiandacd7a32009-07-09 17:33:15 -07001504 0, numAttributes-1,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001505 config_defaults[j].key) < 0)
1506 {
1507 for (int i=0 ; i<numConfigs ; i++) {
1508 if (!(possibleMatch & (1<<i)))
1509 continue;
1510 if (isAttributeMatching(i,
1511 config_defaults[j].key,
1512 config_defaults[j].value) == 0)
1513 {
1514 possibleMatch &= ~(1<<i);
1515 }
1516 }
1517 }
1518 }
1519
1520 // return the configurations found
1521 int n=0;
1522 if (possibleMatch) {
Jack Palevich749c63d2009-03-25 15:12:17 -07001523 if (configs) {
1524 for (int i=0 ; config_size && i<numConfigs ; i++) {
1525 if (possibleMatch & (1<<i)) {
1526 *configs++ = (EGLConfig)i;
1527 config_size--;
1528 n++;
1529 }
1530 }
1531 } else {
1532 for (int i=0 ; i<numConfigs ; i++) {
1533 if (possibleMatch & (1<<i)) {
1534 n++;
1535 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001536 }
1537 }
1538 }
1539 *num_config = n;
1540 return EGL_TRUE;
1541}
1542
1543EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
1544 EGLint attribute, EGLint *value)
1545{
1546 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1547 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1548
1549 return getConfigAttrib(dpy, config, attribute, value);
1550}
1551
1552// ----------------------------------------------------------------------------
1553// surfaces
1554// ----------------------------------------------------------------------------
1555
1556EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
1557 NativeWindowType window,
1558 const EGLint *attrib_list)
1559{
1560 return createWindowSurface(dpy, config, window, attrib_list);
1561}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001562
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001563EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1564 NativePixmapType pixmap,
1565 const EGLint *attrib_list)
1566{
1567 return createPixmapSurface(dpy, config, pixmap, attrib_list);
1568}
1569
1570EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1571 const EGLint *attrib_list)
1572{
1573 return createPbufferSurface(dpy, config, attrib_list);
1574}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001575
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001576EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1577{
1578 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1579 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1580 if (eglSurface != EGL_NO_SURFACE) {
1581 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1582 if (surface->magic != egl_surface_t::MAGIC)
1583 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1584 if (surface->dpy != dpy)
1585 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopiane71212b2009-05-05 00:37:46 -07001586 if (surface->ctx) {
1587 // FIXME: this surface is current check what the spec says
1588 surface->disconnect();
1589 surface->ctx = 0;
1590 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001591 delete surface;
1592 }
1593 return EGL_TRUE;
1594}
1595
1596EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
1597 EGLint attribute, EGLint *value)
1598{
1599 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1600 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1601 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
1602 if (surface->dpy != dpy)
1603 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1604
1605 EGLBoolean ret = EGL_TRUE;
1606 switch (attribute) {
1607 case EGL_CONFIG_ID:
1608 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
1609 break;
1610 case EGL_WIDTH:
1611 *value = surface->getWidth();
1612 break;
1613 case EGL_HEIGHT:
1614 *value = surface->getHeight();
1615 break;
1616 case EGL_LARGEST_PBUFFER:
1617 // not modified for a window or pixmap surface
1618 break;
1619 case EGL_TEXTURE_FORMAT:
1620 *value = EGL_NO_TEXTURE;
1621 break;
1622 case EGL_TEXTURE_TARGET:
1623 *value = EGL_NO_TEXTURE;
1624 break;
1625 case EGL_MIPMAP_TEXTURE:
1626 *value = EGL_FALSE;
1627 break;
1628 case EGL_MIPMAP_LEVEL:
1629 *value = 0;
1630 break;
1631 case EGL_RENDER_BUFFER:
1632 // TODO: return the real RENDER_BUFFER here
1633 *value = EGL_BACK_BUFFER;
1634 break;
1635 case EGL_HORIZONTAL_RESOLUTION:
1636 // pixel/mm * EGL_DISPLAY_SCALING
1637 *value = surface->getHorizontalResolution();
1638 break;
1639 case EGL_VERTICAL_RESOLUTION:
1640 // pixel/mm * EGL_DISPLAY_SCALING
1641 *value = surface->getVerticalResolution();
1642 break;
1643 case EGL_PIXEL_ASPECT_RATIO: {
1644 // w/h * EGL_DISPLAY_SCALING
1645 int wr = surface->getHorizontalResolution();
1646 int hr = surface->getVerticalResolution();
1647 *value = (wr * EGL_DISPLAY_SCALING) / hr;
1648 } break;
1649 case EGL_SWAP_BEHAVIOR:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001650 *value = surface->getSwapBehavior();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001651 break;
1652 default:
1653 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1654 }
1655 return ret;
1656}
1657
1658EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1659 EGLContext share_list, const EGLint *attrib_list)
1660{
1661 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1662 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1663
1664 ogles_context_t* gl = ogles_init(sizeof(egl_context_t));
1665 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1666
1667 egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
1668 c->flags = egl_context_t::NEVER_CURRENT;
1669 c->dpy = dpy;
1670 c->config = config;
1671 c->read = 0;
1672 c->draw = 0;
1673 return (EGLContext)gl;
1674}
1675
1676EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1677{
1678 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1679 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1680 egl_context_t* c = egl_context_t::context(ctx);
1681 if (c->flags & egl_context_t::IS_CURRENT)
1682 setGlThreadSpecific(0);
1683 ogles_uninit((ogles_context_t*)ctx);
1684 return EGL_TRUE;
1685}
1686
1687EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1688 EGLSurface read, EGLContext ctx)
1689{
1690 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1691 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1692 if (draw) {
1693 egl_surface_t* s = (egl_surface_t*)draw;
1694 if (s->dpy != dpy)
1695 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1696 // TODO: check that draw and read are compatible with the context
1697 }
1698
1699 EGLContext current_ctx = EGL_NO_CONTEXT;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001700
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001701 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1702 return setError(EGL_BAD_MATCH, EGL_FALSE);
1703
1704 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1705 return setError(EGL_BAD_MATCH, EGL_FALSE);
1706
1707 if (ctx == EGL_NO_CONTEXT) {
1708 // if we're detaching, we need the current context
1709 current_ctx = (EGLContext)getGlThreadSpecific();
1710 } else {
1711 egl_context_t* c = egl_context_t::context(ctx);
1712 egl_surface_t* d = (egl_surface_t*)draw;
1713 egl_surface_t* r = (egl_surface_t*)read;
1714 if ((d && d->ctx && d->ctx != ctx) ||
1715 (r && r->ctx && r->ctx != ctx)) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001716 // one of the surface is bound to a context in another thread
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001717 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1718 }
1719 }
1720
1721 ogles_context_t* gl = (ogles_context_t*)ctx;
1722 if (makeCurrent(gl) == 0) {
1723 if (ctx) {
1724 egl_context_t* c = egl_context_t::context(ctx);
1725 egl_surface_t* d = (egl_surface_t*)draw;
1726 egl_surface_t* r = (egl_surface_t*)read;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001727
1728 if (c->draw) {
1729 reinterpret_cast<egl_surface_t*>(c->draw)->disconnect();
1730 }
1731 if (c->read) {
1732 // FIXME: unlock/disconnect the read surface too
1733 }
1734
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001735 c->draw = draw;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001736 c->read = read;
1737
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001738 if (c->flags & egl_context_t::NEVER_CURRENT) {
1739 c->flags &= ~egl_context_t::NEVER_CURRENT;
1740 GLint w = 0;
1741 GLint h = 0;
1742 if (draw) {
1743 w = d->getWidth();
1744 h = d->getHeight();
1745 }
1746 ogles_surfaceport(gl, 0, 0);
1747 ogles_viewport(gl, 0, 0, w, h);
1748 ogles_scissor(gl, 0, 0, w, h);
1749 }
1750 if (d) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001751 d->connect();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001752 d->ctx = ctx;
1753 d->bindDrawSurface(gl);
1754 }
1755 if (r) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001756 // FIXME: lock/connect the read surface too
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001757 r->ctx = ctx;
1758 r->bindReadSurface(gl);
1759 }
1760 } else {
1761 // if surfaces were bound to the context bound to this thread
1762 // mark then as unbound.
1763 if (current_ctx) {
1764 egl_context_t* c = egl_context_t::context(current_ctx);
1765 egl_surface_t* d = (egl_surface_t*)c->draw;
1766 egl_surface_t* r = (egl_surface_t*)c->read;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001767 if (d) {
Mathias Agopian9648c1a2009-06-03 19:00:53 -07001768 c->draw = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001769 d->ctx = EGL_NO_CONTEXT;
1770 d->disconnect();
1771 }
1772 if (r) {
Mathias Agopian9648c1a2009-06-03 19:00:53 -07001773 c->read = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001774 r->ctx = EGL_NO_CONTEXT;
1775 // FIXME: unlock/disconnect the read surface too
1776 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001777 }
1778 }
1779 return EGL_TRUE;
1780 }
1781 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1782}
1783
1784EGLContext eglGetCurrentContext(void)
1785{
1786 // eglGetCurrentContext returns the current EGL rendering context,
1787 // as specified by eglMakeCurrent. If no context is current,
1788 // EGL_NO_CONTEXT is returned.
1789 return (EGLContext)getGlThreadSpecific();
1790}
1791
1792EGLSurface eglGetCurrentSurface(EGLint readdraw)
1793{
1794 // eglGetCurrentSurface returns the read or draw surface attached
1795 // to the current EGL rendering context, as specified by eglMakeCurrent.
1796 // If no context is current, EGL_NO_SURFACE is returned.
1797 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1798 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
1799 egl_context_t* c = egl_context_t::context(ctx);
1800 if (readdraw == EGL_READ) {
1801 return c->read;
1802 } else if (readdraw == EGL_DRAW) {
1803 return c->draw;
1804 }
1805 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
1806}
1807
1808EGLDisplay eglGetCurrentDisplay(void)
1809{
1810 // eglGetCurrentDisplay returns the current EGL display connection
1811 // for the current EGL rendering context, as specified by eglMakeCurrent.
1812 // If no context is current, EGL_NO_DISPLAY is returned.
1813 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1814 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
1815 egl_context_t* c = egl_context_t::context(ctx);
1816 return c->dpy;
1817}
1818
1819EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1820 EGLint attribute, EGLint *value)
1821{
1822 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1823 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1824 egl_context_t* c = egl_context_t::context(ctx);
1825 switch (attribute) {
1826 case EGL_CONFIG_ID:
1827 // Returns the ID of the EGL frame buffer configuration with
1828 // respect to which the context was created
1829 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
1830 }
1831 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1832}
1833
1834EGLBoolean eglWaitGL(void)
1835{
1836 return EGL_TRUE;
1837}
1838
1839EGLBoolean eglWaitNative(EGLint engine)
1840{
1841 return EGL_TRUE;
1842}
1843
1844EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1845{
1846 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1847 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001848
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001849 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
1850 if (d->dpy != dpy)
1851 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1852
1853 // post the surface
1854 d->swapBuffers();
1855
1856 // if it's bound to a context, update the buffer
1857 if (d->ctx != EGL_NO_CONTEXT) {
1858 d->bindDrawSurface((ogles_context_t*)d->ctx);
1859 // if this surface is also the read surface of the context
1860 // it is bound to, make sure to update the read buffer as well.
1861 // The EGL spec is a little unclear about this.
1862 egl_context_t* c = egl_context_t::context(d->ctx);
1863 if (c->read == draw) {
1864 d->bindReadSurface((ogles_context_t*)d->ctx);
1865 }
1866 }
1867
1868 return EGL_TRUE;
1869}
1870
1871EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1872 NativePixmapType target)
1873{
1874 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1875 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1876 // TODO: eglCopyBuffers()
1877 return EGL_FALSE;
1878}
1879
1880EGLint eglGetError(void)
1881{
1882 return getError();
1883}
1884
1885const char* eglQueryString(EGLDisplay dpy, EGLint name)
1886{
1887 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1888 return setError(EGL_BAD_DISPLAY, (const char*)0);
1889
1890 switch (name) {
1891 case EGL_VENDOR:
1892 return gVendorString;
1893 case EGL_VERSION:
1894 return gVersionString;
1895 case EGL_EXTENSIONS:
1896 return gExtensionsString;
1897 case EGL_CLIENT_APIS:
1898 return gClientApiString;
1899 }
1900 return setError(EGL_BAD_PARAMETER, (const char *)0);
1901}
1902
1903// ----------------------------------------------------------------------------
1904// EGL 1.1
1905// ----------------------------------------------------------------------------
1906
1907EGLBoolean eglSurfaceAttrib(
1908 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1909{
1910 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1911 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1912 // TODO: eglSurfaceAttrib()
1913 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1914}
1915
1916EGLBoolean eglBindTexImage(
1917 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1918{
1919 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1920 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1921 // TODO: eglBindTexImage()
1922 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1923}
1924
1925EGLBoolean eglReleaseTexImage(
1926 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1927{
1928 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1929 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1930 // TODO: eglReleaseTexImage()
1931 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1932}
1933
1934EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1935{
1936 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1937 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1938 // TODO: eglSwapInterval()
1939 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1940}
1941
1942// ----------------------------------------------------------------------------
1943// EGL 1.2
1944// ----------------------------------------------------------------------------
1945
1946EGLBoolean eglBindAPI(EGLenum api)
1947{
1948 if (api != EGL_OPENGL_ES_API)
1949 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1950 return EGL_TRUE;
1951}
1952
1953EGLenum eglQueryAPI(void)
1954{
1955 return EGL_OPENGL_ES_API;
1956}
1957
1958EGLBoolean eglWaitClient(void)
1959{
1960 glFinish();
1961 return EGL_TRUE;
1962}
1963
1964EGLBoolean eglReleaseThread(void)
1965{
1966 // TODO: eglReleaseThread()
1967 return EGL_TRUE;
1968}
1969
1970EGLSurface eglCreatePbufferFromClientBuffer(
1971 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1972 EGLConfig config, const EGLint *attrib_list)
1973{
1974 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1975 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1976 // TODO: eglCreatePbufferFromClientBuffer()
1977 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1978}
1979
1980// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001981// EGL_EGLEXT_VERSION 3
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001982// ----------------------------------------------------------------------------
1983
1984void (*eglGetProcAddress (const char *procname))()
1985{
1986 extention_map_t const * const map = gExtentionMap;
1987 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
1988 if (!strcmp(procname, map[i].name)) {
1989 return map[i].address;
1990 }
1991 }
1992 return NULL;
1993}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001994
1995EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1996 const EGLint *attrib_list)
1997{
1998 EGLBoolean result = EGL_FALSE;
1999 return result;
2000}
2001
2002EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
2003{
2004 EGLBoolean result = EGL_FALSE;
2005 return result;
2006}
2007
2008EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
2009 EGLClientBuffer buffer, const EGLint *attrib_list)
2010{
2011 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2012 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
2013 }
2014 if (ctx != EGL_NO_CONTEXT) {
2015 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
2016 }
2017 if (target != EGL_NATIVE_BUFFER_ANDROID) {
2018 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2019 }
2020
2021 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
2022
2023 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2024 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2025
2026 if (native_buffer->common.version != sizeof(android_native_buffer_t))
2027 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
Mathias Agopian8b765b72009-04-10 20:34:46 -07002028
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002029 native_buffer->common.incRef(&native_buffer->common);
2030 return (EGLImageKHR)native_buffer;
2031}
2032
2033EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2034{
2035 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2036 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2037 }
2038
2039 android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
2040
2041 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2042 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2043
2044 if (native_buffer->common.version != sizeof(android_native_buffer_t))
2045 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2046
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002047 native_buffer->common.decRef(&native_buffer->common);
2048
2049 return EGL_TRUE;
2050}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002051
2052// ----------------------------------------------------------------------------
2053// ANDROID extensions
2054// ----------------------------------------------------------------------------
2055
2056EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2057 EGLint left, EGLint top, EGLint width, EGLint height)
2058{
2059 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2060 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2061
2062 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
2063 if (d->dpy != dpy)
2064 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2065
2066 // post the surface
2067 d->setSwapRectangle(left, top, width, height);
2068
2069 return EGL_TRUE;
2070}
Mathias Agopian8d2e83b2009-06-24 22:37:39 -07002071
2072EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
2073{
2074 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2075 return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
2076
2077 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
2078 if (d->dpy != dpy)
2079 return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
2080
2081 // post the surface
2082 return d->getRenderBuffer();
2083}