egl.cpp revision f13901eaa98241b52062a3ae3b016badce3dee0c
1/* 2** 3** Copyright 2007 The Android Open Source Project 4** 5** Licensed under the Apache License Version 2.0(the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing software 12** distributed under the License is distributed on an "AS IS" BASIS 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#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 42#include <private/ui/android_natives_priv.h> 43 44#include <hardware/copybit.h> 45 46#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) { } 94 95 static egl_display_t& get_display(EGLDisplay dpy); 96 97 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; 145 146 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; 147 virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; 148 virtual void connect() {} 149 virtual void disconnect() {} 150 virtual EGLint getWidth() const = 0; 151 virtual EGLint getHeight() const = 0; 152 153 virtual EGLint getHorizontalResolution() const; 154 virtual EGLint getVerticalResolution() const; 155 virtual EGLint getRefreshRate() const; 156 virtual EGLint getSwapBehavior() const; 157 virtual EGLBoolean swapBuffers(); 158 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); 159 virtual EGLClientBuffer getRenderBuffer() const; 160protected: 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} 193EGLBoolean egl_surface_t::setSwapRectangle( 194 EGLint l, EGLint t, EGLint w, EGLint h) 195{ 196 return EGL_FALSE; 197} 198EGLClientBuffer egl_surface_t::getRenderBuffer() const { 199 return 0; 200} 201 202// ---------------------------------------------------------------------------- 203 204struct egl_window_surface_v2_t : public egl_surface_t 205{ 206 egl_window_surface_v2_t( 207 EGLDisplay dpy, EGLConfig config, 208 int32_t depthFormat, 209 android_native_window_t* window); 210 211 ~egl_window_surface_v2_t(); 212 213 virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; } 214 virtual EGLBoolean swapBuffers(); 215 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 216 virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 217 virtual void connect(); 218 virtual void disconnect(); 219 virtual EGLint getWidth() const { return buffer->width; } 220 virtual EGLint getHeight() const { return buffer->height; } 221 virtual EGLint getHorizontalResolution() const; 222 virtual EGLint getVerticalResolution() const; 223 virtual EGLint getRefreshRate() const; 224 virtual EGLint getSwapBehavior() const; 225 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); 226 virtual EGLClientBuffer getRenderBuffer() const; 227 228private: 229 status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); 230 status_t unlock(android_native_buffer_t* buf); 231 android_native_window_t* nativeWindow; 232 android_native_buffer_t* buffer; 233 android_native_buffer_t* previousBuffer; 234 gralloc_module_t const* module; 235 copybit_device_t* blitengine; 236 int width; 237 int height; 238 void* bits; 239 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) { } 270 typedef Rect const* const_iterator; 271 const_iterator begin() const { return storage; } 272 const_iterator end() const { return storage+count; } 273 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; 281 storage->bottom = rhs.top; 282 storage++; 283 } 284 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 } 301 } 302 if (lhs.bottom > rhs.bottom) { // bottom rect 303 storage->left = lhs.left; 304 storage->top = rhs.bottom; 305 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 } 316 private: 317 Rect storage[4]; 318 ssize_t count; 319 }; 320 321 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 339 void copyBlt( 340 android_native_buffer_t* dst, void* dst_vaddr, 341 android_native_buffer_t* src, void const* src_vaddr, 342 const Region& clip); 343 344 Rect dirtyRegion; 345 Rect oldDirtyRegion; 346}; 347 348egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, 349 EGLConfig config, 350 int32_t depthFormat, 351 android_native_window_t* window) 352 : egl_surface_t(dpy, config, depthFormat), 353 nativeWindow(window), buffer(0), previousBuffer(0), module(0), 354 blitengine(0), bits(NULL) 355{ 356 hw_module_t const* pModule; 357 hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); 358 module = reinterpret_cast<gralloc_module_t const*>(pModule); 359 360 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) { 361 copybit_open(pModule, &blitengine); 362 } 363 364 pixelFormatTable = gglGetPixelFormatTable(); 365 366 // keep a reference on the window 367 nativeWindow->common.incRef(&nativeWindow->common); 368 369 // dequeue a buffer 370 nativeWindow->dequeueBuffer(nativeWindow, &buffer); 371 372 // allocate a corresponding depth-buffer 373 width = buffer->width; 374 height = buffer->height; 375 if (depthFormat) { 376 depth.width = width; 377 depth.height = height; 378 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 } 385 386 // keep a reference on the buffer 387 buffer->common.incRef(&buffer->common); 388} 389 390egl_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); 398 if (blitengine) { 399 copybit_close(blitengine); 400 } 401} 402 403void egl_window_surface_v2_t::connect() 404{ 405 // Lock the buffer 406 nativeWindow->lockBuffer(nativeWindow, buffer); 407 // pin the buffer down 408 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 409 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { 410 LOGE("connect() failed to lock buffer %p (%ux%u)", 411 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 } 415} 416 417void egl_window_surface_v2_t::disconnect() 418{ 419 if (buffer && bits) { 420 bits = NULL; 421 unlock(buffer); 422 } 423} 424 425status_t egl_window_surface_v2_t::lock( 426 android_native_buffer_t* buf, int usage, void** vaddr) 427{ 428 int err = module->lock(module, buf->handle, 429 usage, 0, 0, buf->width, buf->height, vaddr); 430 return err; 431} 432 433status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) 434{ 435 int err = module->unlock(module, buf->handle); 436 return err; 437} 438 439void 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, 442 const Region& clip) 443{ 444 // FIXME: use copybit if possible 445 // NOTE: dst and src must be the same format 446 447 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); 455 456 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)); 469 } 470 } 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 } 501 } 502} 503 504EGLBoolean egl_window_surface_v2_t::swapBuffers() 505{ 506 /* 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()) { 515 void* prevBits; 516 if (lock(previousBuffer, 517 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) { 518 // copy from previousBuffer to buffer 519 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack); 520 unlock(previousBuffer); 521 } 522 } 523 } 524 oldDirtyRegion = dirtyRegion; 525 } 526 527 if (previousBuffer) { 528 previousBuffer->common.decRef(&previousBuffer->common); 529 previousBuffer = 0; 530 } 531 532 unlock(buffer); 533 previousBuffer = buffer; 534 nativeWindow->queueBuffer(nativeWindow, buffer); 535 buffer = 0; 536 537 // dequeue a new buffer 538 nativeWindow->dequeueBuffer(nativeWindow, &buffer); 539 540 // TODO: lockBuffer should rather be executed when the very first 541 // direct rendering occurs. 542 nativeWindow->lockBuffer(nativeWindow, buffer); 543 544 // reallocate the depth-buffer if needed 545 if ((width != buffer->width) || (height != buffer->height)) { 546 // TODO: we probably should reset the swap rect here 547 // if the window size has changed 548 width = buffer->width; 549 height = buffer->height; 550 if (depth.data) { 551 free(depth.data); 552 depth.width = width; 553 depth.height = height; 554 depth.stride = buffer->stride; 555 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 556 if (depth.data == 0) { 557 setError(EGL_BAD_ALLOC, EGL_FALSE); 558 return EGL_FALSE; 559 } 560 } 561 } 562 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); 582 return EGL_TRUE; 583} 584 585EGLClientBuffer egl_window_surface_v2_t::getRenderBuffer() const 586{ 587 return buffer; 588} 589 590#ifdef LIBAGL_USE_GRALLOC_COPYBITS 591 592static bool supportedCopybitsDestinationFormat(int format) { 593 // Hardware supported 594 switch (format) { 595 case HAL_PIXEL_FORMAT_RGB_565: 596 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: 600 return true; 601 } 602 return false; 603} 604#endif 605 606EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) 607{ 608 GGLSurface buffer; 609 buffer.version = sizeof(GGLSurface); 610 buffer.width = this->buffer->width; 611 buffer.height = this->buffer->height; 612 buffer.stride = this->buffer->stride; 613 buffer.data = (GGLubyte*)bits; 614 buffer.format = this->buffer->format; 615 gl->rasterizer.procs.colorBuffer(gl, &buffer); 616 if (depth.data != gl->rasterizer.state.buffers.depth.data) 617 gl->rasterizer.procs.depthBuffer(gl, &depth); 618 619#ifdef LIBAGL_USE_GRALLOC_COPYBITS 620 gl->copybits.drawSurfaceBuffer = 0; 621 if (gl->copybits.blitEngine != NULL) { 622 if (supportedCopybitsDestinationFormat(buffer.format)) { 623 buffer_handle_t handle = this->buffer->handle; 624 if (handle != NULL) { 625 gl->copybits.drawSurfaceBuffer = handle; 626 } 627 } 628 } 629#endif // LIBAGL_USE_GRALLOC_COPYBITS 630 631 return EGL_TRUE; 632} 633EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) 634{ 635 GGLSurface buffer; 636 buffer.version = sizeof(GGLSurface); 637 buffer.width = this->buffer->width; 638 buffer.height = this->buffer->height; 639 buffer.stride = this->buffer->stride; 640 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! 641 buffer.format = this->buffer->format; 642 gl->rasterizer.procs.readBuffer(gl, &buffer); 643 return EGL_TRUE; 644} 645EGLint egl_window_surface_v2_t::getHorizontalResolution() const { 646 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 647} 648EGLint egl_window_surface_v2_t::getVerticalResolution() const { 649 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 650} 651EGLint egl_window_surface_v2_t::getRefreshRate() const { 652 return (60 * EGL_DISPLAY_SCALING); // FIXME 653} 654EGLint 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 670 return EGL_BUFFER_DESTROYED; 671} 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 684 virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } 685 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; } 689private: 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; 719 720 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 748 virtual bool isValid() const { return pbuffer.data != 0; } 749 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; } 753private: 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; 778 779 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"; 839static char const * const gExtensionsString = 840 "EGL_KHR_image_base " 841 // "KHR_image_pixmap " 842 "EGL_ANDROID_image_native_buffer " 843 "EGL_ANDROID_swap_rectangle " 844 "EGL_ANDROID_get_render_buffer " 845 ; 846 847// ---------------------------------------------------------------------------- 848 849struct extention_map_t { 850 const char * const name; 851 __eglMustCastToProperFunctionPointerType address; 852}; 853 854static const extention_map_t gExtentionMap[] = { 855 { "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 }, 891 { "eglCreateImageKHR", 892 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 893 { "eglDestroyImageKHR", 894 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 895 { "eglSetSwapRectangleANDROID", 896 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 897 { "eglGetRenderBufferANDROID", 898 (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID }, 899}; 900 901/* 902 * 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 }, 912 { EGL_MAX_PBUFFER_PIXELS, 913 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; 1049 if (key > sortedArray[mid].key) { 1050 first = mid + 1; 1051 } else if (key < sortedArray[mid].key) { 1052 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 1063 config_pair_t const* configFound = gConfigs[i].array; 1064 int index = binarySearch<config_pair_t>( 1065 gConfigs[i].array, 1066 0, gConfigs[i].size-1, 1067 attr); 1068 if (index < 0) { 1069 configFound = config_base_attribute_list; 1070 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) { 1183 case 0: 1184 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1185 depthFormat = 0; 1186 break; 1187 case 1: 1188 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1189 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1190 break; 1191 case 2: 1192 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1193 depthFormat = 0; 1194 break; 1195 case 3: 1196 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1197 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1198 break; 1199 case 4: 1200 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1201 depthFormat = 0; 1202 break; 1203 case 5: 1204 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1205 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 1217 egl_surface_t* surface; 1218 surface = new egl_window_surface_v2_t(dpy, config, depthFormat, 1219 static_cast<android_native_window_t*>(window)); 1220 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) { 1252 case 0: 1253 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1254 depthFormat = 0; 1255 break; 1256 case 1: 1257 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1258 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1259 break; 1260 case 2: 1261 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1262 depthFormat = 0; 1263 break; 1264 case 3: 1265 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1266 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1267 break; 1268 case 4: 1269 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1270 depthFormat = 0; 1271 break; 1272 case 5: 1273 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1274 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; 1305 1306 if (!(surfaceType & EGL_PBUFFER_BIT)) 1307 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1308 1309 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) { 1316 case 0: 1317 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1318 depthFormat = 0; 1319 break; 1320 case 1: 1321 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1322 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1323 break; 1324 case 2: 1325 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1326 depthFormat = 0; 1327 break; 1328 case 3: 1329 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1330 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1331 break; 1332 case 4: 1333 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1334 depthFormat = 0; 1335 break; 1336 case 5: 1337 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1338 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; 1390 } 1391 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); 1398 1399 EGLBoolean res = EGL_TRUE; 1400 egl_display_t& d = egl_display_t::get_display(dpy); 1401 1402 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); 1460 1461 if (ggl_unlikely(num_config==0)) { 1462 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1463 } 1464 1465 if (ggl_unlikely(attrib_list==0)) { 1466 *num_config = 0; 1467 return EGL_TRUE; 1468 } 1469 1470 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, 1492 0, numAttributes-1, 1493 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) { 1511 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 } 1524 } 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} 1550 1551EGLSurface 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} 1563 1564EGLBoolean 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); 1574 if (surface->ctx) { 1575 // FIXME: this surface is current check what the spec says 1576 surface->disconnect(); 1577 surface->ctx = 0; 1578 } 1579 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: 1638 *value = surface->getSwapBehavior(); 1639 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; 1688 1689 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)) { 1704 // one of the surface is bound to a context in another thread 1705 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; 1715 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 1723 c->draw = draw; 1724 c->read = read; 1725 1726 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) { 1739 d->connect(); 1740 d->ctx = ctx; 1741 d->bindDrawSurface(gl); 1742 } 1743 if (r) { 1744 // FIXME: lock/connect the read surface too 1745 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; 1755 if (d) { 1756 c->draw = 0; 1757 d->ctx = EGL_NO_CONTEXT; 1758 d->disconnect(); 1759 } 1760 if (r) { 1761 c->read = 0; 1762 r->ctx = EGL_NO_CONTEXT; 1763 // FIXME: unlock/disconnect the read surface too 1764 } 1765 } 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); 1836 1837 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// ---------------------------------------------------------------------------- 1969// EGL_EGLEXT_VERSION 3 1970// ---------------------------------------------------------------------------- 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} 1982 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); 2016 2017 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 2035 native_buffer->common.decRef(&native_buffer->common); 2036 2037 return EGL_TRUE; 2038} 2039 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} 2059 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} 2072