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