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