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