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