blob: 4b7fb54ef55449e60f580e0ab1dda532e8723aed [file] [log] [blame]
/******************************************************************************
@File OGLES2/PVRTBackground.cpp
@Title OGLES2/PVRTBackground
@Version
@Copyright Copyright (c) Imagination Technologies Limited.
@Platform ANSI compatible
@Description Function to draw a background texture.
******************************************************************************/
#include "PVRTShader.h"
#include "PVRTBackground.h"
// The header that contains the shaders
#include "PVRTBackgroundShaders.h"
// Index to bind the attributes to vertex shaders
const int VERTEX_ARRAY = 0;
const int TEXCOORD_ARRAY = 1;
/****************************************************************************
** Structures
****************************************************************************/
// The struct to include various API variables
struct SPVRTBackgroundAPI
{
GLuint m_ui32VertexShader;
GLuint m_ui32FragShader;
GLuint m_ui32ProgramObject;
GLuint m_ui32VertexBufferObject;
};
/****************************************************************************
** Class: CPVRTBackground
****************************************************************************/
/*****************************************************************************
@Function Background
@Description Init some values.
*****************************************************************************/
CPVRTBackground::CPVRTBackground(void)
{
m_bInit = false;
m_pAPI = 0;
}
/*****************************************************************************
@Function ~Background
@Description Calls Destroy()
*****************************************************************************/
CPVRTBackground::~CPVRTBackground(void)
{
delete m_pAPI;
m_pAPI = 0;
}
/*!***************************************************************************
@Function Destroy
@Description Destroys the background and releases API specific resources
*****************************************************************************/
void CPVRTBackground::Destroy()
{
if(m_bInit)
{
// Delete shaders
glDeleteProgram(m_pAPI->m_ui32ProgramObject);
glDeleteShader(m_pAPI->m_ui32VertexShader);
glDeleteShader(m_pAPI->m_ui32FragShader);
// Delete buffer objects
glDeleteBuffers(1, &m_pAPI->m_ui32VertexBufferObject);
m_bInit = false;
}
delete m_pAPI;
m_pAPI = 0;
}
/*!***************************************************************************
@Function Init
@Input pContext A pointer to a PVRTContext
@Input bRotate true to rotate texture 90 degrees.
@Input pszError An option string for returning errors
@Return PVR_SUCCESS on success
@Description Initialises the background
*****************************************************************************/
EPVRTError CPVRTBackground::Init(const SPVRTContext * const pContext, bool bRotate, CPVRTString *pszError)
{
PVRT_UNREFERENCED_PARAMETER(pContext);
Destroy();
m_pAPI = new SPVRTBackgroundAPI;
if(!m_pAPI)
{
if(pszError)
*pszError = "Error: Insufficient memory to allocate SCPVRTBackgroundAPI.";
return PVR_FAIL;
}
m_pAPI->m_ui32VertexShader = 0;
m_pAPI->m_ui32FragShader = 0;
m_pAPI->m_ui32ProgramObject = 0;
m_pAPI->m_ui32VertexBufferObject = 0;
bool bResult;
CPVRTString sTmpErrStr;
// The shader loading code doesn't expect a null pointer for the error string
if(!pszError)
pszError = &sTmpErrStr;
/* Compiles the shaders. For a more detailed explanation, see IntroducingPVRTools */
#if defined(GL_SGX_BINARY_IMG)
// Try binary shaders first
bResult = (PVRTShaderLoadBinaryFromMemory(_BackgroundFragShader_fsc, _BackgroundFragShader_fsc_size,
GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_pAPI->m_ui32FragShader, pszError) == PVR_SUCCESS)
&& (PVRTShaderLoadBinaryFromMemory(_BackgroundVertShader_vsc, _BackgroundVertShader_vsc_size,
GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_pAPI->m_ui32VertexShader, pszError) == PVR_SUCCESS);
if(!bResult)
#endif
{
// if binary shaders don't work, try source shaders
bResult = (PVRTShaderLoadSourceFromMemory(_BackgroundFragShader_fsh, GL_FRAGMENT_SHADER, &m_pAPI->m_ui32FragShader, pszError) == PVR_SUCCESS) &&
(PVRTShaderLoadSourceFromMemory(_BackgroundVertShader_vsh, GL_VERTEX_SHADER, &m_pAPI->m_ui32VertexShader, pszError) == PVR_SUCCESS);
}
_ASSERT(bResult);
if(!bResult)
return PVR_FAIL;
// Reset the error string
if(pszError)
*pszError = "";
// Create the shader program
m_pAPI->m_ui32ProgramObject = glCreateProgram();
// Attach the fragment and vertex shaders to it
glAttachShader(m_pAPI->m_ui32ProgramObject, m_pAPI->m_ui32FragShader);
glAttachShader(m_pAPI->m_ui32ProgramObject, m_pAPI->m_ui32VertexShader);
// Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
glBindAttribLocation(m_pAPI->m_ui32ProgramObject, VERTEX_ARRAY, "myVertex");
// Bind the custom vertex attribute "myUV" to location TEXCOORD_ARRAY
glBindAttribLocation(m_pAPI->m_ui32ProgramObject, TEXCOORD_ARRAY, "myUV");
// Link the program
glLinkProgram(m_pAPI->m_ui32ProgramObject);
GLint Linked;
glGetProgramiv(m_pAPI->m_ui32ProgramObject, GL_LINK_STATUS, &Linked);
if (!Linked)
{
int i32InfoLogLength, i32CharsWritten;
glGetProgramiv(m_pAPI->m_ui32ProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
char* pszInfoLog = new char[i32InfoLogLength];
glGetProgramInfoLog(m_pAPI->m_ui32ProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
*pszError = CPVRTString("Failed to link: ") + pszInfoLog + "\n";
delete [] pszInfoLog;
bResult = false;
}
_ASSERT(bResult);
if(!bResult)
return PVR_FAIL;
// Use the loaded shader program
glUseProgram(m_pAPI->m_ui32ProgramObject);
// Set the sampler2D variable to the first texture unit
glUniform1i(glGetUniformLocation(m_pAPI->m_ui32ProgramObject, "sampler2d"), 0);
// Create the vertex buffer object
GLfloat *pVertexData = 0;
// The vertex data for non-rotated
GLfloat afVertexData[16] = { -1, -1, 1, -1, -1, 1, 1, 1,
0, 0, 1, 0, 0, 1, 1, 1};
// The vertex data for rotated
GLfloat afVertexDataRotated[16] = {-1, 1, -1, -1, 1, 1, 1, -1,
1, 1, 0, 1, 1, 0, 0, 0};
if(!bRotate)
pVertexData = &afVertexData[0];
else
pVertexData = &afVertexDataRotated[0];
glGenBuffers(1, &m_pAPI->m_ui32VertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, m_pAPI->m_ui32VertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, pVertexData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_bInit = true;
return PVR_SUCCESS;
}
/*!***************************************************************************
@Function Draw
@Input ui32Texture Texture to use
@Return PVR_SUCCESS on success
@Description Draws a texture on a quad covering the whole screen.
*****************************************************************************/
EPVRTError CPVRTBackground::Draw(const GLuint ui32Texture)
{
if(!m_bInit)
return PVR_FAIL;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ui32Texture);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
// Use the loaded shader program
glUseProgram(m_pAPI->m_ui32ProgramObject);
// Set vertex data
glBindBuffer(GL_ARRAY_BUFFER, m_pAPI->m_ui32VertexBufferObject);
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, (const void*) 0);
// Set texture coordinates
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, (const void*) (8 * sizeof(float)));
// Render geometry
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableVertexAttribArray(VERTEX_ARRAY);
glDisableVertexAttribArray(TEXCOORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
return PVR_SUCCESS;
}
/*****************************************************************************
End of file (CPVRTBackground.cpp)
*****************************************************************************/