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)
+*****************************************************************************/
+