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