1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifdef _WIN32 17 #undef EGLAPI 18 #define EGLAPI __declspec(dllexport) 19 #endif 20 21 #include <EGL/egl.h> 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <stdio.h> 25 #include "ThreadInfo.h" 26 #include <GLcommon/TranslatorIfaces.h> 27 #include <OpenglOsUtils/osDynLibrary.h> 28 29 #include "EglWindowSurface.h" 30 #include "EglPbufferSurface.h" 31 #include "EglPixmapSurface.h" 32 #include "EglGlobalInfo.h" 33 #include "EglThreadInfo.h" 34 #include "EglValidate.h" 35 #include "EglDisplay.h" 36 #include "EglContext.h" 37 #include "EglConfig.h" 38 #include "EglOsApi.h" 39 #include "ClientAPIExts.h" 40 41 #define MAJOR 1 42 #define MINOR 4 43 44 //declarations 45 46 EglImage *attachEGLImage(unsigned int imageId); 47 void detachEGLImage(unsigned int imageId); 48 GLEScontext* getGLESContext(); 49 50 #define tls_thread EglThreadInfo::get() 51 52 EglGlobalInfo* g_eglInfo = NULL; 53 android::Mutex s_eglLock; 54 55 void initGlobalInfo() 56 { 57 android::Mutex::Autolock mutex(s_eglLock); 58 if (!g_eglInfo) { 59 g_eglInfo = EglGlobalInfo::getInstance(); 60 } 61 } 62 63 static EGLiface s_eglIface = { 64 getGLESContext : getGLESContext, 65 eglAttachEGLImage:attachEGLImage, 66 eglDetachEGLImage:detachEGLImage 67 }; 68 69 /***************************************** supported extentions ***********************************************************************/ 70 71 //extentions 72 #define EGL_EXTENTIONS 2 73 74 //decleration 75 EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); 76 EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image); 77 78 // extentions descriptors 79 static ExtentionDescriptor s_eglExtentions[] = { 80 {"eglCreateImageKHR" ,(__eglMustCastToProperFunctionPointerType)eglCreateImageKHR}, 81 {"eglDestroyImageKHR",(__eglMustCastToProperFunctionPointerType)eglDestroyImageKHR} 82 }; 83 static int s_eglExtentionsSize = sizeof(s_eglExtentions) / 84 sizeof(ExtentionDescriptor); 85 86 /****************************************************************************************************************************************/ 87 //macros for accessing global egl info & tls objects 88 89 #define CURRENT_THREAD() do {} while (0); 90 91 #define RETURN_ERROR(ret,err) \ 92 CURRENT_THREAD() \ 93 if(tls_thread->getError() == EGL_SUCCESS) { \ 94 tls_thread->setError(err); \ 95 } \ 96 return ret; 97 98 #define VALIDATE_DISPLAY_RETURN(EGLDisplay,ret) \ 99 EglDisplay* dpy = g_eglInfo->getDisplay(EGLDisplay); \ 100 if(!dpy){ \ 101 RETURN_ERROR(ret,EGL_BAD_DISPLAY); \ 102 } \ 103 if(!dpy->isInitialize()) { \ 104 RETURN_ERROR(ret,EGL_NOT_INITIALIZED); \ 105 } 106 107 #define VALIDATE_CONFIG_RETURN(EGLConfig,ret) \ 108 EglConfig* cfg = dpy->getConfig(EGLConfig); \ 109 if(!cfg) { \ 110 RETURN_ERROR(ret,EGL_BAD_CONFIG); \ 111 } 112 113 #define VALIDATE_SURFACE_RETURN(EGLSurface,ret,varName) \ 114 SurfacePtr varName = dpy->getSurface(EGLSurface); \ 115 if(!varName.Ptr()) { \ 116 RETURN_ERROR(ret,EGL_BAD_SURFACE); \ 117 } 118 119 #define VALIDATE_CONTEXT_RETURN(EGLContext,ret) \ 120 ContextPtr ctx = dpy->getContext(EGLContext); \ 121 if(!ctx.Ptr()) { \ 122 RETURN_ERROR(ret,EGL_BAD_CONTEXT); \ 123 } 124 125 126 #define VALIDATE_DISPLAY(EGLDisplay) \ 127 VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE) 128 129 #define VALIDATE_CONFIG(EGLConfig) \ 130 VALIDATE_CONFIG_RETURN(EGLConfig,EGL_FALSE) 131 132 #define VALIDATE_SURFACE(EGLSurface,varName) \ 133 VALIDATE_SURFACE_RETURN(EGLSurface,EGL_FALSE,varName) 134 135 #define VALIDATE_CONTEXT(EGLContext) \ 136 VALIDATE_CONTEXT_RETURN(EGLContext,EGL_FALSE) 137 138 139 GLEScontext* getGLESContext() 140 { 141 ThreadInfo* thread = getThreadInfo(); 142 return thread->glesContext; 143 } 144 145 EGLAPI EGLint EGLAPIENTRY eglGetError(void) { 146 CURRENT_THREAD(); 147 EGLint err = tls_thread->getError(); 148 tls_thread->setError(EGL_SUCCESS); 149 return err; 150 } 151 152 EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { 153 EglDisplay* dpy = NULL; 154 EGLNativeInternalDisplayType internalDisplay = NULL; 155 156 initGlobalInfo(); 157 158 if ((dpy = g_eglInfo->getDisplay(display_id))) { 159 return dpy; 160 } else { 161 162 if( display_id == EGL_DEFAULT_DISPLAY) { 163 internalDisplay = g_eglInfo->getDefaultNativeDisplay(); 164 } else { 165 internalDisplay = g_eglInfo->generateInternalDisplay(display_id); 166 } 167 168 dpy = g_eglInfo->addDisplay(display_id,internalDisplay); 169 if(dpy) return dpy; 170 return EGL_NO_DISPLAY; 171 } 172 } 173 174 175 #define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces" 176 177 static __translator_getGLESIfaceFunc loadIfaces(const char* libName){ 178 osUtils::dynLibrary* libGLES = osUtils::dynLibrary::open(libName); 179 180 if(!libGLES) return NULL; 181 __translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc)libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME); 182 if(!func) return NULL; 183 return func; 184 } 185 186 #ifdef _WIN32 187 #define LIB_GLES_CM_NAME "libGLES_CM_translator" 188 #define LIB_GLES_V2_NAME "libGLES_V2_translator" 189 #elif __linux__ 190 #define LIB_GLES_CM_NAME "libGLES_CM_translator.so" 191 #define LIB_GLES_V2_NAME "libGLES_V2_translator.so" 192 #elif __APPLE__ 193 #define LIB_GLES_CM_NAME "libGLES_CM_translator.dylib" 194 #define LIB_GLES_V2_NAME "libGLES_V2_translator.dylib" 195 #endif 196 197 EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) { 198 199 initGlobalInfo(); 200 201 EglDisplay* dpy = g_eglInfo->getDisplay(display); 202 if(!dpy) { 203 RETURN_ERROR(EGL_FALSE,EGL_BAD_DISPLAY); 204 } 205 206 if(major) *major = MAJOR; 207 if(minor) *minor = MINOR; 208 209 __translator_getGLESIfaceFunc func = NULL; 210 int renderableType = EGL_OPENGL_ES_BIT; 211 212 if(!g_eglInfo->getIface(GLES_1_1)) { 213 func = loadIfaces(LIB_GLES_CM_NAME); 214 if(func){ 215 g_eglInfo->setIface(func(&s_eglIface),GLES_1_1); 216 } else { 217 fprintf(stderr,"could not find ifaces for GLES CM 1.1\n"); 218 return EGL_FALSE; 219 } 220 } 221 if(!g_eglInfo->getIface(GLES_2_0)) { 222 func = loadIfaces(LIB_GLES_V2_NAME); 223 if(func){ 224 renderableType |= EGL_OPENGL_ES2_BIT; 225 g_eglInfo->setIface(func(&s_eglIface),GLES_2_0); 226 } else { 227 fprintf(stderr,"could not find ifaces for GLES 2.0\n"); 228 } 229 } 230 dpy->initialize(renderableType); 231 return EGL_TRUE; 232 } 233 234 EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay display) { 235 VALIDATE_DISPLAY(display); 236 dpy->terminate(); 237 return EGL_TRUE; 238 } 239 240 EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay display, EGLint name) { 241 VALIDATE_DISPLAY(display); 242 static const char* vendor = "Google"; 243 static const char* version = "1.4"; 244 static const char* extensions = "EGL_KHR_image_base EGL_KHR_gl_texture_2D_image"; 245 if(!EglValidate::stringName(name)) { 246 RETURN_ERROR(NULL,EGL_BAD_PARAMETER); 247 } 248 switch(name) { 249 case EGL_VENDOR: 250 return vendor; 251 case EGL_VERSION: 252 return version; 253 case EGL_EXTENSIONS: 254 return extensions; 255 } 256 return NULL; 257 } 258 259 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay display, EGLConfig *configs, 260 EGLint config_size, EGLint *num_config) { 261 VALIDATE_DISPLAY(display); 262 if(!num_config) { 263 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); 264 } 265 266 if(configs == NULL) { 267 *num_config = dpy->nConfigs(); 268 } else { 269 *num_config = dpy->getConfigs(configs,config_size); 270 } 271 272 return EGL_TRUE; 273 } 274 275 EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint *attrib_list, 276 EGLConfig *configs, EGLint config_size, 277 EGLint *num_config) { 278 VALIDATE_DISPLAY(display); 279 if(!num_config) { 280 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); 281 } 282 283 //selection defaults 284 EGLint surface_type = EGL_WINDOW_BIT; 285 EGLint renderable_type = EGL_OPENGL_ES_BIT; 286 EGLBoolean bind_to_tex_rgb = EGL_DONT_CARE; 287 EGLBoolean bind_to_tex_rgba = EGL_DONT_CARE; 288 EGLenum caveat = EGL_DONT_CARE; 289 EGLint config_id = EGL_DONT_CARE; 290 EGLBoolean native_renderable = EGL_DONT_CARE; 291 EGLint native_visual_type = EGL_DONT_CARE; 292 EGLint max_swap_interval = EGL_DONT_CARE; 293 EGLint min_swap_interval = EGL_DONT_CARE; 294 EGLint trans_red_val = EGL_DONT_CARE; 295 EGLint trans_green_val = EGL_DONT_CARE; 296 EGLint trans_blue_val = EGL_DONT_CARE; 297 EGLenum transparent_type = EGL_NONE; 298 EGLint buffer_size = 0; 299 EGLint red_size = 0; 300 EGLint green_size = 0; 301 EGLint blue_size = 0; 302 EGLint alpha_size = 0; 303 EGLint depth_size = 0; 304 EGLint frame_buffer_level = 0; 305 EGLint sample_buffers_num = 0; 306 EGLint samples_per_pixel = 0; 307 EGLint stencil_size = 0; 308 309 if(!EglValidate::noAttribs(attrib_list)) { //there are attribs 310 int i = 0 ; 311 bool hasConfigId = false; 312 while(attrib_list[i] != EGL_NONE && !hasConfigId) { 313 switch(attrib_list[i]) { 314 case EGL_MAX_PBUFFER_WIDTH: 315 case EGL_MAX_PBUFFER_HEIGHT: 316 case EGL_MAX_PBUFFER_PIXELS: 317 case EGL_NATIVE_VISUAL_ID: 318 break; //we dont care from those selection crateria 319 case EGL_LEVEL: 320 if(attrib_list[i+1] == EGL_DONT_CARE) { 321 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 322 } 323 frame_buffer_level = attrib_list[i+1]; 324 break; 325 case EGL_BUFFER_SIZE: 326 if(attrib_list[i+1] < 0) { 327 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 328 } 329 buffer_size = attrib_list[i+1]; 330 break; 331 case EGL_RED_SIZE: 332 if(attrib_list[i+1] < 0) { 333 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 334 } 335 red_size = attrib_list[i+1]; 336 break; 337 case EGL_GREEN_SIZE: 338 if(attrib_list[i+1] < 0) { 339 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 340 } 341 green_size = attrib_list[i+1]; 342 break; 343 case EGL_BLUE_SIZE: 344 if(attrib_list[i+1] < 0) { 345 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 346 } 347 blue_size = attrib_list[i+1]; 348 break; 349 case EGL_ALPHA_SIZE: 350 if(attrib_list[i+1] < 0) { 351 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 352 } 353 alpha_size = attrib_list[i+1]; 354 break; 355 case EGL_BIND_TO_TEXTURE_RGB: 356 bind_to_tex_rgb = attrib_list[i+1]; 357 break; 358 case EGL_BIND_TO_TEXTURE_RGBA: 359 bind_to_tex_rgba = attrib_list[i+1]; 360 break; 361 case EGL_CONFIG_CAVEAT: 362 if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_SLOW_CONFIG && attrib_list[i+1] != EGL_NON_CONFORMANT_CONFIG) { 363 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 364 } 365 caveat = attrib_list[i+1]; 366 break; 367 case EGL_CONFIG_ID: 368 if(attrib_list[i+1] < 0) { 369 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 370 } 371 config_id = attrib_list[i+1]; 372 hasConfigId = true; 373 break; 374 case EGL_DEPTH_SIZE: 375 if(attrib_list[i+1] < 0) { 376 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 377 } 378 depth_size = attrib_list[i+1]; 379 break; 380 case EGL_MAX_SWAP_INTERVAL: 381 if(attrib_list[i+1] < 0) { 382 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 383 } 384 max_swap_interval = attrib_list[i+1]; 385 break; 386 case EGL_MIN_SWAP_INTERVAL: 387 if(attrib_list[i+1] < 0) { 388 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 389 } 390 min_swap_interval = attrib_list[i+1]; 391 break; 392 case EGL_NATIVE_RENDERABLE: 393 native_renderable = attrib_list[i+1]; 394 break; 395 case EGL_RENDERABLE_TYPE: 396 renderable_type = attrib_list[i+1]; 397 break; 398 case EGL_NATIVE_VISUAL_TYPE: 399 native_visual_type = attrib_list[i+1]; 400 break; 401 if(attrib_list[i+1] < 0 || attrib_list[i+1] > 1 ) { 402 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 403 } 404 case EGL_SAMPLE_BUFFERS: 405 sample_buffers_num = attrib_list[i+1]; 406 break; 407 if(attrib_list[i+1] < 0) { 408 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 409 } 410 case EGL_SAMPLES: 411 if(attrib_list[i+1] < 0) { 412 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 413 } 414 samples_per_pixel = attrib_list[i+1]; 415 break; 416 case EGL_STENCIL_SIZE: 417 if(attrib_list[i+1] < 0) { 418 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 419 } 420 stencil_size = attrib_list[i+1]; 421 break; 422 case EGL_SURFACE_TYPE: 423 surface_type = attrib_list[i+1]; 424 break; 425 case EGL_TRANSPARENT_TYPE: 426 if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_TRANSPARENT_RGB ) { 427 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 428 } 429 transparent_type = attrib_list[i+1]; 430 break; 431 case EGL_TRANSPARENT_RED_VALUE: 432 trans_red_val = attrib_list[i+1]; 433 break; 434 case EGL_TRANSPARENT_GREEN_VALUE: 435 trans_green_val = attrib_list[i+1]; 436 break; 437 case EGL_TRANSPARENT_BLUE_VALUE: 438 trans_blue_val = attrib_list[i+1]; 439 break; 440 default: 441 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 442 } 443 i+=2; 444 } 445 if(hasConfigId) { 446 EglConfig* pConfig = dpy->getConfig(config_id); 447 if(pConfig) { 448 if(configs) { 449 configs[0] = static_cast<EGLConfig>(pConfig); 450 } 451 *num_config = 1; 452 return EGL_TRUE; 453 } else { 454 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 455 } 456 } 457 } 458 EGLNativePixelFormatType tmpfrmt = PIXEL_FORMAT_INITIALIZER; 459 EglConfig dummy(red_size,green_size,blue_size,alpha_size,caveat,config_id,depth_size, 460 frame_buffer_level,0,0,0,native_renderable,renderable_type,0,native_visual_type, 461 samples_per_pixel,stencil_size,surface_type,transparent_type, 462 trans_red_val,trans_green_val,trans_blue_val,tmpfrmt); 463 464 *num_config = dpy->chooseConfigs(dummy,configs,config_size); 465 466 467 return EGL_TRUE; 468 } 469 470 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay display, EGLConfig config, 471 EGLint attribute, EGLint *value) { 472 VALIDATE_DISPLAY(display); 473 VALIDATE_CONFIG(config); 474 if(!EglValidate::confAttrib(attribute)){ 475 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 476 } 477 return cfg->getConfAttrib(attribute,value)? EGL_TRUE:EGL_FALSE; 478 } 479 480 EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay display, EGLConfig config, 481 EGLNativeWindowType win, 482 const EGLint *attrib_list) { 483 VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); 484 VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); 485 486 if(!(cfg->surfaceType() & EGL_WINDOW_BIT)) { 487 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); 488 } 489 if(!EglOS::validNativeWin(dpy->nativeType(),win)) { 490 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_NATIVE_WINDOW); 491 } 492 if(!EglValidate::noAttribs(attrib_list)) { 493 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); 494 } 495 if(EglWindowSurface::alreadyAssociatedWithConfig(win)) { 496 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 497 } 498 499 unsigned int width,height; 500 if(!EglOS::checkWindowPixelFormatMatch(dpy->nativeType(),win,cfg,&width,&height)) { 501 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 502 } 503 SurfacePtr wSurface(new EglWindowSurface(dpy, win,cfg,width,height)); 504 if(!wSurface.Ptr()) { 505 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 506 } 507 return dpy->addSurface(wSurface); 508 } 509 510 EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, 511 const EGLint *attrib_list) { 512 VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); 513 VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); 514 if(!(cfg->surfaceType() & EGL_PBUFFER_BIT)) { 515 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); 516 } 517 518 519 SurfacePtr pbSurface(new EglPbufferSurface(dpy,cfg)); 520 if(!pbSurface.Ptr()) { 521 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 522 } 523 524 if(!EglValidate::noAttribs(attrib_list)) { //there are attribs 525 int i = 0 ; 526 while(attrib_list[i] != EGL_NONE) { 527 if(!pbSurface->setAttrib(attrib_list[i],attrib_list[i+1])) { 528 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); 529 } 530 i+=2; 531 } 532 } 533 534 EGLint width,height,largest,texTarget,texFormat; 535 EglPbufferSurface* tmpPbSurfacePtr = static_cast<EglPbufferSurface*>(pbSurface.Ptr()); 536 tmpPbSurfacePtr->getDim(&width,&height,&largest); 537 tmpPbSurfacePtr->getTexInfo(&texTarget,&texFormat); 538 539 if(!EglValidate::pbufferAttribs(width,height,texFormat == EGL_NO_TEXTURE,texTarget == EGL_NO_TEXTURE)) { 540 //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad_value 541 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); 542 } 543 544 EGLNativeSurfaceType pb = EglOS::createPbufferSurface(dpy->nativeType(),cfg,tmpPbSurfacePtr); 545 if(!pb) { 546 //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad value 547 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); 548 } 549 550 tmpPbSurfacePtr->setNativePbuffer(pb); 551 return dpy->addSurface(pbSurface); 552 } 553 554 EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay display, EGLConfig config, 555 EGLNativePixmapType pixmap, 556 const EGLint *attrib_list) { 557 VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); 558 VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); 559 if(!(cfg->surfaceType() & EGL_PIXMAP_BIT)) { 560 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); 561 } 562 if(!EglValidate::noAttribs(attrib_list)) { 563 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); 564 } 565 if(EglPixmapSurface::alreadyAssociatedWithConfig(pixmap)) { 566 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 567 } 568 569 unsigned int width,height; 570 if(!EglOS::checkPixmapPixelFormatMatch(dpy->nativeType(),pixmap,cfg,&width,&height)) { 571 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 572 } 573 SurfacePtr pixSurface(new EglPixmapSurface(dpy, pixmap,cfg)); 574 if(!pixSurface.Ptr()) { 575 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); 576 } 577 578 return dpy->addSurface(pixSurface); 579 } 580 581 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface) { 582 VALIDATE_DISPLAY(display); 583 SurfacePtr srfc = dpy->getSurface(surface); 584 if(!srfc.Ptr()) { 585 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 586 } 587 588 dpy->removeSurface(surface); 589 return EGL_TRUE; 590 } 591 592 EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay display, EGLSurface surface, 593 EGLint attribute, EGLint *value) { 594 VALIDATE_DISPLAY(display); 595 VALIDATE_SURFACE(surface,srfc); 596 597 if(!srfc->getAttrib(attribute,value)) { 598 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 599 } 600 return EGL_TRUE; 601 } 602 603 EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay display, EGLSurface surface, 604 EGLint attribute, EGLint value) { 605 VALIDATE_DISPLAY(display); 606 VALIDATE_SURFACE(surface,srfc); 607 if(!srfc->setAttrib(attribute,value)) { 608 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 609 } 610 return EGL_TRUE; 611 } 612 613 EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config, 614 EGLContext share_context, 615 const EGLint *attrib_list) { 616 VALIDATE_DISPLAY_RETURN(display,EGL_NO_CONTEXT); 617 VALIDATE_CONFIG_RETURN(config,EGL_NO_CONTEXT); 618 619 GLESVersion version = GLES_1_1; 620 if(!EglValidate::noAttribs(attrib_list)) { 621 int i = 0; 622 while(attrib_list[i] != EGL_NONE) { 623 switch(attrib_list[i]) { 624 case EGL_CONTEXT_CLIENT_VERSION: 625 if(attrib_list[i+1] == 2) { 626 version = GLES_2_0; 627 } else { 628 version = GLES_1_1; 629 } 630 break; 631 default: 632 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); 633 } 634 i+=2; 635 } 636 } 637 GLESiface* iface = g_eglInfo->getIface(version); 638 GLEScontext* glesCtx = NULL; 639 if(iface) { 640 glesCtx = iface->createGLESContext(); 641 } else { // there is no interface for this gles version 642 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); 643 } 644 645 ContextPtr sharedCtxPtr; 646 EGLNativeContextType nativeShared = NULL; 647 if(share_context != EGL_NO_CONTEXT) { 648 sharedCtxPtr = dpy->getContext(share_context); 649 if(!sharedCtxPtr.Ptr()) { 650 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT); 651 } 652 nativeShared = sharedCtxPtr->nativeType(); 653 } 654 655 EGLNativeContextType globalSharedContext = dpy->getGlobalSharedContext(); 656 EGLNativeContextType nativeContext = EglOS::createContext(dpy->nativeType(),cfg,globalSharedContext); 657 658 if(nativeContext) { 659 ContextPtr ctx(new EglContext(dpy, nativeContext,sharedCtxPtr,cfg,glesCtx,version,dpy->getManager(version))); 660 return dpy->addContext(ctx); 661 } else { 662 iface->deleteGLESContext(glesCtx); 663 } 664 665 return EGL_NO_CONTEXT; 666 } 667 668 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context) { 669 VALIDATE_DISPLAY(display); 670 VALIDATE_CONTEXT(context); 671 672 dpy->removeContext(context); 673 return EGL_TRUE; 674 } 675 676 EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw, 677 EGLSurface read, EGLContext context) { 678 VALIDATE_DISPLAY(display); 679 680 681 bool releaseContext = EglValidate::releaseContext(context,read,draw); 682 if(!releaseContext && EglValidate::badContextMatch(context,read,draw)) { 683 RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH); 684 } 685 686 ThreadInfo* thread = getThreadInfo(); 687 ContextPtr prevCtx = thread->eglContext; 688 689 if(releaseContext) { //releasing current context 690 if(prevCtx.Ptr()) { 691 g_eglInfo->getIface(prevCtx->version())->flush(); 692 if(!EglOS::makeCurrent(dpy->nativeType(),NULL,NULL,NULL)) { 693 RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); 694 } 695 thread->updateInfo(ContextPtr(NULL),dpy,NULL,ShareGroupPtr(NULL),dpy->getManager(prevCtx->version())); 696 } 697 } else { //assining new context 698 VALIDATE_CONTEXT(context); 699 VALIDATE_SURFACE(draw,newDrawSrfc); 700 VALIDATE_SURFACE(read,newReadSrfc); 701 702 EglSurface* newDrawPtr = newDrawSrfc.Ptr(); 703 EglSurface* newReadPtr = newReadSrfc.Ptr(); 704 ContextPtr newCtx = ctx; 705 706 if (newCtx.Ptr() && prevCtx.Ptr()) { 707 if (newCtx.Ptr() == prevCtx.Ptr()) { 708 if (newDrawPtr == prevCtx->draw().Ptr() && 709 newReadPtr == prevCtx->read().Ptr()) { 710 // nothing to do 711 return EGL_TRUE; 712 } 713 } 714 else { 715 // Make sure previous context is detached from surfaces 716 releaseContext = true; 717 } 718 } 719 720 //surfaces compitability check 721 if(!((*ctx->getConfig()).compitableWith((*newDrawPtr->getConfig()))) || 722 !((*ctx->getConfig()).compitableWith((*newReadPtr->getConfig())))) { 723 RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH); 724 } 725 726 EGLNativeInternalDisplayType nativeDisplay = dpy->nativeType(); 727 EGLNativeSurfaceType nativeRead = newReadPtr->native(); 728 EGLNativeSurfaceType nativeDraw = newDrawPtr->native(); 729 //checking native window validity 730 if(newReadPtr->type() == EglSurface::WINDOW && !EglOS::validNativeWin(nativeDisplay,nativeRead)) { 731 RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); 732 } 733 if(newDrawPtr->type() == EglSurface::WINDOW && !EglOS::validNativeWin(nativeDisplay,nativeDraw)) { 734 RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); 735 } 736 737 //checking native pixmap validity 738 if(newReadPtr->type() == EglSurface::PIXMAP && !EglOS::validNativePixmap(nativeDisplay,nativeRead)) { 739 RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); 740 } 741 if(newDrawPtr->type() == EglSurface::PIXMAP && !EglOS::validNativePixmap(nativeDisplay,nativeDraw)) { 742 RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); 743 } 744 if(prevCtx.Ptr()) { 745 g_eglInfo->getIface(prevCtx->version())->flush(); 746 } 747 if(!EglOS::makeCurrent(dpy->nativeType(),newReadPtr,newDrawPtr,newCtx->nativeType())) { 748 RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); 749 } 750 //TODO: handle the following errors 751 // EGL_BAD_CURRENT_SURFACE , EGL_CONTEXT_LOST , EGL_BAD_ACCESS 752 753 thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version())); 754 newCtx->setSurfaces(newReadSrfc,newDrawSrfc); 755 g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(),newCtx->getShareGroup()); 756 757 // Initialize the GLES extension function table used in 758 // eglGetProcAddress for the context's GLES version if not 759 // yet initialized. We initialize it here to make sure we call the 760 // GLES getProcAddress after when a context is bound. 761 g_eglInfo->initClientExtFuncTable(newCtx->version()); 762 } 763 764 // release previous context surface binding 765 if(prevCtx.Ptr() && releaseContext) { 766 prevCtx->setSurfaces(SurfacePtr(NULL),SurfacePtr(NULL)); 767 } 768 769 return EGL_TRUE; 770 } 771 772 EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay display, EGLContext context, 773 EGLint attribute, EGLint *value) { 774 VALIDATE_DISPLAY(display); 775 VALIDATE_CONTEXT(context); 776 777 if(!ctx->getAttrib(attribute,value)){ 778 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); 779 } 780 return EGL_TRUE; 781 } 782 783 EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay display, EGLSurface surface) { 784 VALIDATE_DISPLAY(display); 785 VALIDATE_SURFACE(surface,Srfc); 786 ThreadInfo* thread = getThreadInfo(); 787 ContextPtr currentCtx = thread->eglContext; 788 789 790 //if surface not window return 791 if(Srfc->type() != EglSurface::WINDOW){ 792 RETURN_ERROR(EGL_TRUE,EGL_SUCCESS); 793 } 794 795 if(!currentCtx.Ptr() || !currentCtx->usingSurface(Srfc) || !EglOS::validNativeWin(dpy->nativeType(),Srfc.Ptr()->native())) { 796 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 797 } 798 799 EglOS::swapBuffers(dpy->nativeType(),Srfc->native()); 800 return EGL_TRUE; 801 } 802 803 EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay display, EGLint interval) { 804 VALIDATE_DISPLAY(display); 805 ThreadInfo* thread = getThreadInfo(); 806 ContextPtr currCtx = thread->eglContext; 807 if(currCtx.Ptr()) { 808 if(!currCtx->read().Ptr() || !currCtx->draw().Ptr() || currCtx->draw()->type()!=EglSurface::WINDOW) { 809 RETURN_ERROR(EGL_FALSE,EGL_BAD_CURRENT_SURFACE); 810 } 811 EglOS::swapInterval(dpy->nativeType(),currCtx->draw()->native(),interval); 812 } else { 813 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 814 } 815 return EGL_TRUE; 816 } 817 818 819 EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) { 820 ThreadInfo* thread = getThreadInfo(); 821 EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); 822 ContextPtr ctx = thread->eglContext; 823 if(dpy && ctx.Ptr()){ 824 // This double check is required because a context might still be current after it is destroyed - in which case 825 // its handle should be invalid, that is EGL_NO_CONTEXT should be returned even though the context is current 826 EGLContext c = (EGLContext)ctx->getHndl(); 827 if(dpy->getContext(c).Ptr()) 828 { 829 return c; 830 } 831 } 832 return EGL_NO_CONTEXT; 833 } 834 835 EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { 836 if(!EglValidate::surfaceTarget(readdraw)) return EGL_NO_SURFACE; 837 838 ThreadInfo* thread = getThreadInfo(); 839 EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); 840 ContextPtr ctx = thread->eglContext; 841 842 if(dpy && ctx.Ptr()) { 843 SurfacePtr surface = readdraw == EGL_READ ? ctx->read() : ctx->draw(); 844 if(surface.Ptr()) 845 { 846 // This double check is required because a surface might still be 847 // current after it is destroyed - in which case its handle should 848 // be invalid, that is EGL_NO_SURFACE should be returned even 849 // though the surface is current. 850 EGLSurface s = (EGLSurface)surface->getHndl(); 851 surface = dpy->getSurface(s); 852 if(surface.Ptr()) 853 { 854 return s; 855 } 856 } 857 } 858 return EGL_NO_SURFACE; 859 } 860 861 EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { 862 ThreadInfo* thread = getThreadInfo(); 863 return (thread->eglContext.Ptr()) ? thread->eglDisplay : EGL_NO_DISPLAY; 864 } 865 866 EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void) { 867 EGLenum api = eglQueryAPI(); 868 eglBindAPI(EGL_OPENGL_ES_API); 869 return eglWaitClient(); 870 } 871 872 EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { 873 if(!EglValidate::engine(engine)) { 874 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); 875 } 876 ThreadInfo* thread = getThreadInfo(); 877 ContextPtr currCtx = thread->eglContext; 878 EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); 879 if(currCtx.Ptr()) { 880 SurfacePtr read = currCtx->read(); 881 SurfacePtr draw = currCtx->draw(); 882 883 EGLNativeInternalDisplayType nativeDisplay = dpy->nativeType(); 884 if(read.Ptr()) { 885 if(read->type() == EglSurface::WINDOW && 886 !EglOS::validNativeWin(nativeDisplay,read->native())) { 887 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 888 } 889 if(read->type() == EglSurface::PIXMAP && 890 !EglOS::validNativePixmap(nativeDisplay,read->native())) { 891 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 892 } 893 } 894 if(draw.Ptr()) { 895 if(draw->type() == EglSurface::WINDOW && 896 !EglOS::validNativeWin(nativeDisplay,draw->native())) { 897 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 898 } 899 if(draw->type() == EglSurface::PIXMAP && 900 !EglOS::validNativePixmap(nativeDisplay,draw->native())) { 901 RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); 902 } 903 } 904 } 905 EglOS::waitNative(); 906 return EGL_TRUE; 907 } 908 909 EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { 910 if(!EglValidate::supportedApi(api)) { 911 RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); 912 } 913 CURRENT_THREAD(); 914 tls_thread->setApi(api); 915 return EGL_TRUE; 916 } 917 918 EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) { 919 CURRENT_THREAD(); 920 return tls_thread->getApi(); 921 } 922 923 EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void) { 924 ThreadInfo* thread = getThreadInfo(); 925 ContextPtr currCtx = thread->eglContext; 926 if(currCtx.Ptr()) { 927 if(!currCtx->read().Ptr() || !currCtx->draw().Ptr()) { 928 RETURN_ERROR(EGL_FALSE,EGL_BAD_CURRENT_SURFACE); 929 } 930 g_eglInfo->getIface(currCtx->version())->finish(); 931 } 932 return EGL_TRUE; 933 } 934 935 EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) { 936 ThreadInfo* thread = getThreadInfo(); 937 EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); 938 return eglMakeCurrent(dpy,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); 939 } 940 941 EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY 942 eglGetProcAddress(const char *procname){ 943 __eglMustCastToProperFunctionPointerType retVal = NULL; 944 945 initGlobalInfo(); 946 947 if(!strncmp(procname,"egl",3)) { //EGL proc 948 for(int i=0;i < s_eglExtentionsSize;i++){ 949 if(strcmp(procname,s_eglExtentions[i].name) == 0){ 950 retVal = s_eglExtentions[i].address; 951 break; 952 } 953 } 954 } 955 else { 956 // Look at the clientAPI (GLES) supported extension 957 // function table. 958 retVal = ClientAPIExts::getProcAddress(procname); 959 } 960 return retVal; 961 } 962 963 //not supported for now 964 /************************* NOT SUPPORTED FOR NOW ***********************/ 965 EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer( 966 EGLDisplay display, EGLenum buftype, EGLClientBuffer buffer, 967 EGLConfig config, const EGLint *attrib_list) { 968 VALIDATE_DISPLAY(display); 969 VALIDATE_CONFIG(config); 970 //we do not support for now openVG, and the only client API resources which may be bound in this fashion are OpenVG 971 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_PARAMETER); 972 } 973 974 EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay display, EGLSurface surface, 975 EGLNativePixmapType target) { 976 VALIDATE_DISPLAY(display); 977 VALIDATE_SURFACE(surface,srfc); 978 if(!EglOS::validNativePixmap(dpy->nativeType(),NULL)) { 979 RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); 980 } 981 982 //we do not need to support this for android , since we are not gonna use pixmaps 983 RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); 984 } 985 986 /***********************************************************************/ 987 988 989 990 //do last ( only if needed) 991 /*********************************************************************************************************/ 992 EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { 993 //TODO: 994 return 0; 995 } 996 997 EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { 998 //TODO: 999 return 0; 1000 } 1001 /*********************************************************************************************************/ 1002 1003 1004 /************************** KHR IMAGE *************************************************************/ 1005 EglImage *attachEGLImage(unsigned int imageId) 1006 { 1007 ThreadInfo* thread = getThreadInfo(); 1008 EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); 1009 ContextPtr ctx = thread->eglContext; 1010 if (ctx.Ptr()) { 1011 ImagePtr img = dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId)); 1012 if(img.Ptr()) { 1013 ctx->attachImage(imageId,img); 1014 return img.Ptr(); 1015 } 1016 } 1017 return NULL; 1018 } 1019 1020 void detachEGLImage(unsigned int imageId) 1021 { 1022 ThreadInfo* thread = getThreadInfo(); 1023 EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); 1024 ContextPtr ctx = thread->eglContext; 1025 if (ctx.Ptr()) { 1026 ctx->detachImage(imageId); 1027 } 1028 } 1029 1030 1031 EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) 1032 { 1033 VALIDATE_DISPLAY(display); 1034 VALIDATE_CONTEXT(context); 1035 1036 // We only support EGL_GL_TEXTURE_2D images 1037 if (target != EGL_GL_TEXTURE_2D_KHR) { 1038 RETURN_ERROR(EGL_NO_IMAGE_KHR,EGL_BAD_PARAMETER); 1039 } 1040 1041 ThreadInfo* thread = getThreadInfo(); 1042 ShareGroupPtr sg = thread->shareGroup; 1043 if (sg.Ptr() != NULL) { 1044 unsigned int globalTexName = sg->getGlobalName(TEXTURE, (unsigned int)buffer); 1045 if (!globalTexName) return EGL_NO_IMAGE_KHR; 1046 1047 ImagePtr img( new EglImage() ); 1048 if (img.Ptr() != NULL) { 1049 1050 ObjectDataPtr objData = sg->getObjectData(TEXTURE, (unsigned int)buffer); 1051 if (!objData.Ptr()) return EGL_NO_IMAGE_KHR; 1052 1053 TextureData *texData = (TextureData *)objData.Ptr(); 1054 if(!texData->width || !texData->height) return EGL_NO_IMAGE_KHR; 1055 img->width = texData->width; 1056 img->height = texData->height; 1057 img->border = texData->border; 1058 img->internalFormat = texData->internalFormat; 1059 img->globalTexName = globalTexName; 1060 return dpy->addImageKHR(img); 1061 } 1062 } 1063 1064 return EGL_NO_IMAGE_KHR; 1065 } 1066 1067 1068 EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image) 1069 { 1070 VALIDATE_DISPLAY(display); 1071 return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE; 1072 } 1073 1074 /*********************************************************************************/ 1075