Home | History | Annotate | Download | only in KEGL
      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