blob: 7afcae7504f8962c8ee6b688988800a89c116031 [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 Agopian076b1cc2009-04-10 14:24:30 -0700219 virtual EGLint getWidth() const { return buffer->width; }
220 virtual EGLint getHeight() const { return buffer->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);
368
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700369 // dequeue a buffer
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700370 nativeWindow->dequeueBuffer(nativeWindow, &buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700371
372 // allocate a corresponding depth-buffer
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700373 width = buffer->width;
374 height = buffer->height;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800375 if (depthFormat) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700376 depth.width = width;
377 depth.height = height;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378 depth.stride = depth.width; // use the width here
379 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
380 if (depth.data == 0) {
381 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
382 return;
383 }
384 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700385
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700386 // keep a reference on the buffer
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700387 buffer->common.incRef(&buffer->common);
Mathias Agopiane71212b2009-05-05 00:37:46 -0700388}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700389
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700390egl_window_surface_v2_t::~egl_window_surface_v2_t() {
391 if (buffer) {
392 buffer->common.decRef(&buffer->common);
393 }
394 if (previousBuffer) {
395 previousBuffer->common.decRef(&previousBuffer->common);
396 }
397 nativeWindow->common.decRef(&nativeWindow->common);
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700398 if (blitengine) {
399 copybit_close(blitengine);
400 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700401}
402
Mathias Agopiane71212b2009-05-05 00:37:46 -0700403void egl_window_surface_v2_t::connect()
404{
Mathias Agopian0926f502009-05-04 14:17:04 -0700405 // Lock the buffer
Mathias Agopiane71212b2009-05-05 00:37:46 -0700406 nativeWindow->lockBuffer(nativeWindow, buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700407 // pin the buffer down
408 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
409 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700410 LOGE("connect() failed to lock buffer %p (%ux%u)",
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700411 buffer, buffer->width, buffer->height);
412 setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
413 // FIXME: we should make sure we're not accessing the buffer anymore
414 }
Mathias Agopiane71212b2009-05-05 00:37:46 -0700415}
416
417void egl_window_surface_v2_t::disconnect()
418{
Mathias Agopian9648c1a2009-06-03 19:00:53 -0700419 if (buffer && bits) {
Mathias Agopiane71212b2009-05-05 00:37:46 -0700420 bits = NULL;
421 unlock(buffer);
422 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800423}
424
Mathias Agopian0926f502009-05-04 14:17:04 -0700425status_t egl_window_surface_v2_t::lock(
Mathias Agopiane71212b2009-05-05 00:37:46 -0700426 android_native_buffer_t* buf, int usage, void** vaddr)
Mathias Agopian0926f502009-05-04 14:17:04 -0700427{
Mathias Agopian21c59d02009-05-05 00:59:23 -0700428 int err = module->lock(module, buf->handle,
Mathias Agopiane71212b2009-05-05 00:37:46 -0700429 usage, 0, 0, buf->width, buf->height, vaddr);
Mathias Agopian0926f502009-05-04 14:17:04 -0700430 return err;
431}
432
433status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
434{
Mathias Agopian21c59d02009-05-05 00:59:23 -0700435 int err = module->unlock(module, buf->handle);
Mathias Agopian0926f502009-05-04 14:17:04 -0700436 return err;
437}
438
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700439void egl_window_surface_v2_t::copyBlt(
440 android_native_buffer_t* dst, void* dst_vaddr,
441 android_native_buffer_t* src, void const* src_vaddr,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700442 const Region& clip)
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700443{
444 // FIXME: use copybit if possible
445 // NOTE: dst and src must be the same format
446
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700447 status_t err = NO_ERROR;
448 copybit_device_t* const copybit = blitengine;
449 if (copybit) {
450 copybit_image_t simg;
451 simg.w = src->width;
452 simg.h = src->height;
453 simg.format = src->format;
454 simg.handle = const_cast<native_handle_t*>(src->handle);
Mathias Agopian0926f502009-05-04 14:17:04 -0700455
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700456 copybit_image_t dimg;
457 dimg.w = dst->width;
458 dimg.h = dst->height;
459 dimg.format = dst->format;
460 dimg.handle = const_cast<native_handle_t*>(dst->handle);
461
462 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
463 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
464 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
465 region_iterator it(clip);
466 err = copybit->blit(copybit, &dimg, &simg, &it);
467 if (err != NO_ERROR) {
468 LOGE("copybit failed (%s)", strerror(err));
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700469 }
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700470 }
471
472 if (!copybit || err) {
473 Region::const_iterator cur = clip.begin();
474 Region::const_iterator end = clip.end();
475
476 const size_t bpp = pixelFormatTable[src->format].size;
477 const size_t dbpr = dst->stride * bpp;
478 const size_t sbpr = src->stride * bpp;
479
480 uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
481 uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
482
483 while (cur != end) {
484 const Rect& r(*cur++);
485 ssize_t w = r.right - r.left;
486 ssize_t h = r.bottom - r.top;
487 if (w <= 0 || h<=0) continue;
488 size_t size = w * bpp;
489 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
490 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
491 if (dbpr==sbpr && size==sbpr) {
492 size *= h;
493 h = 1;
494 }
495 do {
496 memcpy(d, s, size);
497 d += dbpr;
498 s += sbpr;
499 } while (--h > 0);
500 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700501 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700502}
503
504EGLBoolean egl_window_surface_v2_t::swapBuffers()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505{
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700506 /*
507 * Handle eglSetSwapRectangleANDROID()
508 * We copyback from the front buffer
509 */
510 if (!dirtyRegion.isEmpty()) {
511 dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
512 if (previousBuffer) {
513 const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
514 if (!copyBack.isEmpty()) {
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700515 void* prevBits;
516 if (lock(previousBuffer,
Mathias Agopian240c9fe2009-06-25 15:39:25 -0700517 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
518 // copy from previousBuffer to buffer
519 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700520 unlock(previousBuffer);
521 }
522 }
523 }
524 oldDirtyRegion = dirtyRegion;
525 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700526
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700527 if (previousBuffer) {
528 previousBuffer->common.decRef(&previousBuffer->common);
529 previousBuffer = 0;
530 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700531
Mathias Agopian0926f502009-05-04 14:17:04 -0700532 unlock(buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700533 previousBuffer = buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700534 nativeWindow->queueBuffer(nativeWindow, buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700535 buffer = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700536
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700537 // dequeue a new buffer
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700538 nativeWindow->dequeueBuffer(nativeWindow, &buffer);
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700539
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700540 // TODO: lockBuffer should rather be executed when the very first
541 // direct rendering occurs.
542 nativeWindow->lockBuffer(nativeWindow, buffer);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700543
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700544 // reallocate the depth-buffer if needed
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700545 if ((width != buffer->width) || (height != buffer->height)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800546 // TODO: we probably should reset the swap rect here
547 // if the window size has changed
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700548 width = buffer->width;
549 height = buffer->height;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800550 if (depth.data) {
551 free(depth.data);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700552 depth.width = width;
553 depth.height = height;
554 depth.stride = buffer->stride;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800555 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
556 if (depth.data == 0) {
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700557 setError(EGL_BAD_ALLOC, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800558 return EGL_FALSE;
559 }
560 }
561 }
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700562
563 // keep a reference on the buffer
564 buffer->common.incRef(&buffer->common);
565
566 // finally pin the buffer down
567 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
568 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
569 LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
570 buffer, buffer->width, buffer->height);
571 setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
572 // FIXME: we should make sure we're not accessing the buffer anymore
573 }
574
575 return EGL_TRUE;
576}
577
578EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
579 EGLint l, EGLint t, EGLint w, EGLint h)
580{
581 dirtyRegion = Rect(l, t, l+w, t+h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800582 return EGL_TRUE;
583}
584
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700585EGLClientBuffer egl_window_surface_v2_t::getRenderBuffer() const
586{
587 return buffer;
588}
589
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700590#ifdef LIBAGL_USE_GRALLOC_COPYBITS
591
592static bool supportedCopybitsDestinationFormat(int format) {
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700593 // Hardware supported
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700594 switch (format) {
595 case HAL_PIXEL_FORMAT_RGB_565:
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700596 case HAL_PIXEL_FORMAT_RGBA_8888:
597 case HAL_PIXEL_FORMAT_RGBA_4444:
598 case HAL_PIXEL_FORMAT_RGBA_5551:
599 case HAL_PIXEL_FORMAT_BGRA_8888:
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700600 return true;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700601 }
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700602 return false;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700603}
604#endif
605
606EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800607{
608 GGLSurface buffer;
609 buffer.version = sizeof(GGLSurface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700610 buffer.width = this->buffer->width;
611 buffer.height = this->buffer->height;
612 buffer.stride = this->buffer->stride;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700613 buffer.data = (GGLubyte*)bits;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700614 buffer.format = this->buffer->format;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800615 gl->rasterizer.procs.colorBuffer(gl, &buffer);
616 if (depth.data != gl->rasterizer.state.buffers.depth.data)
617 gl->rasterizer.procs.depthBuffer(gl, &depth);
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700618
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700619#ifdef LIBAGL_USE_GRALLOC_COPYBITS
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700620 gl->copybits.drawSurfaceBuffer = 0;
Mathias Agopianf13901e2009-07-15 18:53:32 -0700621 if (gl->copybits.blitEngine != NULL) {
622 if (supportedCopybitsDestinationFormat(buffer.format)) {
623 buffer_handle_t handle = this->buffer->handle;
624 if (handle != NULL) {
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700625 gl->copybits.drawSurfaceBuffer = handle;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700626 }
627 }
628 }
629#endif // LIBAGL_USE_GRALLOC_COPYBITS
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700630
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800631 return EGL_TRUE;
632}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700633EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800634{
635 GGLSurface buffer;
636 buffer.version = sizeof(GGLSurface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700637 buffer.width = this->buffer->width;
638 buffer.height = this->buffer->height;
639 buffer.stride = this->buffer->stride;
Mathias Agopiane71212b2009-05-05 00:37:46 -0700640 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700641 buffer.format = this->buffer->format;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800642 gl->rasterizer.procs.readBuffer(gl, &buffer);
643 return EGL_TRUE;
644}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700645EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800646 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
647}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700648EGLint egl_window_surface_v2_t::getVerticalResolution() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800649 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
650}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700651EGLint egl_window_surface_v2_t::getRefreshRate() const {
652 return (60 * EGL_DISPLAY_SCALING); // FIXME
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800653}
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700654EGLint egl_window_surface_v2_t::getSwapBehavior() const
655{
656 /*
657 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
658 * the content of the swapped buffer.
659 *
660 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
661 *
662 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
663 * only applies to the area specified by eglSetSwapRectangleANDROID(), that
664 * is, everything outside of this area is preserved.
665 *
666 * This implementation of EGL assumes the later case.
667 *
668 */
669
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700670 return EGL_BUFFER_DESTROYED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800671}
672
673// ----------------------------------------------------------------------------
674
675struct egl_pixmap_surface_t : public egl_surface_t
676{
677 egl_pixmap_surface_t(
678 EGLDisplay dpy, EGLConfig config,
679 int32_t depthFormat,
680 egl_native_pixmap_t const * pixmap);
681
682 virtual ~egl_pixmap_surface_t() { }
683
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700684 virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800685 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
686 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
687 virtual EGLint getWidth() const { return nativePixmap.width; }
688 virtual EGLint getHeight() const { return nativePixmap.height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800689private:
690 egl_native_pixmap_t nativePixmap;
691};
692
693egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
694 EGLConfig config,
695 int32_t depthFormat,
696 egl_native_pixmap_t const * pixmap)
697 : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
698{
699 if (depthFormat) {
700 depth.width = pixmap->width;
701 depth.height = pixmap->height;
702 depth.stride = depth.width; // use the width here
703 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
704 if (depth.data == 0) {
705 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
706 return;
707 }
708 }
709}
710EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl)
711{
712 GGLSurface buffer;
713 buffer.version = sizeof(GGLSurface);
714 buffer.width = nativePixmap.width;
715 buffer.height = nativePixmap.height;
716 buffer.stride = nativePixmap.stride;
717 buffer.data = nativePixmap.data;
718 buffer.format = nativePixmap.format;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700719
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720 gl->rasterizer.procs.colorBuffer(gl, &buffer);
721 if (depth.data != gl->rasterizer.state.buffers.depth.data)
722 gl->rasterizer.procs.depthBuffer(gl, &depth);
723 return EGL_TRUE;
724}
725EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl)
726{
727 GGLSurface buffer;
728 buffer.version = sizeof(GGLSurface);
729 buffer.width = nativePixmap.width;
730 buffer.height = nativePixmap.height;
731 buffer.stride = nativePixmap.stride;
732 buffer.data = nativePixmap.data;
733 buffer.format = nativePixmap.format;
734 gl->rasterizer.procs.readBuffer(gl, &buffer);
735 return EGL_TRUE;
736}
737
738// ----------------------------------------------------------------------------
739
740struct egl_pbuffer_surface_t : public egl_surface_t
741{
742 egl_pbuffer_surface_t(
743 EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
744 int32_t w, int32_t h, int32_t f);
745
746 virtual ~egl_pbuffer_surface_t();
747
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700748 virtual bool isValid() const { return pbuffer.data != 0; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800749 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
750 virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
751 virtual EGLint getWidth() const { return pbuffer.width; }
752 virtual EGLint getHeight() const { return pbuffer.height; }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800753private:
754 GGLSurface pbuffer;
755};
756
757egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
758 EGLConfig config, int32_t depthFormat,
759 int32_t w, int32_t h, int32_t f)
760 : egl_surface_t(dpy, config, depthFormat)
761{
762 size_t size = w*h;
763 switch (f) {
764 case GGL_PIXEL_FORMAT_A_8: size *= 1; break;
765 case GGL_PIXEL_FORMAT_RGB_565: size *= 2; break;
766 case GGL_PIXEL_FORMAT_RGBA_8888: size *= 4; break;
767 default:
768 LOGE("incompatible pixel format for pbuffer (format=%d)", f);
769 pbuffer.data = 0;
770 break;
771 }
772 pbuffer.version = sizeof(GGLSurface);
773 pbuffer.width = w;
774 pbuffer.height = h;
775 pbuffer.stride = w;
776 pbuffer.data = (GGLubyte*)malloc(size);
777 pbuffer.format = f;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700778
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800779 if (depthFormat) {
780 depth.width = pbuffer.width;
781 depth.height = pbuffer.height;
782 depth.stride = depth.width; // use the width here
783 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
784 if (depth.data == 0) {
785 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
786 return;
787 }
788 }
789}
790egl_pbuffer_surface_t::~egl_pbuffer_surface_t() {
791 free(pbuffer.data);
792}
793EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl)
794{
795 gl->rasterizer.procs.colorBuffer(gl, &pbuffer);
796 if (depth.data != gl->rasterizer.state.buffers.depth.data)
797 gl->rasterizer.procs.depthBuffer(gl, &depth);
798 return EGL_TRUE;
799}
800EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl)
801{
802 gl->rasterizer.procs.readBuffer(gl, &pbuffer);
803 return EGL_TRUE;
804}
805
806// ----------------------------------------------------------------------------
807
808struct config_pair_t {
809 GLint key;
810 GLint value;
811};
812
813struct configs_t {
814 const config_pair_t* array;
815 int size;
816};
817
818struct config_management_t {
819 GLint key;
820 bool (*match)(GLint reqValue, GLint confValue);
821 static bool atLeast(GLint reqValue, GLint confValue) {
822 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
823 }
824 static bool exact(GLint reqValue, GLint confValue) {
825 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
826 }
827 static bool mask(GLint reqValue, GLint confValue) {
828 return (confValue & reqValue) == reqValue;
829 }
830};
831
832// ----------------------------------------------------------------------------
833
834#define VERSION_MAJOR 1
835#define VERSION_MINOR 2
836static char const * const gVendorString = "Google Inc.";
837static char const * const gVersionString = "1.2 Android Driver";
838static char const * const gClientApiString = "OpenGL ES";
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700839static char const * const gExtensionsString =
Mathias Agopiane6bf8b32009-05-06 23:47:08 -0700840 "EGL_KHR_image_base "
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700841 // "KHR_image_pixmap "
842 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -0700843 "EGL_ANDROID_swap_rectangle "
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700844 "EGL_ANDROID_get_render_buffer "
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700845 ;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800846
847// ----------------------------------------------------------------------------
848
849struct extention_map_t {
850 const char * const name;
851 __eglMustCastToProperFunctionPointerType address;
852};
853
854static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700855 { "glDrawTexsOES",
856 (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
857 { "glDrawTexiOES",
858 (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
859 { "glDrawTexfOES",
860 (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
861 { "glDrawTexxOES",
862 (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
863 { "glDrawTexsvOES",
864 (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
865 { "glDrawTexivOES",
866 (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
867 { "glDrawTexfvOES",
868 (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
869 { "glDrawTexxvOES",
870 (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
871 { "glQueryMatrixxOES",
872 (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
873 { "glEGLImageTargetTexture2DOES",
874 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
875 { "glEGLImageTargetRenderbufferStorageOES",
876 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
877 { "glClipPlanef",
878 (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
879 { "glClipPlanex",
880 (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
881 { "glBindBuffer",
882 (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
883 { "glBufferData",
884 (__eglMustCastToProperFunctionPointerType)&glBufferData },
885 { "glBufferSubData",
886 (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
887 { "glDeleteBuffers",
888 (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
889 { "glGenBuffers",
890 (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700891 { "eglCreateImageKHR",
892 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
893 { "eglDestroyImageKHR",
894 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
895 { "eglSetSwapRectangleANDROID",
896 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
897 { "eglGetRenderBufferANDROID",
898 (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800899};
900
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700901/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800902 * In the lists below, attributes names MUST be sorted.
903 * Additionally, all configs must be sorted according to
904 * the EGL specification.
905 */
906
907static config_pair_t const config_base_attribute_list[] = {
908 { EGL_STENCIL_SIZE, 0 },
909 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
910 { EGL_LEVEL, 0 },
911 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700912 { EGL_MAX_PBUFFER_PIXELS,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800913 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
914 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
915 { EGL_NATIVE_RENDERABLE, EGL_TRUE },
916 { EGL_NATIVE_VISUAL_ID, 0 },
917 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGB_565 },
918 { EGL_SAMPLES, 0 },
919 { EGL_SAMPLE_BUFFERS, 0 },
920 { EGL_TRANSPARENT_TYPE, EGL_NONE },
921 { EGL_TRANSPARENT_BLUE_VALUE, 0 },
922 { EGL_TRANSPARENT_GREEN_VALUE, 0 },
923 { EGL_TRANSPARENT_RED_VALUE, 0 },
924 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
925 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
926 { EGL_MIN_SWAP_INTERVAL, 1 },
927 { EGL_MAX_SWAP_INTERVAL, 4 },
928};
929
930// These configs can override the base attribute list
931// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
932
933static config_pair_t const config_0_attribute_list[] = {
934 { EGL_BUFFER_SIZE, 16 },
935 { EGL_ALPHA_SIZE, 0 },
936 { EGL_BLUE_SIZE, 5 },
937 { EGL_GREEN_SIZE, 6 },
938 { EGL_RED_SIZE, 5 },
939 { EGL_DEPTH_SIZE, 0 },
940 { EGL_CONFIG_ID, 0 },
941 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
942};
943
944static config_pair_t const config_1_attribute_list[] = {
945 { EGL_BUFFER_SIZE, 16 },
946 { EGL_ALPHA_SIZE, 0 },
947 { EGL_BLUE_SIZE, 5 },
948 { EGL_GREEN_SIZE, 6 },
949 { EGL_RED_SIZE, 5 },
950 { EGL_DEPTH_SIZE, 16 },
951 { EGL_CONFIG_ID, 1 },
952 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
953};
954
955static config_pair_t const config_2_attribute_list[] = {
956 { EGL_BUFFER_SIZE, 32 },
957 { EGL_ALPHA_SIZE, 8 },
958 { EGL_BLUE_SIZE, 8 },
959 { EGL_GREEN_SIZE, 8 },
960 { EGL_RED_SIZE, 8 },
961 { EGL_DEPTH_SIZE, 0 },
962 { EGL_CONFIG_ID, 2 },
963 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
964};
965
966static config_pair_t const config_3_attribute_list[] = {
967 { 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_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
975};
976
977static config_pair_t const config_4_attribute_list[] = {
978 { EGL_BUFFER_SIZE, 8 },
979 { EGL_ALPHA_SIZE, 8 },
980 { EGL_BLUE_SIZE, 0 },
981 { EGL_GREEN_SIZE, 0 },
982 { EGL_RED_SIZE, 0 },
983 { EGL_DEPTH_SIZE, 0 },
984 { EGL_CONFIG_ID, 4 },
985 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
986};
987
988static config_pair_t const config_5_attribute_list[] = {
989 { EGL_BUFFER_SIZE, 8 },
990 { EGL_ALPHA_SIZE, 8 },
991 { EGL_BLUE_SIZE, 0 },
992 { EGL_GREEN_SIZE, 0 },
993 { EGL_RED_SIZE, 0 },
994 { EGL_DEPTH_SIZE, 16 },
995 { EGL_CONFIG_ID, 5 },
996 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
997};
998
999static configs_t const gConfigs[] = {
1000 { config_0_attribute_list, NELEM(config_0_attribute_list) },
1001 { config_1_attribute_list, NELEM(config_1_attribute_list) },
1002 { config_2_attribute_list, NELEM(config_2_attribute_list) },
1003 { config_3_attribute_list, NELEM(config_3_attribute_list) },
1004 { config_4_attribute_list, NELEM(config_4_attribute_list) },
1005 { config_5_attribute_list, NELEM(config_5_attribute_list) },
1006};
1007
1008static config_management_t const gConfigManagement[] = {
1009 { EGL_BUFFER_SIZE, config_management_t::atLeast },
1010 { EGL_ALPHA_SIZE, config_management_t::atLeast },
1011 { EGL_BLUE_SIZE, config_management_t::atLeast },
1012 { EGL_GREEN_SIZE, config_management_t::atLeast },
1013 { EGL_RED_SIZE, config_management_t::atLeast },
1014 { EGL_DEPTH_SIZE, config_management_t::atLeast },
1015 { EGL_STENCIL_SIZE, config_management_t::atLeast },
1016 { EGL_CONFIG_CAVEAT, config_management_t::exact },
1017 { EGL_CONFIG_ID, config_management_t::exact },
1018 { EGL_LEVEL, config_management_t::exact },
1019 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::exact },
1020 { EGL_MAX_PBUFFER_PIXELS, config_management_t::exact },
1021 { EGL_MAX_PBUFFER_WIDTH, config_management_t::exact },
1022 { EGL_NATIVE_RENDERABLE, config_management_t::exact },
1023 { EGL_NATIVE_VISUAL_ID, config_management_t::exact },
1024 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
1025 { EGL_SAMPLES, config_management_t::exact },
1026 { EGL_SAMPLE_BUFFERS, config_management_t::exact },
1027 { EGL_SURFACE_TYPE, config_management_t::mask },
1028 { EGL_TRANSPARENT_TYPE, config_management_t::exact },
1029 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
1030 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
1031 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
1032 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
1033 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
1034 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
1035 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
1036};
1037
1038static config_pair_t const config_defaults[] = {
1039 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
1040};
1041
1042// ----------------------------------------------------------------------------
1043
1044template<typename T>
1045static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
1046{
1047 while (first <= last) {
1048 int mid = (first + last) / 2;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001049 if (key > sortedArray[mid].key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001050 first = mid + 1;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001051 } else if (key < sortedArray[mid].key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001052 last = mid - 1;
1053 } else {
1054 return mid;
1055 }
1056 }
1057 return -1;
1058}
1059
1060static int isAttributeMatching(int i, EGLint attr, EGLint val)
1061{
1062 // look for the attribute in all of our configs
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001063 config_pair_t const* configFound = gConfigs[i].array;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001064 int index = binarySearch<config_pair_t>(
1065 gConfigs[i].array,
1066 0, gConfigs[i].size-1,
1067 attr);
1068 if (index < 0) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001069 configFound = config_base_attribute_list;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001070 index = binarySearch<config_pair_t>(
1071 config_base_attribute_list,
1072 0, NELEM(config_base_attribute_list)-1,
1073 attr);
1074 }
1075 if (index >= 0) {
1076 // attribute found, check if this config could match
1077 int cfgMgtIndex = binarySearch<config_management_t>(
1078 gConfigManagement,
1079 0, NELEM(gConfigManagement)-1,
1080 attr);
1081 if (index >= 0) {
1082 bool match = gConfigManagement[cfgMgtIndex].match(
1083 val, configFound[index].value);
1084 if (match) {
1085 // this config matches
1086 return 1;
1087 }
1088 } else {
1089 // attribute not found. this should NEVER happen.
1090 }
1091 } else {
1092 // error, this attribute doesn't exist
1093 }
1094 return 0;
1095}
1096
1097static int makeCurrent(ogles_context_t* gl)
1098{
1099 ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific();
1100 if (gl) {
1101 egl_context_t* c = egl_context_t::context(gl);
1102 if (c->flags & egl_context_t::IS_CURRENT) {
1103 if (current != gl) {
1104 // it is an error to set a context current, if it's already
1105 // current to another thread
1106 return -1;
1107 }
1108 } else {
1109 if (current) {
1110 // mark the current context as not current, and flush
1111 glFlush();
1112 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
1113 }
1114 }
1115 if (!(c->flags & egl_context_t::IS_CURRENT)) {
1116 // The context is not current, make it current!
1117 setGlThreadSpecific(gl);
1118 c->flags |= egl_context_t::IS_CURRENT;
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 // this thread has no context attached to it
1127 setGlThreadSpecific(0);
1128 }
1129 return 0;
1130}
1131
1132static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
1133 EGLint attribute, EGLint *value)
1134{
1135 size_t numConfigs = NELEM(gConfigs);
1136 int index = (int)config;
1137 if (uint32_t(index) >= numConfigs)
1138 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1139
1140 int attrIndex;
1141 attrIndex = binarySearch<config_pair_t>(
1142 gConfigs[index].array,
1143 0, gConfigs[index].size-1,
1144 attribute);
1145 if (attrIndex>=0) {
1146 *value = gConfigs[index].array[attrIndex].value;
1147 return EGL_TRUE;
1148 }
1149
1150 attrIndex = binarySearch<config_pair_t>(
1151 config_base_attribute_list,
1152 0, NELEM(config_base_attribute_list)-1,
1153 attribute);
1154 if (attrIndex>=0) {
1155 *value = config_base_attribute_list[attrIndex].value;
1156 return EGL_TRUE;
1157 }
1158 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1159}
1160
1161static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
1162 NativeWindowType window, const EGLint *attrib_list)
1163{
1164 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1165 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1166 if (window == 0)
1167 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1168
1169 EGLint surfaceType;
1170 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1171 return EGL_FALSE;
1172
1173 if (!(surfaceType & EGL_WINDOW_BIT))
1174 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1175
1176 EGLint configID;
1177 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1178 return EGL_FALSE;
1179
1180 int32_t depthFormat;
1181 int32_t pixelFormat;
1182 switch(configID) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001183 case 0:
1184 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001185 depthFormat = 0;
1186 break;
1187 case 1:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001188 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001189 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1190 break;
1191 case 2:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001192 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001193 depthFormat = 0;
1194 break;
1195 case 3:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001196 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001197 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1198 break;
1199 case 4:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001200 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001201 depthFormat = 0;
1202 break;
1203 case 5:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001204 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001205 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1206 break;
1207 default:
1208 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1209 }
1210
1211 // FIXME: we don't have access to the pixelFormat here just yet.
1212 // (it's possible that the surface is not fully initialized)
1213 // maybe this should be done after the page-flip
1214 //if (EGLint(info.format) != pixelFormat)
1215 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1216
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001217 egl_surface_t* surface;
1218 surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
1219 static_cast<android_native_window_t*>(window));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001220
1221 if (!surface->isValid()) {
1222 // there was a problem in the ctor, the error
1223 // flag has been set.
1224 delete surface;
1225 surface = 0;
1226 }
1227 return surface;
1228}
1229
1230static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
1231 NativePixmapType pixmap, const EGLint *attrib_list)
1232{
1233 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1234 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1235 if (pixmap == 0)
1236 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1237
1238 EGLint surfaceType;
1239 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1240 return EGL_FALSE;
1241
1242 if (!(surfaceType & EGL_PIXMAP_BIT))
1243 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1244
1245 EGLint configID;
1246 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1247 return EGL_FALSE;
1248
1249 int32_t depthFormat;
1250 int32_t pixelFormat;
1251 switch(configID) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001252 case 0:
1253 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001254 depthFormat = 0;
1255 break;
1256 case 1:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001257 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001258 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1259 break;
1260 case 2:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001261 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001262 depthFormat = 0;
1263 break;
1264 case 3:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001265 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001266 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1267 break;
1268 case 4:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001269 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001270 depthFormat = 0;
1271 break;
1272 case 5:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001273 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001274 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1275 break;
1276 default:
1277 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1278 }
1279
1280 if (pixmap->format != pixelFormat)
1281 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1282
1283 egl_surface_t* surface =
1284 new egl_pixmap_surface_t(dpy, config, depthFormat,
1285 static_cast<egl_native_pixmap_t*>(pixmap));
1286
1287 if (!surface->isValid()) {
1288 // there was a problem in the ctor, the error
1289 // flag has been set.
1290 delete surface;
1291 surface = 0;
1292 }
1293 return surface;
1294}
1295
1296static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
1297 const EGLint *attrib_list)
1298{
1299 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1300 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1301
1302 EGLint surfaceType;
1303 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
1304 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001305
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001306 if (!(surfaceType & EGL_PBUFFER_BIT))
1307 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001308
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001309 EGLint configID;
1310 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
1311 return EGL_FALSE;
1312
1313 int32_t depthFormat;
1314 int32_t pixelFormat;
1315 switch(configID) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001316 case 0:
1317 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001318 depthFormat = 0;
1319 break;
1320 case 1:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001321 pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001322 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1323 break;
1324 case 2:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001325 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001326 depthFormat = 0;
1327 break;
1328 case 3:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001329 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001330 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1331 break;
1332 case 4:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001333 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001334 depthFormat = 0;
1335 break;
1336 case 5:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001337 pixelFormat = GGL_PIXEL_FORMAT_A_8;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001338 depthFormat = GGL_PIXEL_FORMAT_Z_16;
1339 break;
1340 default:
1341 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
1342 }
1343
1344 int32_t w = 0;
1345 int32_t h = 0;
1346 while (attrib_list[0]) {
1347 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
1348 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
1349 attrib_list+=2;
1350 }
1351
1352 egl_surface_t* surface =
1353 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
1354
1355 if (!surface->isValid()) {
1356 // there was a problem in the ctor, the error
1357 // flag has been set.
1358 delete surface;
1359 surface = 0;
1360 }
1361 return surface;
1362}
1363
1364// ----------------------------------------------------------------------------
1365}; // namespace android
1366// ----------------------------------------------------------------------------
1367
1368using namespace android;
1369
1370// ----------------------------------------------------------------------------
1371// Initialization
1372// ----------------------------------------------------------------------------
1373
1374EGLDisplay eglGetDisplay(NativeDisplayType display)
1375{
1376#ifndef HAVE_ANDROID_OS
1377 // this just needs to be done once
1378 if (gGLKey == -1) {
1379 pthread_mutex_lock(&gInitMutex);
1380 if (gGLKey == -1)
1381 pthread_key_create(&gGLKey, NULL);
1382 pthread_mutex_unlock(&gInitMutex);
1383 }
1384#endif
1385 if (display == EGL_DEFAULT_DISPLAY) {
1386 EGLDisplay dpy = (EGLDisplay)1;
1387 egl_display_t& d = egl_display_t::get_display(dpy);
1388 d.type = display;
1389 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001390 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001391 return EGL_NO_DISPLAY;
1392}
1393
1394EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
1395{
1396 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1397 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001398
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001399 EGLBoolean res = EGL_TRUE;
1400 egl_display_t& d = egl_display_t::get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001401
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001402 if (android_atomic_inc(&d.initialized) == 0) {
1403 // initialize stuff here if needed
1404 //pthread_mutex_lock(&gInitMutex);
1405 //pthread_mutex_unlock(&gInitMutex);
1406 }
1407
1408 if (res == EGL_TRUE) {
1409 if (major != NULL) *major = VERSION_MAJOR;
1410 if (minor != NULL) *minor = VERSION_MINOR;
1411 }
1412 return res;
1413}
1414
1415EGLBoolean eglTerminate(EGLDisplay dpy)
1416{
1417 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1418 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1419
1420 EGLBoolean res = EGL_TRUE;
1421 egl_display_t& d = egl_display_t::get_display(dpy);
1422 if (android_atomic_dec(&d.initialized) == 1) {
1423 // TODO: destroy all resources (surfaces, contexts, etc...)
1424 //pthread_mutex_lock(&gInitMutex);
1425 //pthread_mutex_unlock(&gInitMutex);
1426 }
1427 return res;
1428}
1429
1430// ----------------------------------------------------------------------------
1431// configuration
1432// ----------------------------------------------------------------------------
1433
1434EGLBoolean eglGetConfigs( EGLDisplay dpy,
1435 EGLConfig *configs,
1436 EGLint config_size, EGLint *num_config)
1437{
1438 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1439 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1440
1441 GLint numConfigs = NELEM(gConfigs);
1442 if (!configs) {
1443 *num_config = numConfigs;
1444 return EGL_TRUE;
1445 }
1446 GLint i;
1447 for (i=0 ; i<numConfigs && i<config_size ; i++) {
1448 *configs++ = (EGLConfig)i;
1449 }
1450 *num_config = i;
1451 return EGL_TRUE;
1452}
1453
1454EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
1455 EGLConfig *configs, EGLint config_size,
1456 EGLint *num_config)
1457{
1458 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1459 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Jack Palevich749c63d2009-03-25 15:12:17 -07001460
1461 if (ggl_unlikely(num_config==0)) {
1462 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1463 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001464
Jack Palevich749c63d2009-03-25 15:12:17 -07001465 if (ggl_unlikely(attrib_list==0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001466 *num_config = 0;
1467 return EGL_TRUE;
1468 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001469
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001470 int numAttributes = 0;
1471 int numConfigs = NELEM(gConfigs);
1472 uint32_t possibleMatch = (1<<numConfigs)-1;
1473 while(possibleMatch && *attrib_list != EGL_NONE) {
1474 numAttributes++;
1475 EGLint attr = *attrib_list++;
1476 EGLint val = *attrib_list++;
1477 for (int i=0 ; i<numConfigs ; i++) {
1478 if (!(possibleMatch & (1<<i)))
1479 continue;
1480 if (isAttributeMatching(i, attr, val) == 0) {
1481 possibleMatch &= ~(1<<i);
1482 }
1483 }
1484 }
1485
1486 // now, handle the attributes which have a useful default value
1487 for (size_t j=0 ; j<NELEM(config_defaults) ; j++) {
1488 // see if this attribute was specified, if not apply its
1489 // default value
1490 if (binarySearch<config_pair_t>(
1491 (config_pair_t const*)attrib_list,
Mathias Agopiandacd7a32009-07-09 17:33:15 -07001492 0, numAttributes-1,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001493 config_defaults[j].key) < 0)
1494 {
1495 for (int i=0 ; i<numConfigs ; i++) {
1496 if (!(possibleMatch & (1<<i)))
1497 continue;
1498 if (isAttributeMatching(i,
1499 config_defaults[j].key,
1500 config_defaults[j].value) == 0)
1501 {
1502 possibleMatch &= ~(1<<i);
1503 }
1504 }
1505 }
1506 }
1507
1508 // return the configurations found
1509 int n=0;
1510 if (possibleMatch) {
Jack Palevich749c63d2009-03-25 15:12:17 -07001511 if (configs) {
1512 for (int i=0 ; config_size && i<numConfigs ; i++) {
1513 if (possibleMatch & (1<<i)) {
1514 *configs++ = (EGLConfig)i;
1515 config_size--;
1516 n++;
1517 }
1518 }
1519 } else {
1520 for (int i=0 ; i<numConfigs ; i++) {
1521 if (possibleMatch & (1<<i)) {
1522 n++;
1523 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001524 }
1525 }
1526 }
1527 *num_config = n;
1528 return EGL_TRUE;
1529}
1530
1531EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
1532 EGLint attribute, EGLint *value)
1533{
1534 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1535 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1536
1537 return getConfigAttrib(dpy, config, attribute, value);
1538}
1539
1540// ----------------------------------------------------------------------------
1541// surfaces
1542// ----------------------------------------------------------------------------
1543
1544EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
1545 NativeWindowType window,
1546 const EGLint *attrib_list)
1547{
1548 return createWindowSurface(dpy, config, window, attrib_list);
1549}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001550
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001551EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1552 NativePixmapType pixmap,
1553 const EGLint *attrib_list)
1554{
1555 return createPixmapSurface(dpy, config, pixmap, attrib_list);
1556}
1557
1558EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1559 const EGLint *attrib_list)
1560{
1561 return createPbufferSurface(dpy, config, attrib_list);
1562}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001563
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001564EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
1565{
1566 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1567 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1568 if (eglSurface != EGL_NO_SURFACE) {
1569 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
1570 if (surface->magic != egl_surface_t::MAGIC)
1571 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1572 if (surface->dpy != dpy)
1573 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopiane71212b2009-05-05 00:37:46 -07001574 if (surface->ctx) {
1575 // FIXME: this surface is current check what the spec says
1576 surface->disconnect();
1577 surface->ctx = 0;
1578 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001579 delete surface;
1580 }
1581 return EGL_TRUE;
1582}
1583
1584EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
1585 EGLint attribute, EGLint *value)
1586{
1587 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1588 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1589 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
1590 if (surface->dpy != dpy)
1591 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1592
1593 EGLBoolean ret = EGL_TRUE;
1594 switch (attribute) {
1595 case EGL_CONFIG_ID:
1596 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
1597 break;
1598 case EGL_WIDTH:
1599 *value = surface->getWidth();
1600 break;
1601 case EGL_HEIGHT:
1602 *value = surface->getHeight();
1603 break;
1604 case EGL_LARGEST_PBUFFER:
1605 // not modified for a window or pixmap surface
1606 break;
1607 case EGL_TEXTURE_FORMAT:
1608 *value = EGL_NO_TEXTURE;
1609 break;
1610 case EGL_TEXTURE_TARGET:
1611 *value = EGL_NO_TEXTURE;
1612 break;
1613 case EGL_MIPMAP_TEXTURE:
1614 *value = EGL_FALSE;
1615 break;
1616 case EGL_MIPMAP_LEVEL:
1617 *value = 0;
1618 break;
1619 case EGL_RENDER_BUFFER:
1620 // TODO: return the real RENDER_BUFFER here
1621 *value = EGL_BACK_BUFFER;
1622 break;
1623 case EGL_HORIZONTAL_RESOLUTION:
1624 // pixel/mm * EGL_DISPLAY_SCALING
1625 *value = surface->getHorizontalResolution();
1626 break;
1627 case EGL_VERTICAL_RESOLUTION:
1628 // pixel/mm * EGL_DISPLAY_SCALING
1629 *value = surface->getVerticalResolution();
1630 break;
1631 case EGL_PIXEL_ASPECT_RATIO: {
1632 // w/h * EGL_DISPLAY_SCALING
1633 int wr = surface->getHorizontalResolution();
1634 int hr = surface->getVerticalResolution();
1635 *value = (wr * EGL_DISPLAY_SCALING) / hr;
1636 } break;
1637 case EGL_SWAP_BEHAVIOR:
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001638 *value = surface->getSwapBehavior();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001639 break;
1640 default:
1641 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1642 }
1643 return ret;
1644}
1645
1646EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1647 EGLContext share_list, const EGLint *attrib_list)
1648{
1649 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1650 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1651
1652 ogles_context_t* gl = ogles_init(sizeof(egl_context_t));
1653 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
1654
1655 egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
1656 c->flags = egl_context_t::NEVER_CURRENT;
1657 c->dpy = dpy;
1658 c->config = config;
1659 c->read = 0;
1660 c->draw = 0;
1661 return (EGLContext)gl;
1662}
1663
1664EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1665{
1666 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1667 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1668 egl_context_t* c = egl_context_t::context(ctx);
1669 if (c->flags & egl_context_t::IS_CURRENT)
1670 setGlThreadSpecific(0);
1671 ogles_uninit((ogles_context_t*)ctx);
1672 return EGL_TRUE;
1673}
1674
1675EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1676 EGLSurface read, EGLContext ctx)
1677{
1678 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1679 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1680 if (draw) {
1681 egl_surface_t* s = (egl_surface_t*)draw;
1682 if (s->dpy != dpy)
1683 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1684 // TODO: check that draw and read are compatible with the context
1685 }
1686
1687 EGLContext current_ctx = EGL_NO_CONTEXT;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001688
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001689 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
1690 return setError(EGL_BAD_MATCH, EGL_FALSE);
1691
1692 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
1693 return setError(EGL_BAD_MATCH, EGL_FALSE);
1694
1695 if (ctx == EGL_NO_CONTEXT) {
1696 // if we're detaching, we need the current context
1697 current_ctx = (EGLContext)getGlThreadSpecific();
1698 } else {
1699 egl_context_t* c = egl_context_t::context(ctx);
1700 egl_surface_t* d = (egl_surface_t*)draw;
1701 egl_surface_t* r = (egl_surface_t*)read;
1702 if ((d && d->ctx && d->ctx != ctx) ||
1703 (r && r->ctx && r->ctx != ctx)) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001704 // one of the surface is bound to a context in another thread
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001705 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1706 }
1707 }
1708
1709 ogles_context_t* gl = (ogles_context_t*)ctx;
1710 if (makeCurrent(gl) == 0) {
1711 if (ctx) {
1712 egl_context_t* c = egl_context_t::context(ctx);
1713 egl_surface_t* d = (egl_surface_t*)draw;
1714 egl_surface_t* r = (egl_surface_t*)read;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001715
1716 if (c->draw) {
1717 reinterpret_cast<egl_surface_t*>(c->draw)->disconnect();
1718 }
1719 if (c->read) {
1720 // FIXME: unlock/disconnect the read surface too
1721 }
1722
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001723 c->draw = draw;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001724 c->read = read;
1725
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001726 if (c->flags & egl_context_t::NEVER_CURRENT) {
1727 c->flags &= ~egl_context_t::NEVER_CURRENT;
1728 GLint w = 0;
1729 GLint h = 0;
1730 if (draw) {
1731 w = d->getWidth();
1732 h = d->getHeight();
1733 }
1734 ogles_surfaceport(gl, 0, 0);
1735 ogles_viewport(gl, 0, 0, w, h);
1736 ogles_scissor(gl, 0, 0, w, h);
1737 }
1738 if (d) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001739 d->connect();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001740 d->ctx = ctx;
1741 d->bindDrawSurface(gl);
1742 }
1743 if (r) {
Mathias Agopiane71212b2009-05-05 00:37:46 -07001744 // FIXME: lock/connect the read surface too
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001745 r->ctx = ctx;
1746 r->bindReadSurface(gl);
1747 }
1748 } else {
1749 // if surfaces were bound to the context bound to this thread
1750 // mark then as unbound.
1751 if (current_ctx) {
1752 egl_context_t* c = egl_context_t::context(current_ctx);
1753 egl_surface_t* d = (egl_surface_t*)c->draw;
1754 egl_surface_t* r = (egl_surface_t*)c->read;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001755 if (d) {
Mathias Agopian9648c1a2009-06-03 19:00:53 -07001756 c->draw = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001757 d->ctx = EGL_NO_CONTEXT;
1758 d->disconnect();
1759 }
1760 if (r) {
Mathias Agopian9648c1a2009-06-03 19:00:53 -07001761 c->read = 0;
Mathias Agopiane71212b2009-05-05 00:37:46 -07001762 r->ctx = EGL_NO_CONTEXT;
1763 // FIXME: unlock/disconnect the read surface too
1764 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001765 }
1766 }
1767 return EGL_TRUE;
1768 }
1769 return setError(EGL_BAD_ACCESS, EGL_FALSE);
1770}
1771
1772EGLContext eglGetCurrentContext(void)
1773{
1774 // eglGetCurrentContext returns the current EGL rendering context,
1775 // as specified by eglMakeCurrent. If no context is current,
1776 // EGL_NO_CONTEXT is returned.
1777 return (EGLContext)getGlThreadSpecific();
1778}
1779
1780EGLSurface eglGetCurrentSurface(EGLint readdraw)
1781{
1782 // eglGetCurrentSurface returns the read or draw surface attached
1783 // to the current EGL rendering context, as specified by eglMakeCurrent.
1784 // If no context is current, EGL_NO_SURFACE is returned.
1785 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1786 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
1787 egl_context_t* c = egl_context_t::context(ctx);
1788 if (readdraw == EGL_READ) {
1789 return c->read;
1790 } else if (readdraw == EGL_DRAW) {
1791 return c->draw;
1792 }
1793 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
1794}
1795
1796EGLDisplay eglGetCurrentDisplay(void)
1797{
1798 // eglGetCurrentDisplay returns the current EGL display connection
1799 // for the current EGL rendering context, as specified by eglMakeCurrent.
1800 // If no context is current, EGL_NO_DISPLAY is returned.
1801 EGLContext ctx = (EGLContext)getGlThreadSpecific();
1802 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
1803 egl_context_t* c = egl_context_t::context(ctx);
1804 return c->dpy;
1805}
1806
1807EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1808 EGLint attribute, EGLint *value)
1809{
1810 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1811 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1812 egl_context_t* c = egl_context_t::context(ctx);
1813 switch (attribute) {
1814 case EGL_CONFIG_ID:
1815 // Returns the ID of the EGL frame buffer configuration with
1816 // respect to which the context was created
1817 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
1818 }
1819 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1820}
1821
1822EGLBoolean eglWaitGL(void)
1823{
1824 return EGL_TRUE;
1825}
1826
1827EGLBoolean eglWaitNative(EGLint engine)
1828{
1829 return EGL_TRUE;
1830}
1831
1832EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1833{
1834 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1835 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001836
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001837 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
1838 if (d->dpy != dpy)
1839 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1840
1841 // post the surface
1842 d->swapBuffers();
1843
1844 // if it's bound to a context, update the buffer
1845 if (d->ctx != EGL_NO_CONTEXT) {
1846 d->bindDrawSurface((ogles_context_t*)d->ctx);
1847 // if this surface is also the read surface of the context
1848 // it is bound to, make sure to update the read buffer as well.
1849 // The EGL spec is a little unclear about this.
1850 egl_context_t* c = egl_context_t::context(d->ctx);
1851 if (c->read == draw) {
1852 d->bindReadSurface((ogles_context_t*)d->ctx);
1853 }
1854 }
1855
1856 return EGL_TRUE;
1857}
1858
1859EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1860 NativePixmapType target)
1861{
1862 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1863 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1864 // TODO: eglCopyBuffers()
1865 return EGL_FALSE;
1866}
1867
1868EGLint eglGetError(void)
1869{
1870 return getError();
1871}
1872
1873const char* eglQueryString(EGLDisplay dpy, EGLint name)
1874{
1875 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1876 return setError(EGL_BAD_DISPLAY, (const char*)0);
1877
1878 switch (name) {
1879 case EGL_VENDOR:
1880 return gVendorString;
1881 case EGL_VERSION:
1882 return gVersionString;
1883 case EGL_EXTENSIONS:
1884 return gExtensionsString;
1885 case EGL_CLIENT_APIS:
1886 return gClientApiString;
1887 }
1888 return setError(EGL_BAD_PARAMETER, (const char *)0);
1889}
1890
1891// ----------------------------------------------------------------------------
1892// EGL 1.1
1893// ----------------------------------------------------------------------------
1894
1895EGLBoolean eglSurfaceAttrib(
1896 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1897{
1898 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1899 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1900 // TODO: eglSurfaceAttrib()
1901 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1902}
1903
1904EGLBoolean eglBindTexImage(
1905 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1906{
1907 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1908 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1909 // TODO: eglBindTexImage()
1910 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1911}
1912
1913EGLBoolean eglReleaseTexImage(
1914 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1915{
1916 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1917 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1918 // TODO: eglReleaseTexImage()
1919 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1920}
1921
1922EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1923{
1924 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1925 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1926 // TODO: eglSwapInterval()
1927 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1928}
1929
1930// ----------------------------------------------------------------------------
1931// EGL 1.2
1932// ----------------------------------------------------------------------------
1933
1934EGLBoolean eglBindAPI(EGLenum api)
1935{
1936 if (api != EGL_OPENGL_ES_API)
1937 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1938 return EGL_TRUE;
1939}
1940
1941EGLenum eglQueryAPI(void)
1942{
1943 return EGL_OPENGL_ES_API;
1944}
1945
1946EGLBoolean eglWaitClient(void)
1947{
1948 glFinish();
1949 return EGL_TRUE;
1950}
1951
1952EGLBoolean eglReleaseThread(void)
1953{
1954 // TODO: eglReleaseThread()
1955 return EGL_TRUE;
1956}
1957
1958EGLSurface eglCreatePbufferFromClientBuffer(
1959 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1960 EGLConfig config, const EGLint *attrib_list)
1961{
1962 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
1963 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
1964 // TODO: eglCreatePbufferFromClientBuffer()
1965 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1966}
1967
1968// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001969// EGL_EGLEXT_VERSION 3
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001970// ----------------------------------------------------------------------------
1971
1972void (*eglGetProcAddress (const char *procname))()
1973{
1974 extention_map_t const * const map = gExtentionMap;
1975 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
1976 if (!strcmp(procname, map[i].name)) {
1977 return map[i].address;
1978 }
1979 }
1980 return NULL;
1981}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001982
1983EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1984 const EGLint *attrib_list)
1985{
1986 EGLBoolean result = EGL_FALSE;
1987 return result;
1988}
1989
1990EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1991{
1992 EGLBoolean result = EGL_FALSE;
1993 return result;
1994}
1995
1996EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1997 EGLClientBuffer buffer, const EGLint *attrib_list)
1998{
1999 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2000 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
2001 }
2002 if (ctx != EGL_NO_CONTEXT) {
2003 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
2004 }
2005 if (target != EGL_NATIVE_BUFFER_ANDROID) {
2006 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2007 }
2008
2009 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
2010
2011 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2012 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
2013
2014 if (native_buffer->common.version != sizeof(android_native_buffer_t))
2015 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
Mathias Agopian8b765b72009-04-10 20:34:46 -07002016
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002017 native_buffer->common.incRef(&native_buffer->common);
2018 return (EGLImageKHR)native_buffer;
2019}
2020
2021EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2022{
2023 if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
2024 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2025 }
2026
2027 android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
2028
2029 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
2030 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2031
2032 if (native_buffer->common.version != sizeof(android_native_buffer_t))
2033 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2034
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002035 native_buffer->common.decRef(&native_buffer->common);
2036
2037 return EGL_TRUE;
2038}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002039
2040// ----------------------------------------------------------------------------
2041// ANDROID extensions
2042// ----------------------------------------------------------------------------
2043
2044EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2045 EGLint left, EGLint top, EGLint width, EGLint height)
2046{
2047 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2048 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2049
2050 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
2051 if (d->dpy != dpy)
2052 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2053
2054 // post the surface
2055 d->setSwapRectangle(left, top, width, height);
2056
2057 return EGL_TRUE;
2058}
Mathias Agopian8d2e83b2009-06-24 22:37:39 -07002059
2060EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
2061{
2062 if (egl_display_t::is_valid(dpy) == EGL_FALSE)
2063 return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
2064
2065 egl_surface_t* d = static_cast<egl_surface_t*>(draw);
2066 if (d->dpy != dpy)
2067 return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
2068
2069 // post the surface
2070 return d->getRenderBuffer();
2071}