1 /****************************************************************************** 2 3 @File KEGL/PVRShellAPI.cpp 4 5 @Title KEGL/PVRShellAPI 6 7 @Version 8 9 @Copyright Copyright (c) Imagination Technologies Limited. 10 11 @Platform Independent 12 13 @Description Makes programming for 3D APIs easier by wrapping surface 14 initialization, Texture allocation and other functions for use by a demo. 15 16 ******************************************************************************/ 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <stdarg.h> 22 23 #include "PVRShell.h" 24 #include "PVRShellAPI.h" 25 #include "PVRShellOS.h" 26 #include "PVRShellImpl.h" 27 28 // No Doxygen for CPP files, due to documentation duplication 29 /// @cond NO_DOXYGEN 30 31 #ifndef EGL_CONTEXT_LOST_IMG 32 /*! Extended error code EGL_CONTEXT_LOST_IMG generated when power management event has occurred. */ 33 #define EGL_CONTEXT_LOST_IMG 0x300E 34 #endif 35 36 #ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG 37 /*! An extensions added to the list of attributes for the context to give it a priority hint */ 38 #define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 39 /*! Request the context is created with high priority */ 40 #define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 41 /*! Request the context is created with medium priority */ 42 #define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 43 /*! Request the context is created with low priority */ 44 #define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 45 #endif 46 47 /***************************************************************************** 48 Declarations 49 *****************************************************************************/ 50 static bool PVRShellIsExtensionSupported(EGLDisplay dpy, const char *extension); 51 52 #if defined GL_ES_VERSION_2_0 && !defined EGL_VERSION_1_3 53 #error OpenGL ES 2 requires egl.h version 1.3 or higher 54 #endif 55 56 /**************************************************************************** 57 ** Class: PVRShellInitAPI 58 ****************************************************************************/ 59 60 /***************************************************************************** 61 * Function Name : ActivatePreferences 62 * Description : Activates the user set preferences (like v-sync) 63 *****************************************************************************/ 64 void PVRShellInit::ApiActivatePreferences() 65 { 66 67 #ifdef EGL_VERSION_1_1 68 eglSwapInterval(m_EGLDisplay, m_pShell->m_pShellData->nSwapInterval); 69 #endif 70 } 71 72 /***************************************************************************** 73 * Function Name : ApiInitAPI 74 * Returns : true for success 75 * Description : Initialise the 3D API 76 *****************************************************************************/ 77 bool PVRShellInit::ApiInitAPI() 78 { 79 int bDone; 80 81 m_NDT = (EGLNativeDisplayType)OsGetNativeDisplayType(); 82 m_NPT = (EGLNativePixmapType) OsGetNativePixmapType(); 83 m_NWT = (EGLNativeWindowType) OsGetNativeWindowType(); 84 85 m_EGLContext = 0; 86 87 do 88 { 89 bDone = true; 90 91 m_EGLDisplay = eglGetDisplay(m_NDT); 92 93 if(m_EGLDisplay == EGL_NO_DISPLAY) 94 { 95 #if defined(BUILD_OGLES2) || defined(BUILD_OGLES3) 96 m_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); 97 #else 98 m_EGLDisplay = eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY); 99 #endif 100 } 101 102 if(!eglInitialize(m_EGLDisplay, &m_MajorVersion, &m_MinorVersion)) 103 { 104 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to initialise EGL\n"); 105 m_pShell->PVRShellOutputDebug("PVRShell: EGL Error (%s)\n", StringFrom_eglGetError()); 106 return false; 107 } 108 109 m_pShell->PVRShellOutputDebug("PVRShell: EGL %d.%d initialized\n", m_MajorVersion, m_MinorVersion); 110 111 // Check Extension availability after EGL initialization 112 if (m_MajorVersion > 1 || (m_MajorVersion == 1 && m_MinorVersion >= 1)) 113 { 114 m_bPowerManagementSupported = true; 115 } 116 else 117 { 118 m_bPowerManagementSupported = PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_power_management"); 119 } 120 121 do 122 { 123 #if defined(BUILD_OGL) 124 if(!eglBindAPI(EGL_OPENGL_API)) 125 { 126 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL API\n"); 127 return false; 128 } 129 #else 130 #if defined EGL_VERSION_1_3 && defined GL_ES_VERSION_2_0 131 if(!eglBindAPI(EGL_OPENGL_ES_API)) 132 { 133 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL ES API\n"); 134 return false; 135 } 136 #endif 137 #endif 138 // Find an EGL config 139 m_EGLConfig = SelectEGLConfiguration(m_pShell->m_pShellData); 140 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID, &m_iConfig); 141 142 // Destroy the context if we already created one 143 if (m_EGLContext) 144 { 145 eglDestroyContext(m_EGLDisplay, m_EGLContext); 146 } 147 148 // Attempt to create a context 149 EGLint ai32ContextAttribs[48]; 150 int i = 0; 151 152 #if defined(BUILD_OGLES3) 153 ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION; 154 ai32ContextAttribs[i++] = 3; 155 #else 156 #if defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0) 157 ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION; 158 ai32ContextAttribs[i++] = 2; 159 #endif 160 #endif 161 162 #if defined(BUILD_OGL) 163 //Attempt to create an OpenGL 3.2 context. 164 if (PVRShellIsExtensionSupported(m_EGLDisplay, "EGL_KHR_create_context")) 165 { 166 ai32ContextAttribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR; 167 ai32ContextAttribs[i++] = 3; 168 ai32ContextAttribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR; 169 ai32ContextAttribs[i++] = 2; 170 ai32ContextAttribs[i++] = EGL_CONTEXT_FLAGS_KHR; 171 ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 172 ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; 173 ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 174 } 175 #endif 176 177 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3) 178 if(PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_context_priority")) 179 { 180 ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG; 181 switch(m_pShell->PVRShellGet(prefPriority)) 182 { 183 case 0: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LOW_IMG; break; 184 case 1: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; break; 185 default:ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_HIGH_IMG; break; 186 } 187 } 188 #endif 189 ai32ContextAttribs[i] = EGL_NONE; 190 191 if (m_EGLContext == EGL_NO_CONTEXT) 192 { 193 m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, NULL, ai32ContextAttribs); 194 } 195 196 if(m_EGLContext == EGL_NO_CONTEXT) 197 { 198 if(m_iRequestedConfig > 0) 199 { 200 // We failed to create a context 201 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n"); 202 return false; 203 } 204 else if(m_pShell->m_pShellData->bNeedPbuffer) 205 { 206 // Disable P-buffer and try again 207 m_pShell->m_pShellData->bNeedPbuffer = false; 208 } 209 else if(m_pShell->m_pShellData->bNeedStencilBuffer) 210 { 211 // Disable Stencil Buffer and try again 212 m_pShell->m_pShellData->bNeedStencilBuffer = false; 213 } 214 else if(m_pShell->m_pShellData->nAASamples > 0) 215 { 216 // Still failing, reduce the AA samples and try again 217 --m_pShell->m_pShellData->nAASamples; 218 } 219 else 220 { 221 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n"); 222 return false; 223 } 224 } 225 } while(m_EGLContext == EGL_NO_CONTEXT); 226 227 #if defined(__QNXNTO__) 228 int format = SCREEN_FORMAT_RGBX8888; 229 if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_FORMAT, &format)) 230 { 231 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_FORMAT\n"); 232 return false; 233 } 234 235 #if defined(BUILD_OGLES2) 236 int usage = SCREEN_USAGE_OPENGL_ES2; 237 #else 238 #if defined(BUILD_OGLES) 239 int usage = SCREEN_USAGE_OPENGL_ES1; 240 #endif 241 #endif 242 if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_USAGE, &usage)) 243 { 244 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_USAGE\n"); 245 return false; 246 } 247 248 if(screen_create_window_buffers((_screen_window*) m_NWT, 2)) 249 { 250 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to create window buffers\n"); 251 return false; 252 } 253 #endif 254 EGLint attrib_list[16]; 255 int i = 0; 256 #if defined(EGL_VERSION_1_2) 257 if(m_pShell->m_pShellData->bNeedAlphaFormatPre) // The default is EGL_ALPHA_FORMAT_NONPRE 258 { 259 attrib_list[i++] = EGL_ALPHA_FORMAT; 260 attrib_list[i++] = EGL_ALPHA_FORMAT_PRE; 261 } 262 #endif 263 // Terminate the attribute list with EGL_NONE 264 attrib_list[i] = EGL_NONE; 265 266 if(m_pShell->m_pShellData->bNeedPixmap) 267 { 268 m_pShell->PVRShellOutputDebug("InitAPI() Using pixmaps, about to create egl surface\n"); 269 m_EGLWindow = eglCreatePixmapSurface(m_EGLDisplay, m_EGLConfig, m_NPT, attrib_list); 270 } 271 else 272 { 273 #if defined(ANDROID) 274 EGLint visualID; 275 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_NATIVE_VISUAL_ID, &visualID); 276 277 // Change the format of our window to match our config 278 ANativeWindow_setBuffersGeometry(m_NWT, 0, 0, visualID); 279 #endif 280 m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, m_NWT, attrib_list); 281 282 // If we have failed to create a surface then try using Null 283 if(m_EGLWindow == EGL_NO_SURFACE) 284 { 285 m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, NULL, attrib_list); 286 } 287 } 288 289 if (m_EGLWindow == EGL_NO_SURFACE) 290 { 291 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create surface\n"); 292 return false; 293 } 294 295 if (!eglMakeCurrent(m_EGLDisplay, m_EGLWindow, m_EGLWindow, m_EGLContext)) 296 { 297 #ifdef EGL_VERSION_1_3 298 if((eglGetError() == EGL_CONTEXT_LOST)) 299 #else 300 if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported) 301 #endif 302 { 303 bDone = false; 304 } 305 else 306 { 307 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to make context current\n"); 308 return false; 309 } 310 } 311 } while(!bDone); 312 313 /* 314 Get correct screen width and height and 315 save them into 316 m_pShell->m_pShellData->nShellDimX and 317 m_pShell->m_pShellData->nShellDimY 318 */ 319 eglQuerySurface(m_EGLDisplay, m_EGLWindow, 320 EGL_WIDTH, (EGLint*)&m_pShell->m_pShellData->nShellDimX 321 ); 322 eglQuerySurface(m_EGLDisplay, m_EGLWindow, 323 EGL_HEIGHT, (EGLint*)&m_pShell->m_pShellData->nShellDimY 324 ); 325 326 #if defined(ANDROID) 327 glViewport(0, 0, m_pShell->m_pShellData->nShellDimX, m_pShell->m_pShellData->nShellDimY); 328 #endif 329 /* 330 Done - activate requested features 331 */ 332 333 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) 334 //Get the discardframebufferEXT function. 335 { 336 //Get the gl extension string 337 const char* strExtensions = (const char*)glGetString(GL_EXTENSIONS); 338 339 //Get the length of the string we're searching for 340 const size_t strLength = strlen("GL_EXT_discard_framebuffer"); 341 342 //Get the string position 343 const char* position = strstr(strExtensions,"GL_EXT_discard_framebuffer"); 344 345 //Loop through until we find the actual extension, avoiding substrings. 346 while (position!=NULL && position[strLength]!='\0' && position[strLength]!=' ') 347 { 348 position = strstr(position+strLength,"GL_EXT_discard_framebuffer"); 349 } 350 351 //Initialise the extension if it's found. 352 if (position != NULL) 353 { 354 glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); 355 } 356 else 357 { 358 glDiscardFramebufferEXT = NULL; 359 } 360 } 361 #endif 362 ApiActivatePreferences(); 363 return true; 364 } 365 366 /*!*********************************************************************** 367 @Function OutputAPIInfo 368 @description When prefOutputInfo is set to true this function outputs 369 various pieces of API dependent information via 370 PVRShellOutputDebug. 371 *************************************************************************/ 372 void PVRShellInit::OutputAPIInfo() 373 { 374 // Output API dependent information 375 if(m_pShell->PVRShellGet(prefOutputInfo)) 376 { 377 EGLint i32Values[5]; 378 379 m_pShell->PVRShellOutputDebug("\n"); 380 381 m_pShell->PVRShellOutputDebug("GL:\n"); 382 m_pShell->PVRShellOutputDebug(" Vendor: %s\n", (char*) glGetString(GL_VENDOR)); 383 m_pShell->PVRShellOutputDebug(" Renderer: %s\n", (char*) glGetString(GL_RENDERER)); 384 m_pShell->PVRShellOutputDebug(" Version: %s\n", (char*) glGetString(GL_VERSION)); 385 m_pShell->PVRShellOutputDebug(" Extensions: "); 386 387 #if defined(BUILD_OGL) 388 //Get the glGetString process. 389 typedef const GLubyte* (KHRONOS_APIENTRY * PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); 390 PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC)eglGetProcAddress("glGetStringi"); 391 392 //If we've successfully got the new way to query the string, then go ahead and use this. 393 if (glGetStringi) 394 { 395 #ifndef GL_NUM_EXTENSIONS 396 #define GL_NUM_EXTENSIONS 0x821D 397 #endif 398 GLint numExtensions; 399 glGetIntegerv(GL_NUM_EXTENSIONS,&numExtensions); 400 401 for (GLint i=0; i<numExtensions; ++i) 402 { 403 m_pShell->PVRShellOutputDebug((const char*)glGetStringi(GL_EXTENSIONS,i)); 404 m_pShell->PVRShellOutputDebug(" "); 405 } 406 } 407 #else 408 m_pShell->PVRShellOutputDebug("%s\n", (char*) glGetString(GL_EXTENSIONS)); 409 #endif 410 411 m_pShell->PVRShellOutputDebug("\n"); 412 413 m_pShell->PVRShellOutputDebug("\n"); 414 m_pShell->PVRShellOutputDebug("EGL:\n"); 415 m_pShell->PVRShellOutputDebug(" Vendor: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_VENDOR)); 416 m_pShell->PVRShellOutputDebug(" Version: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_VERSION)); 417 m_pShell->PVRShellOutputDebug(" Extensions: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_EXTENSIONS)); 418 419 if(eglQueryContext(m_EGLDisplay, m_EGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &i32Values[0])) 420 { 421 switch(i32Values[0]) 422 { 423 case EGL_CONTEXT_PRIORITY_HIGH_IMG: m_pShell->PVRShellOutputDebug(" Context priority: High\n"); break; 424 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: m_pShell->PVRShellOutputDebug(" Context priority: Medium\n");break; 425 case EGL_CONTEXT_PRIORITY_LOW_IMG: m_pShell->PVRShellOutputDebug(" Context priority: Low\n"); break; 426 default: m_pShell->PVRShellOutputDebug(" Context priority: Unrecognised.\n"); break; 427 } 428 } 429 else 430 { 431 eglGetError(); // Clear error 432 m_pShell->PVRShellOutputDebug(" Context priority: Unsupported\n"); 433 } 434 435 #ifdef EGL_VERSION_1_2 436 m_pShell->PVRShellOutputDebug(" Client APIs: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_CLIENT_APIS)); 437 #endif 438 439 m_pShell->PVRShellOutputDebug("\n"); 440 m_pShell->PVRShellOutputDebug("Window Width: %i\n" , m_pShell->PVRShellGet(prefWidth)); 441 m_pShell->PVRShellOutputDebug("Window Height: %i\n" , m_pShell->PVRShellGet(prefHeight)); 442 m_pShell->PVRShellOutputDebug("Is Rotated: %s\n", m_pShell->PVRShellGet(prefIsRotated) ? "Yes" : "No"); 443 m_pShell->PVRShellOutputDebug("\n"); 444 445 // EGLSurface details 446 m_pShell->PVRShellOutputDebug("EGL Surface:\n"); 447 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID , &i32Values[0]); 448 m_pShell->PVRShellOutputDebug(" Config ID: %i\n", i32Values[0]); 449 450 // Colour buffer 451 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_BUFFER_SIZE , &i32Values[0]); 452 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_RED_SIZE , &i32Values[1]); 453 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_GREEN_SIZE , &i32Values[2]); 454 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_BLUE_SIZE , &i32Values[3]); 455 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_ALPHA_SIZE , &i32Values[4]); 456 m_pShell->PVRShellOutputDebug(" Colour Buffer: %i bits (R%i G%i B%i A%i)\n", i32Values[0],i32Values[1],i32Values[2],i32Values[3],i32Values[4]); 457 458 // Depth buffer 459 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_DEPTH_SIZE , &i32Values[0]); 460 m_pShell->PVRShellOutputDebug(" Depth Buffer: %i bits\n", i32Values[0]); 461 462 // Stencil Buffer 463 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_STENCIL_SIZE , &i32Values[0]); 464 m_pShell->PVRShellOutputDebug(" Stencil Buffer: %i bits\n", i32Values[0]); 465 466 // EGL surface bits support 467 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SURFACE_TYPE , &i32Values[0]); 468 m_pShell->PVRShellOutputDebug(" Surface type: %s%s%s\n", i32Values[0] & EGL_WINDOW_BIT ? "WINDOW " : "", 469 i32Values[1] & EGL_PBUFFER_BIT ? "PBUFFER " : "", 470 i32Values[2] & EGL_PIXMAP_BIT ? "PIXMAP " : ""); 471 // EGL renderable type 472 #ifdef EGL_VERSION_1_2 473 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_RENDERABLE_TYPE , &i32Values[0]); 474 m_pShell->PVRShellOutputDebug(" Renderable type: %s%s%s%s\n", i32Values[0] & EGL_OPENVG_BIT ? "OPENVG " : "", 475 i32Values[0] & EGL_OPENGL_ES_BIT ? "OPENGL_ES " : "", 476 #ifdef EGL_OPENGL_BIT 477 i32Values[0] & EGL_OPENGL_BIT ? "OPENGL " : 478 #endif 479 "", 480 i32Values[0] & EGL_OPENGL_ES2_BIT ? "OPENGL_ES2 " : ""); 481 #endif 482 483 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SAMPLE_BUFFERS , &i32Values[0]); 484 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SAMPLES , &i32Values[1]); 485 m_pShell->PVRShellOutputDebug(" Sample buffer No.: %i\n", i32Values[0]); 486 m_pShell->PVRShellOutputDebug(" Samples per pixel: %i\n", i32Values[1]); 487 } 488 } 489 490 /*!*********************************************************************** 491 @Function ApiReleaseAPI 492 @description Releases all resources allocated by the API. 493 *************************************************************************/ 494 void PVRShellInit::ApiReleaseAPI() 495 { 496 eglSwapBuffers(m_EGLDisplay, m_EGLWindow); 497 eglMakeCurrent(m_EGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 498 eglDestroyContext(m_EGLDisplay, m_EGLContext); 499 eglDestroySurface(m_EGLDisplay, m_EGLWindow); 500 eglTerminate(m_EGLDisplay); 501 } 502 503 /******************************************************************************* 504 * Function Name : SelectEGLConfiguration 505 * Inputs : pData 506 * Returns : EGLConfig 507 * Description : Find the config to use for EGL initialisation 508 *******************************************************************************/ 509 EGLConfig PVRShellInitAPI::SelectEGLConfiguration(const PVRShellData * const pData) 510 { 511 EGLint num_config; 512 EGLint conflist[32]; 513 EGLConfig conf = (EGLConfig) 0; 514 int i = 0; 515 516 // Specific config ID requested? 517 if (m_iRequestedConfig > 0) 518 { 519 conflist[i++] = EGL_CONFIG_ID; 520 conflist[i++] = m_iRequestedConfig; 521 conflist[i++] = EGL_NONE; 522 if(!eglChooseConfig(m_EGLDisplay, conflist, &conf, 1, &num_config) || num_config != 1) 523 { 524 return 0; 525 } 526 return conf; 527 } 528 529 // Select default configuration 530 #if defined(ANDROID) 531 if(pData->nColorBPP == 32) 532 { 533 conflist[i++] = EGL_RED_SIZE; 534 conflist[i++] = 8; 535 conflist[i++] = EGL_GREEN_SIZE; 536 conflist[i++] = 8; 537 conflist[i++] = EGL_BLUE_SIZE; 538 conflist[i++] = 8; 539 conflist[i++] = EGL_ALPHA_SIZE; 540 conflist[i++] = 8; 541 } 542 else 543 { 544 conflist[i++] = EGL_RED_SIZE; 545 conflist[i++] = 5; 546 conflist[i++] = EGL_GREEN_SIZE; 547 conflist[i++] = 6; 548 conflist[i++] = EGL_BLUE_SIZE; 549 conflist[i++] = 5; 550 conflist[i++] = EGL_ALPHA_SIZE; 551 conflist[i++] = 0; 552 } 553 #else 554 conflist[i++] = EGL_BUFFER_SIZE; 555 conflist[i++] = pData->nColorBPP; 556 #endif 557 558 if(pData->bNeedZbuffer || pData->nDepthBPP > 0) 559 { 560 conflist[i++] = EGL_DEPTH_SIZE; 561 conflist[i++] = (pData->nDepthBPP > 0) ? pData->nDepthBPP : 16; 562 } 563 564 if(pData->bNeedStencilBuffer) 565 { 566 conflist[i++] = EGL_STENCIL_SIZE; 567 conflist[i++] = 8; 568 } 569 570 conflist[i++] = EGL_SURFACE_TYPE; 571 conflist[i] = EGL_WINDOW_BIT; 572 573 if(pData->bNeedPbuffer) 574 { 575 conflist[i] |= EGL_PBUFFER_BIT; 576 } 577 578 if(pData->bNeedPixmap) 579 { 580 conflist[i] |= EGL_PIXMAP_BIT; 581 } 582 583 ++i; 584 585 #if defined(BUILD_OGL) 586 conflist[i++] = EGL_RENDERABLE_TYPE; 587 conflist[i++] = EGL_OPENGL_BIT; 588 #elif defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0) 589 conflist[i++] = EGL_RENDERABLE_TYPE; 590 conflist[i++] = EGL_OPENGL_ES2_BIT; 591 #endif 592 593 // Append number of number of samples depending on AA samples value set 594 if(pData->nAASamples > 0) 595 { 596 conflist[i++] = EGL_SAMPLE_BUFFERS; 597 conflist[i++] = 1; 598 conflist[i++] = EGL_SAMPLES; 599 conflist[i++] = pData->nAASamples; 600 } 601 else 602 { 603 conflist[i++] = EGL_SAMPLE_BUFFERS; 604 conflist[i++] = 0; 605 } 606 607 #if defined(EWS) || defined(__QNXNTO__) 608 if(m_NWT != NULL) 609 { 610 EGLint r,g,b,a, value; 611 EGLint i32Total_num_configs, j; 612 EGLConfig *pConfigs; 613 614 // Some platforms require an egl config to have the same pixel format as the native window because 615 // pixel format conversion is prohibited. 616 #if defined(EWS) 617 int format = EWS_PIXEL_FORMAT_RGB_565; 618 r = 5; g = 6; b = 5; a = 0; 619 #else 620 r = g = b = a = 8; 621 #endif 622 623 conflist[i++] = EGL_RED_SIZE; 624 conflist[i++] = r; 625 626 conflist[i++] = EGL_GREEN_SIZE; 627 conflist[i++] = g; 628 629 conflist[i++] = EGL_BLUE_SIZE; 630 conflist[i++] = b; 631 632 conflist[i++] = EGL_ALPHA_SIZE; 633 conflist[i++] = a; 634 635 // Terminate the list with EGL_NONE 636 conflist[i++] = EGL_NONE; 637 638 // Find out how many configs there are in total that match our criteria 639 if(!eglChooseConfig(m_EGLDisplay, conflist, NULL, 0, &i32Total_num_configs) || i32Total_num_configs == 0) 640 return 0; 641 642 // Allocate an array large enough to store all the possible configs that may be returned 643 pConfigs = new EGLConfig[i32Total_num_configs]; 644 645 if(!pConfigs) 646 return 0; 647 648 // Get all the configs that match our criteria 649 if(!eglChooseConfig(m_EGLDisplay, conflist, pConfigs, i32Total_num_configs, &num_config)) 650 { 651 delete[] pConfigs; 652 return 0; 653 } 654 655 // Go through the returned configs and try and find a suitable match 656 for(j = 0; j < num_config; ++j) 657 { 658 #if defined(__QNXNTO__) 659 if((eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_RED_SIZE, &value) && value == r) 660 && (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_GREEN_SIZE, &value) && value == g) 661 && (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_BLUE_SIZE, &value) && value == b) 662 && (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_ALPHA_SIZE, &value) && value == a)) 663 { 664 conf = pConfigs[j]; 665 break; 666 } 667 #else 668 #if defined (EWS) 669 eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_NATIVE_VISUAL_ID, &value); 670 if (value == format) 671 { 672 conf = pConfigs[j]; 673 break; 674 } 675 #endif 676 #endif 677 } 678 679 // Tidy up 680 delete[] pConfigs; 681 } 682 else 683 #endif 684 { 685 // Terminate the list with EGL_NONE 686 conflist[i++] = EGL_NONE; 687 688 // Return null config if config is not found 689 if(!eglChooseConfig(m_EGLDisplay, conflist, &conf, 1, &num_config) || num_config != 1) 690 { 691 return 0; 692 } 693 } 694 695 // Return config index 696 return conf; 697 } 698 699 /******************************************************************************* 700 * Function Name : StringFrom_eglGetError 701 * Returns : A string 702 * Description : Returns a string representation of an egl error 703 *******************************************************************************/ 704 const char *PVRShellInitAPI::StringFrom_eglGetError() const 705 { 706 EGLint nErr = eglGetError(); 707 708 switch(nErr) 709 { 710 case EGL_SUCCESS: 711 return "EGL_SUCCESS"; 712 case EGL_BAD_DISPLAY: 713 return "EGL_BAD_DISPLAY"; 714 case EGL_NOT_INITIALIZED: 715 return "EGL_NOT_INITIALIZED"; 716 case EGL_BAD_ACCESS: 717 return "EGL_BAD_ACCESS"; 718 case EGL_BAD_ALLOC: 719 return "EGL_BAD_ALLOC"; 720 case EGL_BAD_ATTRIBUTE: 721 return "EGL_BAD_ATTRIBUTE"; 722 case EGL_BAD_CONFIG: 723 return "EGL_BAD_CONFIG"; 724 case EGL_BAD_CONTEXT: 725 return "EGL_BAD_CONTEXT"; 726 case EGL_BAD_CURRENT_SURFACE: 727 return "EGL_BAD_CURRENT_SURFACE"; 728 case EGL_BAD_MATCH: 729 return "EGL_BAD_MATCH"; 730 case EGL_BAD_NATIVE_PIXMAP: 731 return "EGL_BAD_NATIVE_PIXMAP"; 732 case EGL_BAD_NATIVE_WINDOW: 733 return "EGL_BAD_NATIVE_WINDOW"; 734 case EGL_BAD_PARAMETER: 735 return "EGL_BAD_PARAMETER"; 736 case EGL_BAD_SURFACE: 737 return "EGL_BAD_SURFACE"; 738 default: 739 return "unknown"; 740 } 741 } 742 743 /*!*********************************************************************** 744 @Function ApiScreenCaptureBuffer 745 @Input Width Width of the region to capture 746 @Input Height Height of the region to capture 747 @Input pBuf A buffer to put the screen capture into 748 @description API-specific function to store the current content of the 749 FrameBuffer into the memory allocated by the user. 750 *************************************************************************/ 751 bool PVRShellInit::ApiScreenCaptureBuffer(int Width,int Height,unsigned char *pBuf) 752 { 753 unsigned char *pLines2; 754 int i, j; 755 bool bRet = true; 756 757 /* Allocate memory for line */ 758 pLines2 = (unsigned char *)calloc(4 * Width * Height, sizeof(unsigned char)); 759 if (!pLines2) return false; 760 761 while (glGetError()); 762 /* Read line from frame buffer */ 763 glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pLines2); 764 765 if(glGetError()) 766 { 767 bRet = false; 768 } 769 else 770 { 771 /* Convert RGB to BGR in line */ 772 for (j = 0, i = 0; j < 4 * Width * Height; j += 4, i += 3) 773 { 774 pBuf[i] = pLines2[j+2]; 775 pBuf[i+1] = pLines2[j+1]; 776 pBuf[i+2] = pLines2[j]; 777 } 778 } 779 780 free(pLines2); 781 return bRet; 782 } 783 784 /*!*********************************************************************** 785 @Function ApiRenderComplete 786 @description Perform API operations required after a frame has finished (e.g., flipping). 787 *************************************************************************/ 788 void PVRShellInit::ApiRenderComplete() 789 { 790 791 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3) 792 //Discard the framebuffer if set. 793 #if !defined(BUILD_OGLES3) 794 if (glDiscardFramebufferEXT) 795 #endif 796 { 797 const GLint numAttachments=3; 798 GLenum attachments[numAttachments]; 799 GLint currentAttachment=0; 800 if (m_pShell->PVRShellGet(prefDiscardColor)) 801 { 802 attachments[currentAttachment] = GL_COLOR_EXT; 803 currentAttachment++; 804 } 805 if (m_pShell->PVRShellGet(prefDiscardDepth)) 806 { 807 attachments[currentAttachment] = GL_DEPTH_EXT; 808 currentAttachment++; 809 } 810 if (m_pShell->PVRShellGet(prefDiscardStencil)) 811 { 812 attachments[currentAttachment] = GL_STENCIL_EXT; 813 currentAttachment++; 814 } 815 //Assuming some attachments have been chosen, discard/invalidate them. 816 if (currentAttachment!=0) 817 { 818 #if defined(BUILD_OGLES) 819 glDiscardFramebufferEXT(GL_FRAMEBUFFER_OES, currentAttachment, attachments); 820 #elif defined(BUILD_OGLES2) 821 glDiscardFramebufferEXT(GL_FRAMEBUFFER, currentAttachment, attachments); 822 #elif defined(BUILD_OGLES3) 823 glInvalidateFramebuffer(GL_FRAMEBUFFER, currentAttachment, attachments); 824 #endif 825 } 826 } 827 #endif 828 829 bool bRes; 830 831 if(m_pShell->m_pShellData->bNeedPixmap) 832 { 833 /* 834 "Clients rendering to single buffered surfaces (e.g. pixmap surfaces) 835 should call eglWaitGL before accessing the native pixmap from the client." 836 */ 837 eglWaitGL(); 838 839 // Pixmap support: Copy the rendered pixmap to the display 840 if(m_pShell->m_pShellData->bNeedPixmapDisableCopy) 841 { 842 bRes = true; 843 } 844 else 845 { 846 bRes = OsPixmapCopy(); 847 } 848 } 849 else 850 { 851 if(m_pShell->m_pShellData->bNoShellSwapBuffer) 852 return; 853 854 bRes = (eglSwapBuffers (m_EGLDisplay, m_EGLWindow) == EGL_TRUE); 855 } 856 857 if(!bRes) 858 { 859 // check for context loss 860 #ifdef EGL_VERSION_1_3 861 if(eglGetError() == EGL_CONTEXT_LOST) 862 #else 863 if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported) 864 #endif 865 { 866 m_pShell->ReleaseView(); 867 868 OsDoReleaseAPI(); 869 if(ApiInitAPI()) 870 { 871 m_pShell->InitView(); 872 } 873 } 874 else 875 { 876 if(m_pShell->m_pShellData->bNeedPixmap) 877 m_pShell->PVRShellOutputDebug("failed to copy pixmap\n"); 878 else 879 m_pShell->PVRShellOutputDebug("eglSwapBuffers failed\n"); 880 } 881 } 882 } 883 884 /*!*********************************************************************** 885 @Function ApiSet 886 @Input prefName Name of value to set 887 @Modified i32Value Value to set it to 888 @description Set parameters which are specific to the API. 889 *************************************************************************/ 890 bool PVRShellInit::ApiSet(const prefNameIntEnum prefName, const int i32Value) 891 { 892 switch(prefName) 893 { 894 #ifdef EGL_VERSION_1_1 895 case prefSwapInterval: 896 m_pShell->m_pShellData->nSwapInterval = i32Value; 897 return true; 898 #endif 899 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3) 900 case prefPriority: 901 m_pShell->m_pShellData->nPriority = i32Value; 902 return true; 903 #endif 904 case prefRequestedConfig: 905 m_iRequestedConfig = (EGLint) i32Value; 906 return true; 907 908 default: 909 return false; 910 } 911 } 912 913 /*!*********************************************************************** 914 @Function ApiGet 915 @Input prefName Name of value to get 916 @Modified pn A pointer set to the value asked for 917 @description Get parameters which are specific to the API. 918 *************************************************************************/ 919 bool PVRShellInit::ApiGet(const prefNameIntEnum prefName, int *pn) 920 { 921 switch(prefName) 922 { 923 case prefEGLMajorVersion: 924 *pn = (int) m_MajorVersion; 925 return true; 926 927 case prefEGLMinorVersion: 928 *pn = (int) m_MinorVersion; 929 return true; 930 931 case prefRequestedConfig: 932 *pn = (int) m_iRequestedConfig; 933 return true; 934 935 case prefConfig: 936 *pn = (int) m_iConfig; 937 return true; 938 939 default: 940 return false; 941 } 942 } 943 944 /*!*********************************************************************** 945 @Function ApiGet 946 @Input prefName Name of value to get 947 @Modified pp A pointer set to the value asked for 948 @description Get parameters which are specific to the API. 949 *************************************************************************/ 950 bool PVRShellInit::ApiGet(const prefNamePtrEnum prefName, void **pp) 951 { 952 switch(prefName) 953 { 954 case prefEGLDisplay: 955 *pp = (void*)m_EGLDisplay; 956 return true; 957 case prefEGLSurface: 958 *pp = (void*)m_EGLWindow; 959 return true; 960 default: 961 return false; 962 } 963 } 964 965 /**************************************************************************** 966 ** Local code 967 ****************************************************************************/ 968 969 // The recommended technique for querying OpenGL extensions; 970 // adapted from http://opengl.org/resources/features/OGLextensions/ 971 static bool PVRShellIsExtensionSupported(EGLDisplay dpy, const char *extension) 972 { 973 // The recommended technique for querying EGL extensions matches OpenGLES; 974 // from http://opengl.org/resources/features/OGLextensions/ 975 const char *extensions = NULL; 976 const char *start; 977 char *terminator; 978 979 /* Extension names should not have spaces. */ 980 char* where = (char *) strchr(extension, ' '); 981 if (where || *extension == '\0') 982 return 0; 983 984 extensions = eglQueryString(dpy, EGL_EXTENSIONS); 985 if(!extensions) 986 return false; 987 988 /* It takes a bit of care to be fool-proof about parsing the 989 OpenGL extensions string. Don't be fooled by sub-strings, etc. */ 990 start = extensions; 991 for (;;) { 992 where = (char *) strstr((const char *) start, extension); 993 if (!where) 994 break; 995 terminator = where + strlen(extension); 996 if (where == start || *(where - 1) == ' ') 997 if (*terminator == ' ' || *terminator == '\0') 998 return true; 999 start = terminator; 1000 } 1001 return false; 1002 } 1003 1004 /// @endcond 1005 1006 /***************************************************************************** 1007 End of file (PVRShellAPI.cpp) 1008 *****************************************************************************/ 1009 1010