egl.cpp revision 78141e3acc9913153883fa337a0f3a5eff7acc64
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#include <ui/ANativeObjectBase.h> 34#include <ui/Fence.h> 35 36#include <EGL/egl.h> 37#include <EGL/eglext.h> 38#include <GLES/gl.h> 39#include <GLES/glext.h> 40 41#include <pixelflinger/format.h> 42#include <pixelflinger/pixelflinger.h> 43 44#include "context.h" 45#include "state.h" 46#include "texture.h" 47#include "matrix.h" 48 49#undef NELEM 50#define NELEM(x) (sizeof(x)/sizeof(*(x))) 51 52// ---------------------------------------------------------------------------- 53 54EGLBoolean EGLAPI eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 55 EGLint left, EGLint top, EGLint width, EGLint height); 56 57// ---------------------------------------------------------------------------- 58namespace android { 59 60// ---------------------------------------------------------------------------- 61 62const unsigned int NUM_DISPLAYS = 1; 63 64static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER; 65static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER; 66static pthread_key_t gEGLErrorKey = -1; 67#ifndef HAVE_ANDROID_OS 68namespace gl { 69pthread_key_t gGLKey = -1; 70}; // namespace gl 71#endif 72 73template<typename T> 74static T setError(GLint error, T returnValue) { 75 if (ggl_unlikely(gEGLErrorKey == -1)) { 76 pthread_mutex_lock(&gErrorKeyMutex); 77 if (gEGLErrorKey == -1) 78 pthread_key_create(&gEGLErrorKey, NULL); 79 pthread_mutex_unlock(&gErrorKeyMutex); 80 } 81 pthread_setspecific(gEGLErrorKey, (void*)error); 82 return returnValue; 83} 84 85static GLint getError() { 86 if (ggl_unlikely(gEGLErrorKey == -1)) 87 return EGL_SUCCESS; 88 GLint error = (GLint)pthread_getspecific(gEGLErrorKey); 89 if (error == 0) { 90 // The TLS key has been created by another thread, but the value for 91 // this thread has not been initialized. 92 return EGL_SUCCESS; 93 } 94 pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS); 95 return error; 96} 97 98// ---------------------------------------------------------------------------- 99 100struct egl_display_t 101{ 102 egl_display_t() : type(0), initialized(0) { } 103 104 static egl_display_t& get_display(EGLDisplay dpy); 105 106 static EGLBoolean is_valid(EGLDisplay dpy) { 107 return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; 108 } 109 110 NativeDisplayType type; 111 volatile int32_t initialized; 112}; 113 114static egl_display_t gDisplays[NUM_DISPLAYS]; 115 116egl_display_t& egl_display_t::get_display(EGLDisplay dpy) { 117 return gDisplays[uintptr_t(dpy)-1U]; 118} 119 120struct egl_context_t { 121 enum { 122 IS_CURRENT = 0x00010000, 123 NEVER_CURRENT = 0x00020000 124 }; 125 uint32_t flags; 126 EGLDisplay dpy; 127 EGLConfig config; 128 EGLSurface read; 129 EGLSurface draw; 130 131 static inline egl_context_t* context(EGLContext ctx) { 132 ogles_context_t* const gl = static_cast<ogles_context_t*>(ctx); 133 return static_cast<egl_context_t*>(gl->rasterizer.base); 134 } 135}; 136 137// ---------------------------------------------------------------------------- 138 139struct egl_surface_t 140{ 141 enum { 142 PAGE_FLIP = 0x00000001, 143 MAGIC = 0x31415265 144 }; 145 146 uint32_t magic; 147 EGLDisplay dpy; 148 EGLConfig config; 149 EGLContext ctx; 150 bool zombie; 151 152 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); 153 virtual ~egl_surface_t(); 154 bool isValid() const; 155 virtual bool initCheck() const = 0; 156 157 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; 158 virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; 159 virtual EGLBoolean connect() { return EGL_TRUE; } 160 virtual void disconnect() {} 161 virtual EGLint getWidth() const = 0; 162 virtual EGLint getHeight() const = 0; 163 164 virtual EGLint getHorizontalResolution() const; 165 virtual EGLint getVerticalResolution() const; 166 virtual EGLint getRefreshRate() const; 167 virtual EGLint getSwapBehavior() const; 168 virtual EGLBoolean swapBuffers(); 169 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); 170protected: 171 GGLSurface depth; 172}; 173 174egl_surface_t::egl_surface_t(EGLDisplay dpy, 175 EGLConfig config, 176 int32_t depthFormat) 177 : magic(MAGIC), dpy(dpy), config(config), ctx(0), zombie(false) 178{ 179 depth.version = sizeof(GGLSurface); 180 depth.data = 0; 181 depth.format = depthFormat; 182} 183egl_surface_t::~egl_surface_t() 184{ 185 magic = 0; 186 free(depth.data); 187} 188bool egl_surface_t::isValid() const { 189 ALOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this); 190 return magic == MAGIC; 191} 192 193EGLBoolean egl_surface_t::swapBuffers() { 194 return EGL_FALSE; 195} 196EGLint egl_surface_t::getHorizontalResolution() const { 197 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 198} 199EGLint egl_surface_t::getVerticalResolution() const { 200 return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 201} 202EGLint egl_surface_t::getRefreshRate() const { 203 return (60 * EGL_DISPLAY_SCALING); 204} 205EGLint egl_surface_t::getSwapBehavior() const { 206 return EGL_BUFFER_PRESERVED; 207} 208EGLBoolean egl_surface_t::setSwapRectangle( 209 EGLint l, EGLint t, EGLint w, EGLint h) 210{ 211 return EGL_FALSE; 212} 213 214// ---------------------------------------------------------------------------- 215 216struct egl_window_surface_v2_t : public egl_surface_t 217{ 218 egl_window_surface_v2_t( 219 EGLDisplay dpy, EGLConfig config, 220 int32_t depthFormat, 221 ANativeWindow* window); 222 223 ~egl_window_surface_v2_t(); 224 225 virtual bool initCheck() const { return true; } // TODO: report failure if ctor fails 226 virtual EGLBoolean swapBuffers(); 227 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 228 virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 229 virtual EGLBoolean connect(); 230 virtual void disconnect(); 231 virtual EGLint getWidth() const { return width; } 232 virtual EGLint getHeight() const { return height; } 233 virtual EGLint getHorizontalResolution() const; 234 virtual EGLint getVerticalResolution() const; 235 virtual EGLint getRefreshRate() const; 236 virtual EGLint getSwapBehavior() const; 237 virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); 238 239private: 240 status_t lock(ANativeWindowBuffer* buf, int usage, void** vaddr); 241 status_t unlock(ANativeWindowBuffer* buf); 242 ANativeWindow* nativeWindow; 243 ANativeWindowBuffer* buffer; 244 ANativeWindowBuffer* previousBuffer; 245 gralloc_module_t const* module; 246 int width; 247 int height; 248 void* bits; 249 GGLFormat const* pixelFormatTable; 250 251 struct Rect { 252 inline Rect() { }; 253 inline Rect(int32_t w, int32_t h) 254 : left(0), top(0), right(w), bottom(h) { } 255 inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) 256 : left(l), top(t), right(r), bottom(b) { } 257 Rect& andSelf(const Rect& r) { 258 left = max(left, r.left); 259 top = max(top, r.top); 260 right = min(right, r.right); 261 bottom = min(bottom, r.bottom); 262 return *this; 263 } 264 bool isEmpty() const { 265 return (left>=right || top>=bottom); 266 } 267 void dump(char const* what) { 268 ALOGD("%s { %5d, %5d, w=%5d, h=%5d }", 269 what, left, top, right-left, bottom-top); 270 } 271 272 int32_t left; 273 int32_t top; 274 int32_t right; 275 int32_t bottom; 276 }; 277 278 struct Region { 279 inline Region() : count(0) { } 280 typedef Rect const* const_iterator; 281 const_iterator begin() const { return storage; } 282 const_iterator end() const { return storage+count; } 283 static Region subtract(const Rect& lhs, const Rect& rhs) { 284 Region reg; 285 Rect* storage = reg.storage; 286 if (!lhs.isEmpty()) { 287 if (lhs.top < rhs.top) { // top rect 288 storage->left = lhs.left; 289 storage->top = lhs.top; 290 storage->right = lhs.right; 291 storage->bottom = rhs.top; 292 storage++; 293 } 294 const int32_t top = max(lhs.top, rhs.top); 295 const int32_t bot = min(lhs.bottom, rhs.bottom); 296 if (top < bot) { 297 if (lhs.left < rhs.left) { // left-side rect 298 storage->left = lhs.left; 299 storage->top = top; 300 storage->right = rhs.left; 301 storage->bottom = bot; 302 storage++; 303 } 304 if (lhs.right > rhs.right) { // right-side rect 305 storage->left = rhs.right; 306 storage->top = top; 307 storage->right = lhs.right; 308 storage->bottom = bot; 309 storage++; 310 } 311 } 312 if (lhs.bottom > rhs.bottom) { // bottom rect 313 storage->left = lhs.left; 314 storage->top = rhs.bottom; 315 storage->right = lhs.right; 316 storage->bottom = lhs.bottom; 317 storage++; 318 } 319 reg.count = storage - reg.storage; 320 } 321 return reg; 322 } 323 bool isEmpty() const { 324 return count<=0; 325 } 326 private: 327 Rect storage[4]; 328 ssize_t count; 329 }; 330 331 void copyBlt( 332 ANativeWindowBuffer* dst, void* dst_vaddr, 333 ANativeWindowBuffer* src, void const* src_vaddr, 334 const Region& clip); 335 336 Rect dirtyRegion; 337 Rect oldDirtyRegion; 338}; 339 340egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, 341 EGLConfig config, 342 int32_t depthFormat, 343 ANativeWindow* window) 344 : egl_surface_t(dpy, config, depthFormat), 345 nativeWindow(window), buffer(0), previousBuffer(0), module(0), 346 bits(NULL) 347{ 348 hw_module_t const* pModule; 349 hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); 350 module = reinterpret_cast<gralloc_module_t const*>(pModule); 351 352 pixelFormatTable = gglGetPixelFormatTable(); 353 354 // keep a reference on the window 355 nativeWindow->common.incRef(&nativeWindow->common); 356 nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width); 357 nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height); 358} 359 360egl_window_surface_v2_t::~egl_window_surface_v2_t() { 361 if (buffer) { 362 buffer->common.decRef(&buffer->common); 363 } 364 if (previousBuffer) { 365 previousBuffer->common.decRef(&previousBuffer->common); 366 } 367 nativeWindow->common.decRef(&nativeWindow->common); 368} 369 370EGLBoolean egl_window_surface_v2_t::connect() 371{ 372 // we're intending to do software rendering 373 native_window_set_usage(nativeWindow, 374 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 375 376 // dequeue a buffer 377 int fenceFd = -1; 378 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, 379 &fenceFd) != NO_ERROR) { 380 return setError(EGL_BAD_ALLOC, EGL_FALSE); 381 } 382 383 // wait for the buffer 384 sp<Fence> fence(new Fence(fenceFd)); 385 if (fence->wait(Fence::TIMEOUT_NEVER) != NO_ERROR) { 386 nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd); 387 return setError(EGL_BAD_ALLOC, EGL_FALSE); 388 } 389 390 // allocate a corresponding depth-buffer 391 width = buffer->width; 392 height = buffer->height; 393 if (depth.format) { 394 depth.width = width; 395 depth.height = height; 396 depth.stride = depth.width; // use the width here 397 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 398 if (depth.data == 0) { 399 return setError(EGL_BAD_ALLOC, EGL_FALSE); 400 } 401 } 402 403 // keep a reference on the buffer 404 buffer->common.incRef(&buffer->common); 405 406 // pin the buffer down 407 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 408 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { 409 ALOGE("connect() failed to lock buffer %p (%ux%u)", 410 buffer, buffer->width, buffer->height); 411 return setError(EGL_BAD_ACCESS, EGL_FALSE); 412 // FIXME: we should make sure we're not accessing the buffer anymore 413 } 414 return EGL_TRUE; 415} 416 417void egl_window_surface_v2_t::disconnect() 418{ 419 if (buffer && bits) { 420 bits = NULL; 421 unlock(buffer); 422 } 423 // enqueue the last frame 424 nativeWindow->queueBuffer(nativeWindow, buffer, -1); 425 if (buffer) { 426 buffer->common.decRef(&buffer->common); 427 buffer = 0; 428 } 429 if (previousBuffer) { 430 previousBuffer->common.decRef(&previousBuffer->common); 431 previousBuffer = 0; 432 } 433} 434 435status_t egl_window_surface_v2_t::lock( 436 ANativeWindowBuffer* buf, int usage, void** vaddr) 437{ 438 int err; 439 440 err = module->lock(module, buf->handle, 441 usage, 0, 0, buf->width, buf->height, vaddr); 442 443 return err; 444} 445 446status_t egl_window_surface_v2_t::unlock(ANativeWindowBuffer* buf) 447{ 448 if (!buf) return BAD_VALUE; 449 int err = NO_ERROR; 450 451 err = module->unlock(module, buf->handle); 452 453 return err; 454} 455 456void egl_window_surface_v2_t::copyBlt( 457 ANativeWindowBuffer* dst, void* dst_vaddr, 458 ANativeWindowBuffer* src, void const* src_vaddr, 459 const Region& clip) 460{ 461 // NOTE: dst and src must be the same format 462 463 Region::const_iterator cur = clip.begin(); 464 Region::const_iterator end = clip.end(); 465 466 const size_t bpp = pixelFormatTable[src->format].size; 467 const size_t dbpr = dst->stride * bpp; 468 const size_t sbpr = src->stride * bpp; 469 470 uint8_t const * const src_bits = (uint8_t const *)src_vaddr; 471 uint8_t * const dst_bits = (uint8_t *)dst_vaddr; 472 473 while (cur != end) { 474 const Rect& r(*cur++); 475 ssize_t w = r.right - r.left; 476 ssize_t h = r.bottom - r.top; 477 if (w <= 0 || h<=0) continue; 478 size_t size = w * bpp; 479 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; 480 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; 481 if (dbpr==sbpr && size==sbpr) { 482 size *= h; 483 h = 1; 484 } 485 do { 486 memcpy(d, s, size); 487 d += dbpr; 488 s += sbpr; 489 } while (--h > 0); 490 } 491} 492 493EGLBoolean egl_window_surface_v2_t::swapBuffers() 494{ 495 if (!buffer) { 496 return setError(EGL_BAD_ACCESS, EGL_FALSE); 497 } 498 499 /* 500 * Handle eglSetSwapRectangleANDROID() 501 * We copyback from the front buffer 502 */ 503 if (!dirtyRegion.isEmpty()) { 504 dirtyRegion.andSelf(Rect(buffer->width, buffer->height)); 505 if (previousBuffer) { 506 // This was const Region copyBack, but that causes an 507 // internal compile error on simulator builds 508 /*const*/ Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); 509 if (!copyBack.isEmpty()) { 510 void* prevBits; 511 if (lock(previousBuffer, 512 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) { 513 // copy from previousBuffer to buffer 514 copyBlt(buffer, bits, previousBuffer, prevBits, copyBack); 515 unlock(previousBuffer); 516 } 517 } 518 } 519 oldDirtyRegion = dirtyRegion; 520 } 521 522 if (previousBuffer) { 523 previousBuffer->common.decRef(&previousBuffer->common); 524 previousBuffer = 0; 525 } 526 527 unlock(buffer); 528 previousBuffer = buffer; 529 nativeWindow->queueBuffer(nativeWindow, buffer, -1); 530 buffer = 0; 531 532 // dequeue a new buffer 533 int fenceFd = -1; 534 if (nativeWindow->dequeueBuffer(nativeWindow, &buffer, &fenceFd) == NO_ERROR) { 535 sp<Fence> fence(new Fence(fenceFd)); 536 if (fence->wait(Fence::TIMEOUT_NEVER)) { 537 nativeWindow->cancelBuffer(nativeWindow, buffer, fenceFd); 538 return setError(EGL_BAD_ALLOC, EGL_FALSE); 539 } 540 541 // reallocate the depth-buffer if needed 542 if ((width != buffer->width) || (height != buffer->height)) { 543 // TODO: we probably should reset the swap rect here 544 // if the window size has changed 545 width = buffer->width; 546 height = buffer->height; 547 if (depth.data) { 548 free(depth.data); 549 depth.width = width; 550 depth.height = height; 551 depth.stride = buffer->stride; 552 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 553 if (depth.data == 0) { 554 setError(EGL_BAD_ALLOC, EGL_FALSE); 555 return EGL_FALSE; 556 } 557 } 558 } 559 560 // keep a reference on the buffer 561 buffer->common.incRef(&buffer->common); 562 563 // finally pin the buffer down 564 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 565 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { 566 ALOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", 567 buffer, buffer->width, buffer->height); 568 return setError(EGL_BAD_ACCESS, EGL_FALSE); 569 // FIXME: we should make sure we're not accessing the buffer anymore 570 } 571 } else { 572 return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 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 585EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) 586{ 587 GGLSurface buffer; 588 buffer.version = sizeof(GGLSurface); 589 buffer.width = this->buffer->width; 590 buffer.height = this->buffer->height; 591 buffer.stride = this->buffer->stride; 592 buffer.data = (GGLubyte*)bits; 593 buffer.format = this->buffer->format; 594 gl->rasterizer.procs.colorBuffer(gl, &buffer); 595 if (depth.data != gl->rasterizer.state.buffers.depth.data) 596 gl->rasterizer.procs.depthBuffer(gl, &depth); 597 598 return EGL_TRUE; 599} 600EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) 601{ 602 GGLSurface buffer; 603 buffer.version = sizeof(GGLSurface); 604 buffer.width = this->buffer->width; 605 buffer.height = this->buffer->height; 606 buffer.stride = this->buffer->stride; 607 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! 608 buffer.format = this->buffer->format; 609 gl->rasterizer.procs.readBuffer(gl, &buffer); 610 return EGL_TRUE; 611} 612EGLint egl_window_surface_v2_t::getHorizontalResolution() const { 613 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 614} 615EGLint egl_window_surface_v2_t::getVerticalResolution() const { 616 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 617} 618EGLint egl_window_surface_v2_t::getRefreshRate() const { 619 return (60 * EGL_DISPLAY_SCALING); // FIXME 620} 621EGLint egl_window_surface_v2_t::getSwapBehavior() const 622{ 623 /* 624 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves 625 * the content of the swapped buffer. 626 * 627 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost. 628 * 629 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED 630 * only applies to the area specified by eglSetSwapRectangleANDROID(), that 631 * is, everything outside of this area is preserved. 632 * 633 * This implementation of EGL assumes the later case. 634 * 635 */ 636 637 return EGL_BUFFER_DESTROYED; 638} 639 640// ---------------------------------------------------------------------------- 641 642struct egl_pixmap_surface_t : public egl_surface_t 643{ 644 egl_pixmap_surface_t( 645 EGLDisplay dpy, EGLConfig config, 646 int32_t depthFormat, 647 egl_native_pixmap_t const * pixmap); 648 649 virtual ~egl_pixmap_surface_t() { } 650 651 virtual bool initCheck() const { return !depth.format || depth.data!=0; } 652 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 653 virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 654 virtual EGLint getWidth() const { return nativePixmap.width; } 655 virtual EGLint getHeight() const { return nativePixmap.height; } 656private: 657 egl_native_pixmap_t nativePixmap; 658}; 659 660egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy, 661 EGLConfig config, 662 int32_t depthFormat, 663 egl_native_pixmap_t const * pixmap) 664 : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap) 665{ 666 if (depthFormat) { 667 depth.width = pixmap->width; 668 depth.height = pixmap->height; 669 depth.stride = depth.width; // use the width here 670 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 671 if (depth.data == 0) { 672 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 673 } 674 } 675} 676EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl) 677{ 678 GGLSurface buffer; 679 buffer.version = sizeof(GGLSurface); 680 buffer.width = nativePixmap.width; 681 buffer.height = nativePixmap.height; 682 buffer.stride = nativePixmap.stride; 683 buffer.data = nativePixmap.data; 684 buffer.format = nativePixmap.format; 685 686 gl->rasterizer.procs.colorBuffer(gl, &buffer); 687 if (depth.data != gl->rasterizer.state.buffers.depth.data) 688 gl->rasterizer.procs.depthBuffer(gl, &depth); 689 return EGL_TRUE; 690} 691EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl) 692{ 693 GGLSurface buffer; 694 buffer.version = sizeof(GGLSurface); 695 buffer.width = nativePixmap.width; 696 buffer.height = nativePixmap.height; 697 buffer.stride = nativePixmap.stride; 698 buffer.data = nativePixmap.data; 699 buffer.format = nativePixmap.format; 700 gl->rasterizer.procs.readBuffer(gl, &buffer); 701 return EGL_TRUE; 702} 703 704// ---------------------------------------------------------------------------- 705 706struct egl_pbuffer_surface_t : public egl_surface_t 707{ 708 egl_pbuffer_surface_t( 709 EGLDisplay dpy, EGLConfig config, int32_t depthFormat, 710 int32_t w, int32_t h, int32_t f); 711 712 virtual ~egl_pbuffer_surface_t(); 713 714 virtual bool initCheck() const { return pbuffer.data != 0; } 715 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 716 virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 717 virtual EGLint getWidth() const { return pbuffer.width; } 718 virtual EGLint getHeight() const { return pbuffer.height; } 719private: 720 GGLSurface pbuffer; 721}; 722 723egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, 724 EGLConfig config, int32_t depthFormat, 725 int32_t w, int32_t h, int32_t f) 726 : egl_surface_t(dpy, config, depthFormat) 727{ 728 size_t size = w*h; 729 switch (f) { 730 case GGL_PIXEL_FORMAT_A_8: size *= 1; break; 731 case GGL_PIXEL_FORMAT_RGB_565: size *= 2; break; 732 case GGL_PIXEL_FORMAT_RGBA_8888: size *= 4; break; 733 case GGL_PIXEL_FORMAT_RGBX_8888: size *= 4; break; 734 default: 735 ALOGE("incompatible pixel format for pbuffer (format=%d)", f); 736 pbuffer.data = 0; 737 break; 738 } 739 pbuffer.version = sizeof(GGLSurface); 740 pbuffer.width = w; 741 pbuffer.height = h; 742 pbuffer.stride = w; 743 pbuffer.data = (GGLubyte*)malloc(size); 744 pbuffer.format = f; 745 746 if (depthFormat) { 747 depth.width = pbuffer.width; 748 depth.height = pbuffer.height; 749 depth.stride = depth.width; // use the width here 750 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 751 if (depth.data == 0) { 752 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 753 return; 754 } 755 } 756} 757egl_pbuffer_surface_t::~egl_pbuffer_surface_t() { 758 free(pbuffer.data); 759} 760EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl) 761{ 762 gl->rasterizer.procs.colorBuffer(gl, &pbuffer); 763 if (depth.data != gl->rasterizer.state.buffers.depth.data) 764 gl->rasterizer.procs.depthBuffer(gl, &depth); 765 return EGL_TRUE; 766} 767EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl) 768{ 769 gl->rasterizer.procs.readBuffer(gl, &pbuffer); 770 return EGL_TRUE; 771} 772 773// ---------------------------------------------------------------------------- 774 775struct config_pair_t { 776 GLint key; 777 GLint value; 778}; 779 780struct configs_t { 781 const config_pair_t* array; 782 int size; 783}; 784 785struct config_management_t { 786 GLint key; 787 bool (*match)(GLint reqValue, GLint confValue); 788 static bool atLeast(GLint reqValue, GLint confValue) { 789 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue); 790 } 791 static bool exact(GLint reqValue, GLint confValue) { 792 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue); 793 } 794 static bool mask(GLint reqValue, GLint confValue) { 795 return (confValue & reqValue) == reqValue; 796 } 797 static bool ignore(GLint reqValue, GLint confValue) { 798 return true; 799 } 800}; 801 802// ---------------------------------------------------------------------------- 803 804#define VERSION_MAJOR 1 805#define VERSION_MINOR 2 806static char const * const gVendorString = "Google Inc."; 807static char const * const gVersionString = "1.2 Android Driver 1.2.0"; 808static char const * const gClientApiString = "OpenGL_ES"; 809static char const * const gExtensionsString = 810 "EGL_KHR_fence_sync " 811 "EGL_KHR_image_base " 812 // "KHR_image_pixmap " 813 "EGL_ANDROID_image_native_buffer " 814 "EGL_ANDROID_swap_rectangle " 815 ; 816 817// ---------------------------------------------------------------------------- 818 819struct extention_map_t { 820 const char * const name; 821 __eglMustCastToProperFunctionPointerType address; 822}; 823 824static const extention_map_t gExtentionMap[] = { 825 { "glDrawTexsOES", 826 (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, 827 { "glDrawTexiOES", 828 (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, 829 { "glDrawTexfOES", 830 (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, 831 { "glDrawTexxOES", 832 (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, 833 { "glDrawTexsvOES", 834 (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, 835 { "glDrawTexivOES", 836 (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, 837 { "glDrawTexfvOES", 838 (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, 839 { "glDrawTexxvOES", 840 (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, 841 { "glQueryMatrixxOES", 842 (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, 843 { "glEGLImageTargetTexture2DOES", 844 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, 845 { "glEGLImageTargetRenderbufferStorageOES", 846 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, 847 { "glClipPlanef", 848 (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, 849 { "glClipPlanex", 850 (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, 851 { "glBindBuffer", 852 (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, 853 { "glBufferData", 854 (__eglMustCastToProperFunctionPointerType)&glBufferData }, 855 { "glBufferSubData", 856 (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, 857 { "glDeleteBuffers", 858 (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, 859 { "glGenBuffers", 860 (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, 861 { "eglCreateImageKHR", 862 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 863 { "eglDestroyImageKHR", 864 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 865 { "eglCreateSyncKHR", 866 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 867 { "eglDestroySyncKHR", 868 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 869 { "eglClientWaitSyncKHR", 870 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 871 { "eglGetSyncAttribKHR", 872 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 873 { "eglSetSwapRectangleANDROID", 874 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 875}; 876 877/* 878 * In the lists below, attributes names MUST be sorted. 879 * Additionally, all configs must be sorted according to 880 * the EGL specification. 881 */ 882 883static config_pair_t const config_base_attribute_list[] = { 884 { EGL_STENCIL_SIZE, 0 }, 885 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, 886 { EGL_LEVEL, 0 }, 887 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, 888 { EGL_MAX_PBUFFER_PIXELS, 889 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, 890 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, 891 { EGL_NATIVE_RENDERABLE, EGL_TRUE }, 892 { EGL_NATIVE_VISUAL_ID, 0 }, 893 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGB_565 }, 894 { EGL_SAMPLES, 0 }, 895 { EGL_SAMPLE_BUFFERS, 0 }, 896 { EGL_TRANSPARENT_TYPE, EGL_NONE }, 897 { EGL_TRANSPARENT_BLUE_VALUE, 0 }, 898 { EGL_TRANSPARENT_GREEN_VALUE, 0 }, 899 { EGL_TRANSPARENT_RED_VALUE, 0 }, 900 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE }, 901 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE }, 902 { EGL_MIN_SWAP_INTERVAL, 1 }, 903 { EGL_MAX_SWAP_INTERVAL, 1 }, 904 { EGL_LUMINANCE_SIZE, 0 }, 905 { EGL_ALPHA_MASK_SIZE, 0 }, 906 { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER }, 907 { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT }, 908 { EGL_CONFORMANT, 0 } 909}; 910 911// These configs can override the base attribute list 912// NOTE: when adding a config here, don't forget to update eglCreate*Surface() 913 914// 565 configs 915static config_pair_t const config_0_attribute_list[] = { 916 { EGL_BUFFER_SIZE, 16 }, 917 { EGL_ALPHA_SIZE, 0 }, 918 { EGL_BLUE_SIZE, 5 }, 919 { EGL_GREEN_SIZE, 6 }, 920 { EGL_RED_SIZE, 5 }, 921 { EGL_DEPTH_SIZE, 0 }, 922 { EGL_CONFIG_ID, 0 }, 923 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 }, 924 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 925}; 926 927static config_pair_t const config_1_attribute_list[] = { 928 { EGL_BUFFER_SIZE, 16 }, 929 { EGL_ALPHA_SIZE, 0 }, 930 { EGL_BLUE_SIZE, 5 }, 931 { EGL_GREEN_SIZE, 6 }, 932 { EGL_RED_SIZE, 5 }, 933 { EGL_DEPTH_SIZE, 16 }, 934 { EGL_CONFIG_ID, 1 }, 935 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 }, 936 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 937}; 938 939// RGB 888 configs 940static config_pair_t const config_2_attribute_list[] = { 941 { EGL_BUFFER_SIZE, 32 }, 942 { EGL_ALPHA_SIZE, 0 }, 943 { EGL_BLUE_SIZE, 8 }, 944 { EGL_GREEN_SIZE, 8 }, 945 { EGL_RED_SIZE, 8 }, 946 { EGL_DEPTH_SIZE, 0 }, 947 { EGL_CONFIG_ID, 6 }, 948 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 }, 949 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 950}; 951 952static config_pair_t const config_3_attribute_list[] = { 953 { EGL_BUFFER_SIZE, 32 }, 954 { EGL_ALPHA_SIZE, 0 }, 955 { EGL_BLUE_SIZE, 8 }, 956 { EGL_GREEN_SIZE, 8 }, 957 { EGL_RED_SIZE, 8 }, 958 { EGL_DEPTH_SIZE, 16 }, 959 { EGL_CONFIG_ID, 7 }, 960 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 }, 961 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 962}; 963 964// 8888 configs 965static config_pair_t const config_4_attribute_list[] = { 966 { EGL_BUFFER_SIZE, 32 }, 967 { EGL_ALPHA_SIZE, 8 }, 968 { EGL_BLUE_SIZE, 8 }, 969 { EGL_GREEN_SIZE, 8 }, 970 { EGL_RED_SIZE, 8 }, 971 { EGL_DEPTH_SIZE, 0 }, 972 { EGL_CONFIG_ID, 2 }, 973 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 }, 974 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 975}; 976 977static config_pair_t const config_5_attribute_list[] = { 978 { EGL_BUFFER_SIZE, 32 }, 979 { EGL_ALPHA_SIZE, 8 }, 980 { EGL_BLUE_SIZE, 8 }, 981 { EGL_GREEN_SIZE, 8 }, 982 { EGL_RED_SIZE, 8 }, 983 { EGL_DEPTH_SIZE, 16 }, 984 { EGL_CONFIG_ID, 3 }, 985 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 }, 986 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 987}; 988 989// A8 configs 990static config_pair_t const config_6_attribute_list[] = { 991 { EGL_BUFFER_SIZE, 8 }, 992 { EGL_ALPHA_SIZE, 8 }, 993 { EGL_BLUE_SIZE, 0 }, 994 { EGL_GREEN_SIZE, 0 }, 995 { EGL_RED_SIZE, 0 }, 996 { EGL_DEPTH_SIZE, 0 }, 997 { EGL_CONFIG_ID, 4 }, 998 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 }, 999 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 1000}; 1001 1002static config_pair_t const config_7_attribute_list[] = { 1003 { EGL_BUFFER_SIZE, 8 }, 1004 { EGL_ALPHA_SIZE, 8 }, 1005 { EGL_BLUE_SIZE, 0 }, 1006 { EGL_GREEN_SIZE, 0 }, 1007 { EGL_RED_SIZE, 0 }, 1008 { EGL_DEPTH_SIZE, 16 }, 1009 { EGL_CONFIG_ID, 5 }, 1010 { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 }, 1011 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 1012}; 1013 1014static configs_t const gConfigs[] = { 1015 { config_0_attribute_list, NELEM(config_0_attribute_list) }, 1016 { config_1_attribute_list, NELEM(config_1_attribute_list) }, 1017 { config_2_attribute_list, NELEM(config_2_attribute_list) }, 1018 { config_3_attribute_list, NELEM(config_3_attribute_list) }, 1019 { config_4_attribute_list, NELEM(config_4_attribute_list) }, 1020 { config_5_attribute_list, NELEM(config_5_attribute_list) }, 1021 { config_6_attribute_list, NELEM(config_6_attribute_list) }, 1022 { config_7_attribute_list, NELEM(config_7_attribute_list) }, 1023}; 1024 1025static config_management_t const gConfigManagement[] = { 1026 { EGL_BUFFER_SIZE, config_management_t::atLeast }, 1027 { EGL_ALPHA_SIZE, config_management_t::atLeast }, 1028 { EGL_BLUE_SIZE, config_management_t::atLeast }, 1029 { EGL_GREEN_SIZE, config_management_t::atLeast }, 1030 { EGL_RED_SIZE, config_management_t::atLeast }, 1031 { EGL_DEPTH_SIZE, config_management_t::atLeast }, 1032 { EGL_STENCIL_SIZE, config_management_t::atLeast }, 1033 { EGL_CONFIG_CAVEAT, config_management_t::exact }, 1034 { EGL_CONFIG_ID, config_management_t::exact }, 1035 { EGL_LEVEL, config_management_t::exact }, 1036 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore }, 1037 { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore }, 1038 { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore }, 1039 { EGL_NATIVE_RENDERABLE, config_management_t::exact }, 1040 { EGL_NATIVE_VISUAL_ID, config_management_t::ignore }, 1041 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact }, 1042 { EGL_SAMPLES, config_management_t::exact }, 1043 { EGL_SAMPLE_BUFFERS, config_management_t::exact }, 1044 { EGL_SURFACE_TYPE, config_management_t::mask }, 1045 { EGL_TRANSPARENT_TYPE, config_management_t::exact }, 1046 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact }, 1047 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact }, 1048 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact }, 1049 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact }, 1050 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact }, 1051 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact }, 1052 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact }, 1053 { EGL_LUMINANCE_SIZE, config_management_t::atLeast }, 1054 { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast }, 1055 { EGL_COLOR_BUFFER_TYPE, config_management_t::exact }, 1056 { EGL_RENDERABLE_TYPE, config_management_t::mask }, 1057 { EGL_CONFORMANT, config_management_t::mask } 1058}; 1059 1060 1061static config_pair_t const config_defaults[] = { 1062 // attributes that are not specified are simply ignored, if a particular 1063 // one needs not be ignored, it must be specified here, eg: 1064 // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT }, 1065}; 1066 1067// ---------------------------------------------------------------------------- 1068 1069static status_t getConfigFormatInfo(EGLint configID, 1070 int32_t& pixelFormat, int32_t& depthFormat) 1071{ 1072 switch(configID) { 1073 case 0: 1074 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1075 depthFormat = 0; 1076 break; 1077 case 1: 1078 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1079 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1080 break; 1081 case 2: 1082 pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888; 1083 depthFormat = 0; 1084 break; 1085 case 3: 1086 pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888; 1087 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1088 break; 1089 case 4: 1090 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1091 depthFormat = 0; 1092 break; 1093 case 5: 1094 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1095 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1096 break; 1097 case 6: 1098 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1099 depthFormat = 0; 1100 break; 1101 case 7: 1102 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1103 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1104 break; 1105 default: 1106 return NAME_NOT_FOUND; 1107 } 1108 return NO_ERROR; 1109} 1110 1111// ---------------------------------------------------------------------------- 1112 1113template<typename T> 1114static int binarySearch(T const sortedArray[], int first, int last, EGLint key) 1115{ 1116 while (first <= last) { 1117 int mid = (first + last) / 2; 1118 if (key > sortedArray[mid].key) { 1119 first = mid + 1; 1120 } else if (key < sortedArray[mid].key) { 1121 last = mid - 1; 1122 } else { 1123 return mid; 1124 } 1125 } 1126 return -1; 1127} 1128 1129static int isAttributeMatching(int i, EGLint attr, EGLint val) 1130{ 1131 // look for the attribute in all of our configs 1132 config_pair_t const* configFound = gConfigs[i].array; 1133 int index = binarySearch<config_pair_t>( 1134 gConfigs[i].array, 1135 0, gConfigs[i].size-1, 1136 attr); 1137 if (index < 0) { 1138 configFound = config_base_attribute_list; 1139 index = binarySearch<config_pair_t>( 1140 config_base_attribute_list, 1141 0, NELEM(config_base_attribute_list)-1, 1142 attr); 1143 } 1144 if (index >= 0) { 1145 // attribute found, check if this config could match 1146 int cfgMgtIndex = binarySearch<config_management_t>( 1147 gConfigManagement, 1148 0, NELEM(gConfigManagement)-1, 1149 attr); 1150 if (cfgMgtIndex >= 0) { 1151 bool match = gConfigManagement[cfgMgtIndex].match( 1152 val, configFound[index].value); 1153 if (match) { 1154 // this config matches 1155 return 1; 1156 } 1157 } else { 1158 // attribute not found. this should NEVER happen. 1159 } 1160 } else { 1161 // error, this attribute doesn't exist 1162 } 1163 return 0; 1164} 1165 1166static int makeCurrent(ogles_context_t* gl) 1167{ 1168 ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific(); 1169 if (gl) { 1170 egl_context_t* c = egl_context_t::context(gl); 1171 if (c->flags & egl_context_t::IS_CURRENT) { 1172 if (current != gl) { 1173 // it is an error to set a context current, if it's already 1174 // current to another thread 1175 return -1; 1176 } 1177 } else { 1178 if (current) { 1179 // mark the current context as not current, and flush 1180 glFlush(); 1181 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; 1182 } 1183 } 1184 if (!(c->flags & egl_context_t::IS_CURRENT)) { 1185 // The context is not current, make it current! 1186 setGlThreadSpecific(gl); 1187 c->flags |= egl_context_t::IS_CURRENT; 1188 } 1189 } else { 1190 if (current) { 1191 // mark the current context as not current, and flush 1192 glFlush(); 1193 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; 1194 } 1195 // this thread has no context attached to it 1196 setGlThreadSpecific(0); 1197 } 1198 return 0; 1199} 1200 1201static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config, 1202 EGLint attribute, EGLint *value) 1203{ 1204 size_t numConfigs = NELEM(gConfigs); 1205 int index = (int)config; 1206 if (uint32_t(index) >= numConfigs) 1207 return setError(EGL_BAD_CONFIG, EGL_FALSE); 1208 1209 int attrIndex; 1210 attrIndex = binarySearch<config_pair_t>( 1211 gConfigs[index].array, 1212 0, gConfigs[index].size-1, 1213 attribute); 1214 if (attrIndex>=0) { 1215 *value = gConfigs[index].array[attrIndex].value; 1216 return EGL_TRUE; 1217 } 1218 1219 attrIndex = binarySearch<config_pair_t>( 1220 config_base_attribute_list, 1221 0, NELEM(config_base_attribute_list)-1, 1222 attribute); 1223 if (attrIndex>=0) { 1224 *value = config_base_attribute_list[attrIndex].value; 1225 return EGL_TRUE; 1226 } 1227 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1228} 1229 1230static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, 1231 NativeWindowType window, 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 (window == 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_WINDOW_BIT)) 1243 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1244 1245 if (static_cast<ANativeWindow*>(window)->common.magic != 1246 ANDROID_NATIVE_WINDOW_MAGIC) { 1247 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 1248 } 1249 1250 EGLint configID; 1251 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) 1252 return EGL_FALSE; 1253 1254 int32_t depthFormat; 1255 int32_t pixelFormat; 1256 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { 1257 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1258 } 1259 1260 // FIXME: we don't have access to the pixelFormat here just yet. 1261 // (it's possible that the surface is not fully initialized) 1262 // maybe this should be done after the page-flip 1263 //if (EGLint(info.format) != pixelFormat) 1264 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1265 1266 egl_surface_t* surface; 1267 surface = new egl_window_surface_v2_t(dpy, config, depthFormat, 1268 static_cast<ANativeWindow*>(window)); 1269 1270 if (!surface->initCheck()) { 1271 // there was a problem in the ctor, the error 1272 // flag has been set. 1273 delete surface; 1274 surface = 0; 1275 } 1276 return surface; 1277} 1278 1279static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, 1280 NativePixmapType pixmap, const EGLint *attrib_list) 1281{ 1282 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1283 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1284 if (pixmap == 0) 1285 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1286 1287 EGLint surfaceType; 1288 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) 1289 return EGL_FALSE; 1290 1291 if (!(surfaceType & EGL_PIXMAP_BIT)) 1292 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1293 1294 if (static_cast<egl_native_pixmap_t*>(pixmap)->version != 1295 sizeof(egl_native_pixmap_t)) { 1296 return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); 1297 } 1298 1299 EGLint configID; 1300 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) 1301 return EGL_FALSE; 1302 1303 int32_t depthFormat; 1304 int32_t pixelFormat; 1305 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { 1306 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1307 } 1308 1309 if (pixmap->format != pixelFormat) 1310 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1311 1312 egl_surface_t* surface = 1313 new egl_pixmap_surface_t(dpy, config, depthFormat, 1314 static_cast<egl_native_pixmap_t*>(pixmap)); 1315 1316 if (!surface->initCheck()) { 1317 // there was a problem in the ctor, the error 1318 // flag has been set. 1319 delete surface; 1320 surface = 0; 1321 } 1322 return surface; 1323} 1324 1325static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, 1326 const EGLint *attrib_list) 1327{ 1328 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1329 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1330 1331 EGLint surfaceType; 1332 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) 1333 return EGL_FALSE; 1334 1335 if (!(surfaceType & EGL_PBUFFER_BIT)) 1336 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1337 1338 EGLint configID; 1339 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) 1340 return EGL_FALSE; 1341 1342 int32_t depthFormat; 1343 int32_t pixelFormat; 1344 if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { 1345 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1346 } 1347 1348 int32_t w = 0; 1349 int32_t h = 0; 1350 while (attrib_list[0]) { 1351 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1]; 1352 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1]; 1353 attrib_list+=2; 1354 } 1355 1356 egl_surface_t* surface = 1357 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat); 1358 1359 if (!surface->initCheck()) { 1360 // there was a problem in the ctor, the error 1361 // flag has been set. 1362 delete surface; 1363 surface = 0; 1364 } 1365 return surface; 1366} 1367 1368// ---------------------------------------------------------------------------- 1369}; // namespace android 1370// ---------------------------------------------------------------------------- 1371 1372using namespace android; 1373 1374// ---------------------------------------------------------------------------- 1375// Initialization 1376// ---------------------------------------------------------------------------- 1377 1378EGLDisplay eglGetDisplay(NativeDisplayType display) 1379{ 1380#ifndef HAVE_ANDROID_OS 1381 // this just needs to be done once 1382 if (gGLKey == -1) { 1383 pthread_mutex_lock(&gInitMutex); 1384 if (gGLKey == -1) 1385 pthread_key_create(&gGLKey, NULL); 1386 pthread_mutex_unlock(&gInitMutex); 1387 } 1388#endif 1389 if (display == EGL_DEFAULT_DISPLAY) { 1390 EGLDisplay dpy = (EGLDisplay)1; 1391 egl_display_t& d = egl_display_t::get_display(dpy); 1392 d.type = display; 1393 return dpy; 1394 } 1395 return EGL_NO_DISPLAY; 1396} 1397 1398EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 1399{ 1400 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1401 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1402 1403 EGLBoolean res = EGL_TRUE; 1404 egl_display_t& d = egl_display_t::get_display(dpy); 1405 1406 if (android_atomic_inc(&d.initialized) == 0) { 1407 // initialize stuff here if needed 1408 //pthread_mutex_lock(&gInitMutex); 1409 //pthread_mutex_unlock(&gInitMutex); 1410 } 1411 1412 if (res == EGL_TRUE) { 1413 if (major != NULL) *major = VERSION_MAJOR; 1414 if (minor != NULL) *minor = VERSION_MINOR; 1415 } 1416 return res; 1417} 1418 1419EGLBoolean eglTerminate(EGLDisplay dpy) 1420{ 1421 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1422 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1423 1424 EGLBoolean res = EGL_TRUE; 1425 egl_display_t& d = egl_display_t::get_display(dpy); 1426 if (android_atomic_dec(&d.initialized) == 1) { 1427 // TODO: destroy all resources (surfaces, contexts, etc...) 1428 //pthread_mutex_lock(&gInitMutex); 1429 //pthread_mutex_unlock(&gInitMutex); 1430 } 1431 return res; 1432} 1433 1434// ---------------------------------------------------------------------------- 1435// configuration 1436// ---------------------------------------------------------------------------- 1437 1438EGLBoolean eglGetConfigs( EGLDisplay dpy, 1439 EGLConfig *configs, 1440 EGLint config_size, EGLint *num_config) 1441{ 1442 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1443 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1444 1445 GLint numConfigs = NELEM(gConfigs); 1446 if (!configs) { 1447 *num_config = numConfigs; 1448 return EGL_TRUE; 1449 } 1450 GLint i; 1451 for (i=0 ; i<numConfigs && i<config_size ; i++) { 1452 *configs++ = (EGLConfig)i; 1453 } 1454 *num_config = i; 1455 return EGL_TRUE; 1456} 1457 1458EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 1459 EGLConfig *configs, EGLint config_size, 1460 EGLint *num_config) 1461{ 1462 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1463 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1464 1465 if (ggl_unlikely(num_config==0)) { 1466 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1467 } 1468 1469 if (ggl_unlikely(attrib_list==0)) { 1470 /* 1471 * A NULL attrib_list should be treated as though it was an empty 1472 * one (terminated with EGL_NONE) as defined in 1473 * section 3.4.1 "Querying Configurations" in the EGL specification. 1474 */ 1475 static const EGLint dummy = EGL_NONE; 1476 attrib_list = &dummy; 1477 } 1478 1479 int numAttributes = 0; 1480 int numConfigs = NELEM(gConfigs); 1481 uint32_t possibleMatch = (1<<numConfigs)-1; 1482 while(possibleMatch && *attrib_list != EGL_NONE) { 1483 numAttributes++; 1484 EGLint attr = *attrib_list++; 1485 EGLint val = *attrib_list++; 1486 for (int i=0 ; possibleMatch && i<numConfigs ; i++) { 1487 if (!(possibleMatch & (1<<i))) 1488 continue; 1489 if (isAttributeMatching(i, attr, val) == 0) { 1490 possibleMatch &= ~(1<<i); 1491 } 1492 } 1493 } 1494 1495 // now, handle the attributes which have a useful default value 1496 for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) { 1497 // see if this attribute was specified, if not, apply its 1498 // default value 1499 if (binarySearch<config_pair_t>( 1500 (config_pair_t const*)attrib_list, 1501 0, numAttributes-1, 1502 config_defaults[j].key) < 0) 1503 { 1504 for (int i=0 ; possibleMatch && i<numConfigs ; i++) { 1505 if (!(possibleMatch & (1<<i))) 1506 continue; 1507 if (isAttributeMatching(i, 1508 config_defaults[j].key, 1509 config_defaults[j].value) == 0) 1510 { 1511 possibleMatch &= ~(1<<i); 1512 } 1513 } 1514 } 1515 } 1516 1517 // return the configurations found 1518 int n=0; 1519 if (possibleMatch) { 1520 if (configs) { 1521 for (int i=0 ; config_size && i<numConfigs ; i++) { 1522 if (possibleMatch & (1<<i)) { 1523 *configs++ = (EGLConfig)i; 1524 config_size--; 1525 n++; 1526 } 1527 } 1528 } else { 1529 for (int i=0 ; i<numConfigs ; i++) { 1530 if (possibleMatch & (1<<i)) { 1531 n++; 1532 } 1533 } 1534 } 1535 } 1536 *num_config = n; 1537 return EGL_TRUE; 1538} 1539 1540EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 1541 EGLint attribute, EGLint *value) 1542{ 1543 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1544 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1545 1546 return getConfigAttrib(dpy, config, attribute, value); 1547} 1548 1549// ---------------------------------------------------------------------------- 1550// surfaces 1551// ---------------------------------------------------------------------------- 1552 1553EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 1554 NativeWindowType window, 1555 const EGLint *attrib_list) 1556{ 1557 return createWindowSurface(dpy, config, window, attrib_list); 1558} 1559 1560EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 1561 NativePixmapType pixmap, 1562 const EGLint *attrib_list) 1563{ 1564 return createPixmapSurface(dpy, config, pixmap, attrib_list); 1565} 1566 1567EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 1568 const EGLint *attrib_list) 1569{ 1570 return createPbufferSurface(dpy, config, attrib_list); 1571} 1572 1573EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) 1574{ 1575 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1576 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1577 if (eglSurface != EGL_NO_SURFACE) { 1578 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); 1579 if (!surface->isValid()) 1580 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1581 if (surface->dpy != dpy) 1582 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1583 if (surface->ctx) { 1584 // defer disconnect/delete until no longer current 1585 surface->zombie = true; 1586 } else { 1587 surface->disconnect(); 1588 delete surface; 1589 } 1590 } 1591 return EGL_TRUE; 1592} 1593 1594EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface, 1595 EGLint attribute, EGLint *value) 1596{ 1597 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1598 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1599 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface); 1600 if (!surface->isValid()) 1601 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1602 if (surface->dpy != dpy) 1603 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1604 1605 EGLBoolean ret = EGL_TRUE; 1606 switch (attribute) { 1607 case EGL_CONFIG_ID: 1608 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value); 1609 break; 1610 case EGL_WIDTH: 1611 *value = surface->getWidth(); 1612 break; 1613 case EGL_HEIGHT: 1614 *value = surface->getHeight(); 1615 break; 1616 case EGL_LARGEST_PBUFFER: 1617 // not modified for a window or pixmap surface 1618 break; 1619 case EGL_TEXTURE_FORMAT: 1620 *value = EGL_NO_TEXTURE; 1621 break; 1622 case EGL_TEXTURE_TARGET: 1623 *value = EGL_NO_TEXTURE; 1624 break; 1625 case EGL_MIPMAP_TEXTURE: 1626 *value = EGL_FALSE; 1627 break; 1628 case EGL_MIPMAP_LEVEL: 1629 *value = 0; 1630 break; 1631 case EGL_RENDER_BUFFER: 1632 // TODO: return the real RENDER_BUFFER here 1633 *value = EGL_BACK_BUFFER; 1634 break; 1635 case EGL_HORIZONTAL_RESOLUTION: 1636 // pixel/mm * EGL_DISPLAY_SCALING 1637 *value = surface->getHorizontalResolution(); 1638 break; 1639 case EGL_VERTICAL_RESOLUTION: 1640 // pixel/mm * EGL_DISPLAY_SCALING 1641 *value = surface->getVerticalResolution(); 1642 break; 1643 case EGL_PIXEL_ASPECT_RATIO: { 1644 // w/h * EGL_DISPLAY_SCALING 1645 int wr = surface->getHorizontalResolution(); 1646 int hr = surface->getVerticalResolution(); 1647 *value = (wr * EGL_DISPLAY_SCALING) / hr; 1648 } break; 1649 case EGL_SWAP_BEHAVIOR: 1650 *value = surface->getSwapBehavior(); 1651 break; 1652 default: 1653 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1654 } 1655 return ret; 1656} 1657 1658EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 1659 EGLContext share_list, const EGLint *attrib_list) 1660{ 1661 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1662 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1663 1664 ogles_context_t* gl = ogles_init(sizeof(egl_context_t)); 1665 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); 1666 1667 egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base); 1668 c->flags = egl_context_t::NEVER_CURRENT; 1669 c->dpy = dpy; 1670 c->config = config; 1671 c->read = 0; 1672 c->draw = 0; 1673 return (EGLContext)gl; 1674} 1675 1676EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 1677{ 1678 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1679 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1680 egl_context_t* c = egl_context_t::context(ctx); 1681 if (c->flags & egl_context_t::IS_CURRENT) 1682 setGlThreadSpecific(0); 1683 ogles_uninit((ogles_context_t*)ctx); 1684 return EGL_TRUE; 1685} 1686 1687EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1688 EGLSurface read, EGLContext ctx) 1689{ 1690 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1691 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1692 if (draw) { 1693 egl_surface_t* s = (egl_surface_t*)draw; 1694 if (!s->isValid()) 1695 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1696 if (s->dpy != dpy) 1697 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1698 // TODO: check that draw is compatible with the context 1699 } 1700 if (read && read!=draw) { 1701 egl_surface_t* s = (egl_surface_t*)read; 1702 if (!s->isValid()) 1703 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1704 if (s->dpy != dpy) 1705 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1706 // TODO: check that read is compatible with the context 1707 } 1708 1709 EGLContext current_ctx = EGL_NO_CONTEXT; 1710 1711 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) 1712 return setError(EGL_BAD_MATCH, EGL_FALSE); 1713 1714 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT)) 1715 return setError(EGL_BAD_MATCH, EGL_FALSE); 1716 1717 if (ctx == EGL_NO_CONTEXT) { 1718 // if we're detaching, we need the current context 1719 current_ctx = (EGLContext)getGlThreadSpecific(); 1720 } else { 1721 egl_context_t* c = egl_context_t::context(ctx); 1722 egl_surface_t* d = (egl_surface_t*)draw; 1723 egl_surface_t* r = (egl_surface_t*)read; 1724 if ((d && d->ctx && d->ctx != ctx) || 1725 (r && r->ctx && r->ctx != ctx)) { 1726 // one of the surface is bound to a context in another thread 1727 return setError(EGL_BAD_ACCESS, EGL_FALSE); 1728 } 1729 } 1730 1731 ogles_context_t* gl = (ogles_context_t*)ctx; 1732 if (makeCurrent(gl) == 0) { 1733 if (ctx) { 1734 egl_context_t* c = egl_context_t::context(ctx); 1735 egl_surface_t* d = (egl_surface_t*)draw; 1736 egl_surface_t* r = (egl_surface_t*)read; 1737 1738 if (c->draw) { 1739 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw); 1740 s->disconnect(); 1741 s->ctx = EGL_NO_CONTEXT; 1742 if (s->zombie) 1743 delete s; 1744 } 1745 if (c->read) { 1746 // FIXME: unlock/disconnect the read surface too 1747 } 1748 1749 c->draw = draw; 1750 c->read = read; 1751 1752 if (c->flags & egl_context_t::NEVER_CURRENT) { 1753 c->flags &= ~egl_context_t::NEVER_CURRENT; 1754 GLint w = 0; 1755 GLint h = 0; 1756 if (draw) { 1757 w = d->getWidth(); 1758 h = d->getHeight(); 1759 } 1760 ogles_surfaceport(gl, 0, 0); 1761 ogles_viewport(gl, 0, 0, w, h); 1762 ogles_scissor(gl, 0, 0, w, h); 1763 } 1764 if (d) { 1765 if (d->connect() == EGL_FALSE) { 1766 return EGL_FALSE; 1767 } 1768 d->ctx = ctx; 1769 d->bindDrawSurface(gl); 1770 } 1771 if (r) { 1772 // FIXME: lock/connect the read surface too 1773 r->ctx = ctx; 1774 r->bindReadSurface(gl); 1775 } 1776 } else { 1777 // if surfaces were bound to the context bound to this thread 1778 // mark then as unbound. 1779 if (current_ctx) { 1780 egl_context_t* c = egl_context_t::context(current_ctx); 1781 egl_surface_t* d = (egl_surface_t*)c->draw; 1782 egl_surface_t* r = (egl_surface_t*)c->read; 1783 if (d) { 1784 c->draw = 0; 1785 d->disconnect(); 1786 d->ctx = EGL_NO_CONTEXT; 1787 if (d->zombie) 1788 delete d; 1789 } 1790 if (r) { 1791 c->read = 0; 1792 r->ctx = EGL_NO_CONTEXT; 1793 // FIXME: unlock/disconnect the read surface too 1794 } 1795 } 1796 } 1797 return EGL_TRUE; 1798 } 1799 return setError(EGL_BAD_ACCESS, EGL_FALSE); 1800} 1801 1802EGLContext eglGetCurrentContext(void) 1803{ 1804 // eglGetCurrentContext returns the current EGL rendering context, 1805 // as specified by eglMakeCurrent. If no context is current, 1806 // EGL_NO_CONTEXT is returned. 1807 return (EGLContext)getGlThreadSpecific(); 1808} 1809 1810EGLSurface eglGetCurrentSurface(EGLint readdraw) 1811{ 1812 // eglGetCurrentSurface returns the read or draw surface attached 1813 // to the current EGL rendering context, as specified by eglMakeCurrent. 1814 // If no context is current, EGL_NO_SURFACE is returned. 1815 EGLContext ctx = (EGLContext)getGlThreadSpecific(); 1816 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE; 1817 egl_context_t* c = egl_context_t::context(ctx); 1818 if (readdraw == EGL_READ) { 1819 return c->read; 1820 } else if (readdraw == EGL_DRAW) { 1821 return c->draw; 1822 } 1823 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1824} 1825 1826EGLDisplay eglGetCurrentDisplay(void) 1827{ 1828 // eglGetCurrentDisplay returns the current EGL display connection 1829 // for the current EGL rendering context, as specified by eglMakeCurrent. 1830 // If no context is current, EGL_NO_DISPLAY is returned. 1831 EGLContext ctx = (EGLContext)getGlThreadSpecific(); 1832 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY; 1833 egl_context_t* c = egl_context_t::context(ctx); 1834 return c->dpy; 1835} 1836 1837EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1838 EGLint attribute, EGLint *value) 1839{ 1840 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1841 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1842 egl_context_t* c = egl_context_t::context(ctx); 1843 switch (attribute) { 1844 case EGL_CONFIG_ID: 1845 // Returns the ID of the EGL frame buffer configuration with 1846 // respect to which the context was created 1847 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value); 1848 } 1849 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1850} 1851 1852EGLBoolean eglWaitGL(void) 1853{ 1854 return EGL_TRUE; 1855} 1856 1857EGLBoolean eglWaitNative(EGLint engine) 1858{ 1859 return EGL_TRUE; 1860} 1861 1862EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1863{ 1864 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1865 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1866 1867 egl_surface_t* d = static_cast<egl_surface_t*>(draw); 1868 if (!d->isValid()) 1869 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1870 if (d->dpy != dpy) 1871 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1872 1873 // post the surface 1874 d->swapBuffers(); 1875 1876 // if it's bound to a context, update the buffer 1877 if (d->ctx != EGL_NO_CONTEXT) { 1878 d->bindDrawSurface((ogles_context_t*)d->ctx); 1879 // if this surface is also the read surface of the context 1880 // it is bound to, make sure to update the read buffer as well. 1881 // The EGL spec is a little unclear about this. 1882 egl_context_t* c = egl_context_t::context(d->ctx); 1883 if (c->read == draw) { 1884 d->bindReadSurface((ogles_context_t*)d->ctx); 1885 } 1886 } 1887 1888 return EGL_TRUE; 1889} 1890 1891EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1892 NativePixmapType target) 1893{ 1894 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1895 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1896 // TODO: eglCopyBuffers() 1897 return EGL_FALSE; 1898} 1899 1900EGLint eglGetError(void) 1901{ 1902 return getError(); 1903} 1904 1905const char* eglQueryString(EGLDisplay dpy, EGLint name) 1906{ 1907 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1908 return setError(EGL_BAD_DISPLAY, (const char*)0); 1909 1910 switch (name) { 1911 case EGL_VENDOR: 1912 return gVendorString; 1913 case EGL_VERSION: 1914 return gVersionString; 1915 case EGL_EXTENSIONS: 1916 return gExtensionsString; 1917 case EGL_CLIENT_APIS: 1918 return gClientApiString; 1919 } 1920 return setError(EGL_BAD_PARAMETER, (const char *)0); 1921} 1922 1923// ---------------------------------------------------------------------------- 1924// EGL 1.1 1925// ---------------------------------------------------------------------------- 1926 1927EGLBoolean eglSurfaceAttrib( 1928 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1929{ 1930 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1931 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1932 // TODO: eglSurfaceAttrib() 1933 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1934} 1935 1936EGLBoolean eglBindTexImage( 1937 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1938{ 1939 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1940 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1941 // TODO: eglBindTexImage() 1942 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1943} 1944 1945EGLBoolean eglReleaseTexImage( 1946 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1947{ 1948 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1949 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1950 // TODO: eglReleaseTexImage() 1951 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1952} 1953 1954EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1955{ 1956 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1957 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1958 // TODO: eglSwapInterval() 1959 return EGL_TRUE; 1960} 1961 1962// ---------------------------------------------------------------------------- 1963// EGL 1.2 1964// ---------------------------------------------------------------------------- 1965 1966EGLBoolean eglBindAPI(EGLenum api) 1967{ 1968 if (api != EGL_OPENGL_ES_API) 1969 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1970 return EGL_TRUE; 1971} 1972 1973EGLenum eglQueryAPI(void) 1974{ 1975 return EGL_OPENGL_ES_API; 1976} 1977 1978EGLBoolean eglWaitClient(void) 1979{ 1980 glFinish(); 1981 return EGL_TRUE; 1982} 1983 1984EGLBoolean eglReleaseThread(void) 1985{ 1986 // TODO: eglReleaseThread() 1987 return EGL_TRUE; 1988} 1989 1990EGLSurface eglCreatePbufferFromClientBuffer( 1991 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1992 EGLConfig config, const EGLint *attrib_list) 1993{ 1994 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1995 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1996 // TODO: eglCreatePbufferFromClientBuffer() 1997 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1998} 1999 2000// ---------------------------------------------------------------------------- 2001// EGL_EGLEXT_VERSION 3 2002// ---------------------------------------------------------------------------- 2003 2004void (*eglGetProcAddress (const char *procname))() 2005{ 2006 extention_map_t const * const map = gExtentionMap; 2007 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) { 2008 if (!strcmp(procname, map[i].name)) { 2009 return map[i].address; 2010 } 2011 } 2012 return NULL; 2013} 2014 2015EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 2016 const EGLint *attrib_list) 2017{ 2018 EGLBoolean result = EGL_FALSE; 2019 return result; 2020} 2021 2022EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 2023{ 2024 EGLBoolean result = EGL_FALSE; 2025 return result; 2026} 2027 2028EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 2029 EGLClientBuffer buffer, const EGLint *attrib_list) 2030{ 2031 if (egl_display_t::is_valid(dpy) == EGL_FALSE) { 2032 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 2033 } 2034 if (ctx != EGL_NO_CONTEXT) { 2035 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 2036 } 2037 if (target != EGL_NATIVE_BUFFER_ANDROID) { 2038 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 2039 } 2040 2041 ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer; 2042 2043 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) 2044 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 2045 2046 if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) 2047 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 2048 2049 switch (native_buffer->format) { 2050 case HAL_PIXEL_FORMAT_RGBA_8888: 2051 case HAL_PIXEL_FORMAT_RGBX_8888: 2052 case HAL_PIXEL_FORMAT_RGB_888: 2053 case HAL_PIXEL_FORMAT_RGB_565: 2054 case HAL_PIXEL_FORMAT_BGRA_8888: 2055 case HAL_PIXEL_FORMAT_RGBA_5551: 2056 case HAL_PIXEL_FORMAT_RGBA_4444: 2057 break; 2058 default: 2059 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 2060 } 2061 2062 native_buffer->common.incRef(&native_buffer->common); 2063 return (EGLImageKHR)native_buffer; 2064} 2065 2066EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 2067{ 2068 if (egl_display_t::is_valid(dpy) == EGL_FALSE) { 2069 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 2070 } 2071 2072 ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img; 2073 2074 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) 2075 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2076 2077 if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) 2078 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2079 2080 native_buffer->common.decRef(&native_buffer->common); 2081 2082 return EGL_TRUE; 2083} 2084 2085// ---------------------------------------------------------------------------- 2086// EGL_KHR_fence_sync 2087// ---------------------------------------------------------------------------- 2088 2089#define FENCE_SYNC_HANDLE ((EGLSyncKHR)0xFE4CE) 2090 2091EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, 2092 const EGLint *attrib_list) 2093{ 2094 if (egl_display_t::is_valid(dpy) == EGL_FALSE) { 2095 return setError(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR); 2096 } 2097 2098 if (type != EGL_SYNC_FENCE_KHR || 2099 (attrib_list != NULL && attrib_list[0] != EGL_NONE)) { 2100 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR); 2101 } 2102 2103 if (eglGetCurrentContext() == EGL_NO_CONTEXT) { 2104 return setError(EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 2105 } 2106 2107 // AGL is synchronous; nothing to do here. 2108 2109 return FENCE_SYNC_HANDLE; 2110} 2111 2112EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 2113{ 2114 if (sync != FENCE_SYNC_HANDLE) { 2115 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2116 } 2117 2118 return EGL_TRUE; 2119} 2120 2121EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, 2122 EGLTimeKHR timeout) 2123{ 2124 if (sync != FENCE_SYNC_HANDLE) { 2125 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2126 } 2127 2128 return EGL_CONDITION_SATISFIED_KHR; 2129} 2130 2131EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 2132 EGLint attribute, EGLint *value) 2133{ 2134 if (sync != FENCE_SYNC_HANDLE) { 2135 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2136 } 2137 2138 switch (attribute) { 2139 case EGL_SYNC_TYPE_KHR: 2140 *value = EGL_SYNC_FENCE_KHR; 2141 return EGL_TRUE; 2142 case EGL_SYNC_STATUS_KHR: 2143 *value = EGL_SIGNALED_KHR; 2144 return EGL_TRUE; 2145 case EGL_SYNC_CONDITION_KHR: 2146 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR; 2147 return EGL_TRUE; 2148 default: 2149 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 2150 } 2151} 2152 2153// ---------------------------------------------------------------------------- 2154// ANDROID extensions 2155// ---------------------------------------------------------------------------- 2156 2157EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 2158 EGLint left, EGLint top, EGLint width, EGLint height) 2159{ 2160 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 2161 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 2162 2163 egl_surface_t* d = static_cast<egl_surface_t*>(draw); 2164 if (!d->isValid()) 2165 return setError(EGL_BAD_SURFACE, EGL_FALSE); 2166 if (d->dpy != dpy) 2167 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 2168 2169 // post the surface 2170 d->setSwapRectangle(left, top, width, height); 2171 2172 return EGL_TRUE; 2173} 2174