Add the ChameleonMan PowerVR sample.

BUG=14598298

Change-Id: Id6dcaebe793cf3d3a10af571348f461023d2a9d2
Reviewed-on: https://swiftshader-review.googlesource.com/1090
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/tests/third_party/PowerVR/Shell/API/KEGL/PVRShellAPI.cpp b/tests/third_party/PowerVR/Shell/API/KEGL/PVRShellAPI.cpp
new file mode 100644
index 0000000..6a0878e
--- /dev/null
+++ b/tests/third_party/PowerVR/Shell/API/KEGL/PVRShellAPI.cpp
@@ -0,0 +1,1009 @@
+/******************************************************************************

+

+ @File         KEGL/PVRShellAPI.cpp

+

+ @Title        KEGL/PVRShellAPI

+

+ @Version      

+

+ @Copyright    Copyright (c) Imagination Technologies Limited.

+

+ @Platform     Independent

+

+ @Description  Makes programming for 3D APIs easier by wrapping surface

+               initialization, Texture allocation and other functions for use by a demo.

+

+******************************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <stdarg.h>

+

+#include "PVRShell.h"

+#include "PVRShellAPI.h"

+#include "PVRShellOS.h"

+#include "PVRShellImpl.h"

+

+// No Doxygen for CPP files, due to documentation duplication

+/// @cond NO_DOXYGEN

+

+#ifndef EGL_CONTEXT_LOST_IMG

+/*! Extended error code EGL_CONTEXT_LOST_IMG generated when power management event has occurred. */

+#define EGL_CONTEXT_LOST_IMG		0x300E

+#endif

+

+#ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG

+/*! An extensions added to the list of attributes for the context to give it a priority hint */

+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG		0x3100

+/*! Request the context is created with high priority */

+#define EGL_CONTEXT_PRIORITY_HIGH_IMG		0x3101

+/*! Request the context is created with medium priority */

+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG		0x3102

+/*! Request the context is created with low priority */

+#define EGL_CONTEXT_PRIORITY_LOW_IMG		0x3103

+#endif

+

+/*****************************************************************************

+	Declarations

+*****************************************************************************/

+static bool PVRShellIsExtensionSupported(EGLDisplay dpy, const char *extension);

+

+#if defined GL_ES_VERSION_2_0 && !defined EGL_VERSION_1_3

+#error OpenGL ES 2 requires egl.h version 1.3 or higher

+#endif

+

+/****************************************************************************

+** Class: PVRShellInitAPI

+****************************************************************************/

+

+/*****************************************************************************

+* Function Name  : ActivatePreferences

+* Description    : Activates the user set preferences (like v-sync)

+*****************************************************************************/

+void PVRShellInit::ApiActivatePreferences()

+{

+

+#ifdef EGL_VERSION_1_1

+	eglSwapInterval(m_EGLDisplay, m_pShell->m_pShellData->nSwapInterval);

+#endif

+}

+

+/*****************************************************************************

+* Function Name  : ApiInitAPI

+* Returns        : true for success

+* Description    : Initialise the 3D API

+*****************************************************************************/

+bool PVRShellInit::ApiInitAPI()

+{

+	int					bDone;

+

+	m_NDT = (EGLNativeDisplayType)OsGetNativeDisplayType();

+	m_NPT = (EGLNativePixmapType) OsGetNativePixmapType();

+	m_NWT = (EGLNativeWindowType) OsGetNativeWindowType();

+

+	m_EGLContext = 0;

+

+	do

+	{

+		bDone = true;

+

+		m_EGLDisplay = eglGetDisplay(m_NDT);

+

+		if(m_EGLDisplay == EGL_NO_DISPLAY)

+		{

+#if defined(BUILD_OGLES2) || defined(BUILD_OGLES3)

+			m_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);

+#else

+			m_EGLDisplay = eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY);

+#endif

+		}

+

+		if(!eglInitialize(m_EGLDisplay, &m_MajorVersion, &m_MinorVersion))

+		{

+			m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to initialise EGL\n");

+			m_pShell->PVRShellOutputDebug("PVRShell: EGL Error (%s)\n", StringFrom_eglGetError());

+			return false;

+		}

+

+		m_pShell->PVRShellOutputDebug("PVRShell: EGL %d.%d initialized\n", m_MajorVersion, m_MinorVersion);

+

+		// Check Extension availability after EGL initialization

+		if (m_MajorVersion > 1 || (m_MajorVersion == 1 && m_MinorVersion >= 1))

+		{

+			m_bPowerManagementSupported = true;

+		}

+		else

+		{

+			m_bPowerManagementSupported = PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_power_management");

+		}

+

+		do

+		{

+#if defined(BUILD_OGL)

+			if(!eglBindAPI(EGL_OPENGL_API))

+			{

+				m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL API\n");

+				return false;

+			}

+#else

+#if defined EGL_VERSION_1_3 && defined GL_ES_VERSION_2_0

+			if(!eglBindAPI(EGL_OPENGL_ES_API))

+			{

+				m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL ES API\n");

+				return false;

+			}

+#endif

+#endif

+			// Find an EGL config

+			m_EGLConfig = SelectEGLConfiguration(m_pShell->m_pShellData);

+			eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID, &m_iConfig);

+

+			// Destroy the context if we already created one

+			if (m_EGLContext)

+			{

+				eglDestroyContext(m_EGLDisplay, m_EGLContext);

+			}

+

+			// Attempt to create a context

+			EGLint ai32ContextAttribs[48];

+			int	i = 0;

+

+#if defined(BUILD_OGLES3)

+			ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION;

+			ai32ContextAttribs[i++] = 3;

+#else

+#if defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0)

+			ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION;

+			ai32ContextAttribs[i++] = 2;

+#endif

+#endif

+

+#if defined(BUILD_OGL)

+			//Attempt to create an OpenGL 3.2 context.

+			if (PVRShellIsExtensionSupported(m_EGLDisplay, "EGL_KHR_create_context"))

+			{

+				ai32ContextAttribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;

+				ai32ContextAttribs[i++] = 3;

+				ai32ContextAttribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;

+				ai32ContextAttribs[i++] = 2;

+				ai32ContextAttribs[i++] = EGL_CONTEXT_FLAGS_KHR;

+				ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;

+				ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;

+				ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;

+			}

+#endif

+

+#if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3)

+			if(PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_context_priority"))

+			{

+				ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG;

+				switch(m_pShell->PVRShellGet(prefPriority))

+				{

+					case 0: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LOW_IMG; break;

+					case 1: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; break;

+					default:ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_HIGH_IMG; break;

+				}

+			}

+#endif

+			ai32ContextAttribs[i] = EGL_NONE;

+

+			if (m_EGLContext == EGL_NO_CONTEXT)

+			{

+				m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, NULL, ai32ContextAttribs);

+			}

+

+			if(m_EGLContext == EGL_NO_CONTEXT)

+			{

+				if(m_iRequestedConfig > 0)

+				{

+					// We failed to create a context

+					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n");

+					return false;

+				}

+				else if(m_pShell->m_pShellData->bNeedPbuffer)

+				{

+					// Disable P-buffer and try again

+					m_pShell->m_pShellData->bNeedPbuffer = false;

+				}

+				else if(m_pShell->m_pShellData->bNeedStencilBuffer)

+				{

+                    // Disable Stencil Buffer and try again

+					m_pShell->m_pShellData->bNeedStencilBuffer = false;

+				}

+				else if(m_pShell->m_pShellData->nAASamples > 0)

+				{

+					// Still failing, reduce the AA samples and try again

+					--m_pShell->m_pShellData->nAASamples;

+				}

+				else

+				{

+					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n");

+					return false;

+				}

+			}

+		} while(m_EGLContext == EGL_NO_CONTEXT);

+

+#if defined(__QNXNTO__)

+		int format = SCREEN_FORMAT_RGBX8888;

+	    if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_FORMAT, &format))

+	    {

+	    	m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_FORMAT\n");

+	    	return false;

+	    }

+

+#if defined(BUILD_OGLES2)

+	    int usage = SCREEN_USAGE_OPENGL_ES2;

+#else

+#if defined(BUILD_OGLES)

+	    int usage = SCREEN_USAGE_OPENGL_ES1;

+#endif

+#endif

+	    if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_USAGE, &usage))

+	    {

+	    	m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_USAGE\n");

+	    	return false;

+	    }

+

+	    if(screen_create_window_buffers((_screen_window*) m_NWT, 2))

+	    {

+	    	m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to create window buffers\n");

+	    	return false;

+	    }

+#endif

+		EGLint		attrib_list[16];

+		int	i = 0;

+#if defined(EGL_VERSION_1_2)

+		if(m_pShell->m_pShellData->bNeedAlphaFormatPre) // The default is EGL_ALPHA_FORMAT_NONPRE

+		{

+			attrib_list[i++] = EGL_ALPHA_FORMAT;

+			attrib_list[i++] = EGL_ALPHA_FORMAT_PRE;

+		}

+#endif

+		// Terminate the attribute list with EGL_NONE

+		attrib_list[i] = EGL_NONE;

+

+		if(m_pShell->m_pShellData->bNeedPixmap)

+		{

+			m_pShell->PVRShellOutputDebug("InitAPI() Using pixmaps, about to create egl surface\n");

+			m_EGLWindow = eglCreatePixmapSurface(m_EGLDisplay, m_EGLConfig, m_NPT, attrib_list);

+		}

+		else

+		{

+#if defined(ANDROID)

+			EGLint visualID;

+		    eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_NATIVE_VISUAL_ID, &visualID);

+

+		    // Change the format of our window to match our config

+    		ANativeWindow_setBuffersGeometry(m_NWT, 0, 0, visualID);

+#endif

+			m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, m_NWT, attrib_list);

+

+            // If we have failed to create a surface then try using Null

+			if(m_EGLWindow == EGL_NO_SURFACE)

+			{

+				m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, NULL, attrib_list);

+			}

+		}

+

+		if (m_EGLWindow == EGL_NO_SURFACE)

+		{

+			m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create surface\n");

+			return false;

+		}

+

+		if (!eglMakeCurrent(m_EGLDisplay, m_EGLWindow, m_EGLWindow, m_EGLContext))

+		{

+#ifdef EGL_VERSION_1_3

+			if((eglGetError() == EGL_CONTEXT_LOST))

+#else

+			if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported)

+#endif

+			{

+				bDone = false;

+			}

+			else

+			{

+				m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to make context current\n");

+				return false;

+			}

+		}

+	} while(!bDone);

+

+	/*

+	 	Get correct screen width and height and

+		save them into

+		m_pShell->m_pShellData->nShellDimX and

+		m_pShell->m_pShellData->nShellDimY

+	*/

+	eglQuerySurface(m_EGLDisplay, m_EGLWindow,

+			EGL_WIDTH,  (EGLint*)&m_pShell->m_pShellData->nShellDimX

+		);

+	eglQuerySurface(m_EGLDisplay, m_EGLWindow,

+			EGL_HEIGHT, (EGLint*)&m_pShell->m_pShellData->nShellDimY

+		);

+

+#if defined(ANDROID)

+	glViewport(0, 0, m_pShell->m_pShellData->nShellDimX, m_pShell->m_pShellData->nShellDimY);

+#endif

+	/*

+		Done - activate requested features

+	*/

+

+#if defined(BUILD_OGLES) || defined(BUILD_OGLES2)

+	//Get the discardframebufferEXT function.

+	{

+		//Get the gl extension string

+		const char* strExtensions = (const char*)glGetString(GL_EXTENSIONS);

+

+		//Get the length of the string we're searching for

+		const size_t strLength = strlen("GL_EXT_discard_framebuffer");

+

+		//Get the string position

+		const char* position = strstr(strExtensions,"GL_EXT_discard_framebuffer");

+

+		//Loop through until we find the actual extension, avoiding substrings.

+		while (position!=NULL && position[strLength]!='\0' && position[strLength]!=' ')

+		{

+			position = strstr(position+strLength,"GL_EXT_discard_framebuffer");

+		}

+

+		//Initialise the extension if it's found.

+		if (position != NULL)

+		{

+			glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");

+		}

+		else

+		{

+			glDiscardFramebufferEXT = NULL;

+		}

+	}

+#endif

+	ApiActivatePreferences();

+	return true;

+}

+

+/*!***********************************************************************

+@Function		OutputAPIInfo

+@description	When prefOutputInfo is set to true this function outputs

+				various pieces of API dependent information via

+				PVRShellOutputDebug.

+*************************************************************************/

+void PVRShellInit::OutputAPIInfo()

+{

+	// Output API dependent information

+	if(m_pShell->PVRShellGet(prefOutputInfo))

+	{

+		EGLint i32Values[5];

+

+		m_pShell->PVRShellOutputDebug("\n");

+

+		m_pShell->PVRShellOutputDebug("GL:\n");

+		m_pShell->PVRShellOutputDebug("  Vendor:   %s\n", (char*) glGetString(GL_VENDOR));

+		m_pShell->PVRShellOutputDebug("  Renderer: %s\n", (char*) glGetString(GL_RENDERER));

+		m_pShell->PVRShellOutputDebug("  Version:  %s\n", (char*) glGetString(GL_VERSION));

+		m_pShell->PVRShellOutputDebug("  Extensions:  ");

+

+#if defined(BUILD_OGL)

+		//Get the glGetString process.

+		typedef const GLubyte* (KHRONOS_APIENTRY * PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);

+		PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC)eglGetProcAddress("glGetStringi");

+

+		//If we've successfully got the new way to query the string, then go ahead and use this.

+		if (glGetStringi)

+		{

+#ifndef GL_NUM_EXTENSIONS

+#define GL_NUM_EXTENSIONS                 0x821D

+#endif

+			GLint numExtensions;

+			glGetIntegerv(GL_NUM_EXTENSIONS,&numExtensions);

+

+			for (GLint i=0; i<numExtensions; ++i)

+			{

+				m_pShell->PVRShellOutputDebug((const char*)glGetStringi(GL_EXTENSIONS,i));

+				m_pShell->PVRShellOutputDebug(" ");

+			}

+		}

+#else

+		m_pShell->PVRShellOutputDebug("%s\n", (char*) glGetString(GL_EXTENSIONS));

+#endif

+

+		m_pShell->PVRShellOutputDebug("\n");

+

+		m_pShell->PVRShellOutputDebug("\n");

+		m_pShell->PVRShellOutputDebug("EGL:\n");

+		m_pShell->PVRShellOutputDebug("  Vendor:   %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_VENDOR));

+		m_pShell->PVRShellOutputDebug("  Version:  %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_VERSION));

+		m_pShell->PVRShellOutputDebug("  Extensions:  %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_EXTENSIONS));

+

+		if(eglQueryContext(m_EGLDisplay, m_EGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &i32Values[0]))

+		{

+			switch(i32Values[0])

+			{

+				case EGL_CONTEXT_PRIORITY_HIGH_IMG:   m_pShell->PVRShellOutputDebug("  Context priority: High\n");  break;

+				case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: m_pShell->PVRShellOutputDebug("  Context priority: Medium\n");break;

+				case EGL_CONTEXT_PRIORITY_LOW_IMG:    m_pShell->PVRShellOutputDebug("  Context priority: Low\n");   break;

+				default: m_pShell->PVRShellOutputDebug("  Context priority: Unrecognised.\n"); break;

+			}

+		}

+		else

+		{

+			eglGetError(); // Clear error

+			m_pShell->PVRShellOutputDebug("  Context priority: Unsupported\n");

+		}

+

+#ifdef EGL_VERSION_1_2

+		m_pShell->PVRShellOutputDebug("  Client APIs:  %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_CLIENT_APIS));

+#endif

+

+		m_pShell->PVRShellOutputDebug("\n");

+		m_pShell->PVRShellOutputDebug("Window Width:  %i\n" , m_pShell->PVRShellGet(prefWidth));

+		m_pShell->PVRShellOutputDebug("Window Height: %i\n" , m_pShell->PVRShellGet(prefHeight));

+		m_pShell->PVRShellOutputDebug("Is Rotated: %s\n", m_pShell->PVRShellGet(prefIsRotated) ? "Yes" : "No");

+		m_pShell->PVRShellOutputDebug("\n");

+

+		// EGLSurface details

+		m_pShell->PVRShellOutputDebug("EGL Surface:\n");

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID , &i32Values[0]);

+		m_pShell->PVRShellOutputDebug("  Config ID:      %i\n", i32Values[0]);

+

+		// Colour buffer

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_BUFFER_SIZE , &i32Values[0]);

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_RED_SIZE    , &i32Values[1]);

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_GREEN_SIZE  , &i32Values[2]);

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_BLUE_SIZE   , &i32Values[3]);

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_ALPHA_SIZE  , &i32Values[4]);

+		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]);

+

+		// Depth buffer

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_DEPTH_SIZE , &i32Values[0]);

+		m_pShell->PVRShellOutputDebug("  Depth Buffer:   %i bits\n", i32Values[0]);

+

+		// Stencil Buffer

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_STENCIL_SIZE , &i32Values[0]);

+		m_pShell->PVRShellOutputDebug("  Stencil Buffer: %i bits\n", i32Values[0]);

+

+		// EGL surface bits support

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SURFACE_TYPE , &i32Values[0]);

+		m_pShell->PVRShellOutputDebug("  Surface type:   %s%s%s\n",	i32Values[0] & EGL_WINDOW_BIT  ? "WINDOW " : "",

+																		i32Values[1] & EGL_PBUFFER_BIT ? "PBUFFER " : "",

+																		i32Values[2] & EGL_PIXMAP_BIT  ? "PIXMAP " : "");

+		// EGL renderable type

+#ifdef EGL_VERSION_1_2

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_RENDERABLE_TYPE , &i32Values[0]);

+		m_pShell->PVRShellOutputDebug("  Renderable type: %s%s%s%s\n", i32Values[0] & EGL_OPENVG_BIT ? "OPENVG " : "",

+															i32Values[0] & EGL_OPENGL_ES_BIT ? "OPENGL_ES " : "",

+#ifdef EGL_OPENGL_BIT

+															i32Values[0] & EGL_OPENGL_BIT ? "OPENGL " :

+#endif

+															"",

+															i32Values[0] & EGL_OPENGL_ES2_BIT ? "OPENGL_ES2 " : "");

+#endif

+

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SAMPLE_BUFFERS , &i32Values[0]);

+		eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SAMPLES , &i32Values[1]);

+		m_pShell->PVRShellOutputDebug("  Sample buffer No.: %i\n", i32Values[0]);

+		m_pShell->PVRShellOutputDebug("  Samples per pixel: %i\n", i32Values[1]);

+	}

+}

+

+/*!***********************************************************************

+ @Function		ApiReleaseAPI

+ @description	Releases all resources allocated by the API.

+*************************************************************************/

+void PVRShellInit::ApiReleaseAPI()

+{

+	eglSwapBuffers(m_EGLDisplay, m_EGLWindow);

+	eglMakeCurrent(m_EGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

+ 	eglDestroyContext(m_EGLDisplay, m_EGLContext);

+	eglDestroySurface(m_EGLDisplay, m_EGLWindow);

+   	eglTerminate(m_EGLDisplay);

+}

+

+/*******************************************************************************

+ * Function Name  : SelectEGLConfiguration

+ * Inputs		  : pData

+ * Returns        : EGLConfig

+ * Description    : Find the config to use for EGL initialisation

+ *******************************************************************************/

+EGLConfig PVRShellInitAPI::SelectEGLConfiguration(const PVRShellData * const pData)

+{

+    EGLint		num_config;

+    EGLint		conflist[32];

+	EGLConfig	conf = (EGLConfig) 0;

+    int			i = 0;

+

+	// Specific config ID requested?

+	if (m_iRequestedConfig > 0)

+	{

+		conflist[i++] = EGL_CONFIG_ID;

+		conflist[i++] = m_iRequestedConfig;

+		conflist[i++] = EGL_NONE;

+		if(!eglChooseConfig(m_EGLDisplay, conflist, &conf, 1, &num_config) || num_config != 1)

+		{

+			return 0;

+		}

+		return conf;

+	}

+

+	// Select default configuration

+#if defined(ANDROID)

+	if(pData->nColorBPP == 32)

+	{

+		conflist[i++] = EGL_RED_SIZE;

+		conflist[i++] = 8;

+		conflist[i++] = EGL_GREEN_SIZE;

+		conflist[i++] = 8;

+		conflist[i++] = EGL_BLUE_SIZE;

+		conflist[i++] = 8;

+		conflist[i++] = EGL_ALPHA_SIZE;

+		conflist[i++] = 8;

+	}

+	else

+	{

+		conflist[i++] = EGL_RED_SIZE;

+		conflist[i++] = 5;

+		conflist[i++] = EGL_GREEN_SIZE;

+		conflist[i++] = 6;

+		conflist[i++] = EGL_BLUE_SIZE;

+		conflist[i++] = 5;

+		conflist[i++] = EGL_ALPHA_SIZE;

+		conflist[i++] = 0;

+	}

+#else

+	conflist[i++] = EGL_BUFFER_SIZE;

+	conflist[i++] = pData->nColorBPP;

+#endif

+

+	if(pData->bNeedZbuffer || pData->nDepthBPP > 0)

+	{

+		conflist[i++] = EGL_DEPTH_SIZE;

+		conflist[i++] = (pData->nDepthBPP > 0) ? pData->nDepthBPP : 16;

+	}

+

+	if(pData->bNeedStencilBuffer)

+	{

+		conflist[i++] = EGL_STENCIL_SIZE;

+		conflist[i++] = 8;

+	}

+

+	conflist[i++] = EGL_SURFACE_TYPE;

+	conflist[i] = EGL_WINDOW_BIT;

+

+	if(pData->bNeedPbuffer)

+	{

+		conflist[i] |= EGL_PBUFFER_BIT;

+	}

+

+	if(pData->bNeedPixmap)

+	{

+		conflist[i] |= EGL_PIXMAP_BIT;

+	}

+

+	++i;

+

+#if defined(BUILD_OGL)

+	conflist[i++] = EGL_RENDERABLE_TYPE;

+	conflist[i++] = EGL_OPENGL_BIT;

+#elif defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0)

+	conflist[i++] = EGL_RENDERABLE_TYPE;

+	conflist[i++] = EGL_OPENGL_ES2_BIT;

+#endif

+

+	// Append number of number of samples depending on AA samples value set

+	if(pData->nAASamples > 0)

+	{

+		conflist[i++] = EGL_SAMPLE_BUFFERS;

+		conflist[i++] = 1;

+		conflist[i++] = EGL_SAMPLES;

+		conflist[i++] = pData->nAASamples;

+	}

+	else

+	{

+		conflist[i++] = EGL_SAMPLE_BUFFERS;

+		conflist[i++] = 0;

+	}

+

+#if defined(EWS) || defined(__QNXNTO__)

+	if(m_NWT != NULL)

+	{

+		EGLint r,g,b,a, value;

+		EGLint i32Total_num_configs, j;

+		EGLConfig	*pConfigs;

+

+		// Some platforms require an egl config to have the same pixel format as the native window because

+		// pixel format conversion is prohibited.

+#if defined(EWS)

+		int format = EWS_PIXEL_FORMAT_RGB_565;

+		r = 5; g = 6; b = 5; a = 0;

+#else

+		r = g = b = a = 8;

+#endif

+

+		conflist[i++] = EGL_RED_SIZE;

+		conflist[i++] = r;

+

+		conflist[i++] = EGL_GREEN_SIZE;

+		conflist[i++] = g;

+

+		conflist[i++] = EGL_BLUE_SIZE;

+		conflist[i++] = b;

+

+		conflist[i++] = EGL_ALPHA_SIZE;

+		conflist[i++] = a;

+

+		// Terminate the list with EGL_NONE

+		conflist[i++] = EGL_NONE;

+

+		// Find out how many configs there are in total that match our criteria

+		if(!eglChooseConfig(m_EGLDisplay, conflist, NULL, 0, &i32Total_num_configs) || i32Total_num_configs == 0)

+			return 0;

+

+		// Allocate an array large enough to store all the possible configs that may be returned

+		pConfigs = new EGLConfig[i32Total_num_configs];

+

+		if(!pConfigs)

+			return 0;

+

+		// Get all the configs that match our criteria

+		if(!eglChooseConfig(m_EGLDisplay, conflist, pConfigs, i32Total_num_configs, &num_config))

+		{

+			delete[] pConfigs;

+			return 0;

+		}

+

+		// Go through the returned configs and try and find a suitable match

+		for(j = 0; j < num_config; ++j)

+		{

+#if defined(__QNXNTO__)

+			if((eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_RED_SIZE,   &value) && value == r)

+			&& (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_GREEN_SIZE, &value) && value == g)

+			&& (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_BLUE_SIZE,  &value) && value == b)

+			&& (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_ALPHA_SIZE, &value) && value == a))

+			{

+				conf = pConfigs[j];

+				break;

+			}

+#else

+#if defined (EWS)

+			eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_NATIVE_VISUAL_ID, &value);

+			if (value == format)

+			{

+				conf = pConfigs[j];

+				break;

+			}

+#endif

+#endif

+		}

+

+		// Tidy up

+		delete[] pConfigs;

+	}

+	else

+#endif

+	{

+		// Terminate the list with EGL_NONE

+		conflist[i++] = EGL_NONE;

+

+		// Return null config if config is not found

+		if(!eglChooseConfig(m_EGLDisplay, conflist, &conf, 1, &num_config) || num_config != 1)

+		{

+			return 0;

+		}

+	}

+

+	// Return config index

+	return conf;

+}

+

+/*******************************************************************************

+ * Function Name  : StringFrom_eglGetError

+ * Returns        : A string

+ * Description    : Returns a string representation of an egl error

+ *******************************************************************************/

+const char *PVRShellInitAPI::StringFrom_eglGetError() const

+{

+	EGLint nErr = eglGetError();

+

+	switch(nErr)

+	{

+		case EGL_SUCCESS:

+			return "EGL_SUCCESS";

+		case EGL_BAD_DISPLAY:

+			return "EGL_BAD_DISPLAY";

+		case EGL_NOT_INITIALIZED:

+			return "EGL_NOT_INITIALIZED";

+		case EGL_BAD_ACCESS:

+			return "EGL_BAD_ACCESS";

+		case EGL_BAD_ALLOC:

+			return "EGL_BAD_ALLOC";

+		case EGL_BAD_ATTRIBUTE:

+			return "EGL_BAD_ATTRIBUTE";

+		case EGL_BAD_CONFIG:

+			return "EGL_BAD_CONFIG";

+		case EGL_BAD_CONTEXT:

+			return "EGL_BAD_CONTEXT";

+		case EGL_BAD_CURRENT_SURFACE:

+			return "EGL_BAD_CURRENT_SURFACE";

+		case EGL_BAD_MATCH:

+			return "EGL_BAD_MATCH";

+		case EGL_BAD_NATIVE_PIXMAP:

+			return "EGL_BAD_NATIVE_PIXMAP";

+		case EGL_BAD_NATIVE_WINDOW:

+			return "EGL_BAD_NATIVE_WINDOW";

+		case EGL_BAD_PARAMETER:

+			return "EGL_BAD_PARAMETER";

+		case EGL_BAD_SURFACE:

+			return "EGL_BAD_SURFACE";

+		default:

+			return "unknown";

+	}

+}

+

+/*!***********************************************************************

+@Function		ApiScreenCaptureBuffer

+@Input			Width Width of the region to capture

+@Input			Height Height of the region to capture

+@Input			pBuf A buffer to put the screen capture into

+@description	API-specific function to store the current content of the

+				FrameBuffer into the memory allocated by the user.

+*************************************************************************/

+bool PVRShellInit::ApiScreenCaptureBuffer(int Width,int Height,unsigned char *pBuf)

+{

+	unsigned char	*pLines2;

+	int				i, j;

+	bool			bRet = true;

+

+	/* Allocate memory for line */

+	pLines2 = (unsigned char *)calloc(4 * Width * Height, sizeof(unsigned char));

+	if (!pLines2) return false;

+

+	while (glGetError());

+	/* Read line from frame buffer */

+	glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pLines2);

+

+	if(glGetError())

+	{

+		bRet = false;

+	}

+	else

+	{

+		/* Convert RGB to BGR in line */

+		for (j = 0, i = 0; j < 4 * Width * Height; j += 4, i += 3)

+		{

+			pBuf[i] = pLines2[j+2];

+			pBuf[i+1] = pLines2[j+1];

+			pBuf[i+2] = pLines2[j];

+		}

+	}

+

+	free(pLines2);

+	return bRet;

+}

+

+/*!***********************************************************************

+ @Function		ApiRenderComplete

+ @description	Perform API operations required after a frame has finished (e.g., flipping).

+*************************************************************************/

+void PVRShellInit::ApiRenderComplete()

+{

+

+#if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3)

+	//Discard the framebuffer if set.

+#if !defined(BUILD_OGLES3)

+	if (glDiscardFramebufferEXT)

+#endif

+	{

+		const GLint numAttachments=3;

+		GLenum attachments[numAttachments];

+		GLint currentAttachment=0;

+		if (m_pShell->PVRShellGet(prefDiscardColor))

+		{

+			attachments[currentAttachment] = GL_COLOR_EXT;

+			currentAttachment++;

+		}

+		if (m_pShell->PVRShellGet(prefDiscardDepth))

+		{

+			attachments[currentAttachment] = GL_DEPTH_EXT;

+			currentAttachment++;

+		}

+		if (m_pShell->PVRShellGet(prefDiscardStencil))

+		{

+			attachments[currentAttachment] = GL_STENCIL_EXT;

+			currentAttachment++;

+		}

+		//Assuming some attachments have been chosen, discard/invalidate them.

+		if (currentAttachment!=0)

+		{

+#if defined(BUILD_OGLES)

+			glDiscardFramebufferEXT(GL_FRAMEBUFFER_OES, currentAttachment, attachments);

+#elif defined(BUILD_OGLES2)

+			glDiscardFramebufferEXT(GL_FRAMEBUFFER, currentAttachment, attachments);

+#elif defined(BUILD_OGLES3)

+			glInvalidateFramebuffer(GL_FRAMEBUFFER, currentAttachment, attachments);

+#endif

+		}

+	}

+#endif

+

+	bool bRes;

+

+	if(m_pShell->m_pShellData->bNeedPixmap)

+	{

+		/*

+			"Clients rendering to single buffered surfaces (e.g. pixmap surfaces)

+			should call eglWaitGL before accessing the native pixmap from the client."

+		*/

+		eglWaitGL();

+

+		// Pixmap support: Copy the rendered pixmap to the display

+		if(m_pShell->m_pShellData->bNeedPixmapDisableCopy)

+		{

+			bRes = true;

+		}

+		else

+		{

+			bRes = OsPixmapCopy();

+		}

+	}

+	else

+	{

+		if(m_pShell->m_pShellData->bNoShellSwapBuffer)

+			return;

+

+		bRes = (eglSwapBuffers (m_EGLDisplay, m_EGLWindow) == EGL_TRUE);

+	}

+

+	if(!bRes)

+	{

+		// check for context loss

+#ifdef EGL_VERSION_1_3

+		if(eglGetError() == EGL_CONTEXT_LOST)

+#else

+		if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported)

+#endif

+		{

+			m_pShell->ReleaseView();

+

+			OsDoReleaseAPI();

+			if(ApiInitAPI())

+			{

+				m_pShell->InitView();

+			}

+		}

+		else

+		{

+			if(m_pShell->m_pShellData->bNeedPixmap)

+				m_pShell->PVRShellOutputDebug("failed to copy pixmap\n");

+			else

+				m_pShell->PVRShellOutputDebug("eglSwapBuffers failed\n");

+		}

+	}

+}

+

+/*!***********************************************************************

+ @Function		ApiSet

+ @Input			prefName	Name of value to set

+ @Modified		i32Value	Value to set it to

+ @description	Set parameters which are specific to the API.

+*************************************************************************/

+bool PVRShellInit::ApiSet(const prefNameIntEnum prefName, const int i32Value)

+{

+	switch(prefName)

+	{

+#ifdef EGL_VERSION_1_1

+	case prefSwapInterval:

+		m_pShell->m_pShellData->nSwapInterval = i32Value;

+		return true;

+#endif

+#if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3)

+	case prefPriority:

+		m_pShell->m_pShellData->nPriority = i32Value;

+		return true;

+#endif

+	case prefRequestedConfig:

+		m_iRequestedConfig = (EGLint) i32Value;

+		return true;

+

+	default:

+		return false;

+	}

+}

+

+/*!***********************************************************************

+ @Function		ApiGet

+ @Input			prefName	Name of value to get

+ @Modified		pn A pointer set to the value asked for

+ @description	Get parameters which are specific to the API.

+*************************************************************************/

+bool PVRShellInit::ApiGet(const prefNameIntEnum prefName, int *pn)

+{

+	switch(prefName)

+	{

+		case prefEGLMajorVersion:

+			*pn = (int) m_MajorVersion;

+			return true;

+

+		case prefEGLMinorVersion:

+			*pn = (int) m_MinorVersion;

+			return true;

+

+		case prefRequestedConfig:

+			*pn = (int) m_iRequestedConfig;

+			return true;

+

+		case prefConfig:

+			*pn = (int) m_iConfig;

+			return true;

+

+		default:

+			return false;

+	}

+}

+

+/*!***********************************************************************

+ @Function		ApiGet

+ @Input			prefName	Name of value to get

+ @Modified		pp A pointer set to the value asked for

+ @description	Get parameters which are specific to the API.

+*************************************************************************/

+bool PVRShellInit::ApiGet(const prefNamePtrEnum prefName, void **pp)

+{

+		switch(prefName)

+		{

+		case prefEGLDisplay:

+			*pp = (void*)m_EGLDisplay;

+			return true;

+		case prefEGLSurface:

+			*pp = (void*)m_EGLWindow;

+			return true;

+		default:

+			return false;

+		}

+}

+

+/****************************************************************************

+** Local code

+****************************************************************************/

+

+// The recommended technique for querying OpenGL extensions;

+// adapted from http://opengl.org/resources/features/OGLextensions/

+static bool PVRShellIsExtensionSupported(EGLDisplay dpy, const char *extension)

+{

+	// The recommended technique for querying EGL extensions matches OpenGLES;

+	// from http://opengl.org/resources/features/OGLextensions/

+    const char *extensions = NULL;

+    const char *start;

+    char *terminator;

+

+    /* Extension names should not have spaces. */

+    char* where = (char *) strchr(extension, ' ');

+    if (where || *extension == '\0')

+        return 0;

+

+    extensions = eglQueryString(dpy, EGL_EXTENSIONS);

+	if(!extensions)

+		return false;

+

+    /* It takes a bit of care to be fool-proof about parsing the

+    OpenGL extensions string. Don't be fooled by sub-strings, etc. */

+    start = extensions;

+    for (;;) {

+        where = (char *) strstr((const char *) start, extension);

+        if (!where)

+            break;

+        terminator = where + strlen(extension);

+        if (where == start || *(where - 1) == ' ')

+            if (*terminator == ' ' || *terminator == '\0')

+                return true;

+        start = terminator;

+    }

+    return false;

+}

+

+/// @endcond

+

+/*****************************************************************************

+ End of file (PVRShellAPI.cpp)

+*****************************************************************************/

+