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