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