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