Sources/Toolkits/OpenGL/Shaders/GLUProgram.mm
/* |
File: GLUProgram.mm |
Abstract: n/a |
Version: 1.2 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Inc. ("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or redistribution of |
this Apple software constitutes acceptance of these terms. If you do |
not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. may |
be used to endorse or promote products derived from the Apple Software |
without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or |
implied, are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or by other |
works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2014 Apple Inc. All Rights Reserved. |
*/ |
#pragma mark - |
#pragma mark Headers |
// OpenGL core profile |
#import <OpenGL/gl3.h> |
// String copy utilities |
#import "CFString.h" |
// OpenGL string utilities |
#import "GLUString.h" |
// OpenGL file stream utilities |
#import "CFIFStream.h" |
// OpenGL utilities header |
#import "GLUProgram.h" |
#pragma mark - |
#pragma mark Private - Data Structures |
namespace GLU |
{ |
// GLSL program description |
struct Program |
{ |
GLuint mnPID; |
Inputs m_Inputs; |
Locations m_Fragments; |
Locations m_Attributes; |
Objects m_Shaders; |
Sources m_Sources; |
}; // Program |
typedef struct Program Program; |
} // GLU |
#pragma mark - |
#pragma mark Private - Utilities - Destructor |
static void GLUProgramClearInputs(GLU::ProgramRef pProgram) |
{ |
if(!pProgram->m_Inputs.empty()) |
{ |
pProgram->m_Inputs.clear(); |
} // if |
} // GLUProgramClearInputs |
// Delete locations |
static void GLUProgramClearLocations(GLU::ProgramRef pProgram) |
{ |
if(!pProgram->m_Fragments.empty()) |
{ |
pProgram->m_Fragments.clear(); |
} // if |
if(!pProgram->m_Attributes.empty()) |
{ |
pProgram->m_Attributes.clear(); |
} // if |
} // GLUProgramClearLocations |
// Delete inputs |
static void GLUProgramClearSources(GLU::ProgramRef pProgram) |
{ |
if(!pProgram->m_Sources.empty()) |
{ |
pProgram->m_Sources.clear(); |
} // if |
} // GLUProgramClearSources |
// Delete all the shaders |
static void GLUProgramDeleteShaders(GLU::ProgramRef pProgram) |
{ |
if(!pProgram->m_Shaders.empty()) |
{ |
for(auto& shader:pProgram->m_Shaders) |
{ |
glDeleteShader(shader); |
} // if |
pProgram->m_Shaders.clear(); |
} // if |
} // GLUProgramDeleteShaders |
// Delete program object |
static void GLUProgramDeleteProgObj(GLU::ProgramRef pProgram) |
{ |
if(!pProgram->mnPID) |
{ |
glDeleteProgram(pProgram->mnPID); |
} // if |
} // GLUProgramDeleteProgObj |
// Delete all the program object and shaders |
static void GLUProgramDelete(GLU::ProgramRef pProgram) |
{ |
GLUProgramClearInputs(pProgram); |
GLUProgramClearLocations(pProgram); |
GLUProgramClearSources(pProgram); |
GLUProgramDeleteShaders(pProgram); |
GLUProgramDeleteProgObj(pProgram); |
delete pProgram; |
} // GLUProgramDelete |
#pragma mark - |
#pragma mark Private - Utilities - Locations |
// Function pointer definition for location binding |
typedef void (*GLUProgramBindLocationFuncPtr)(GLuint nPID, GLuint nIndex, const GLchar *pName); |
// Bind locations using an OpenGL function |
static bool GLUProgramBindLocations(const GLuint nPID, |
GLU::Locations &rLocations, |
GLUProgramBindLocationFuncPtr GLUBindLocation) |
{ |
bool bSuccess = !rLocations.empty(); |
if(bSuccess) |
{ |
// Vertex shader inputs |
for(auto& location: rLocations) |
{ |
GLUBindLocation(nPID, location.first, location.second.c_str()); |
} // for |
} // if |
return bSuccess; |
} // GLUProgramBindLocations |
// Create an associative array (a.k.a. map) from key-value pairs |
static GLU::Locations GLUProgramLocationsCreate(const GLU::UInts &rKeys, |
const GLU::Strings &rValues) |
{ |
GLU::Locations locs; |
if(!rKeys.empty()) |
{ |
GLuint i = 0; |
// Insert the key-value pair into an associative array |
for(auto& key:rKeys) |
{ |
locs[key] = rValues[i]; |
++i; |
} // for |
} // if |
return locs; |
} // GLUProgramLocationsCreate |
// Create an associative array (a.k.a. map) from key-value pairs |
static GLU::Locations GLUProgramLocationsCreate(CFArrayRef pKeys, |
CFArrayRef pValues) |
{ |
GLU::Locations locs; |
if(pKeys && pValues) |
{ |
GLuint iMax = CFArrayGetCount(pKeys); |
GLuint jMax = CFArrayGetCount(pValues); |
if(iMax > jMax) |
{ |
iMax = jMax; |
} // if |
if(iMax) |
{ |
GLuint i; |
CFStringRef pValue = NULL; |
CFNumberRef pKey = NULL; |
GLuint key = 0; |
bool bSuccess = false; |
// Insert the key-value pair into an associative array |
for(i = 0; i < iMax; ++i) |
{ |
pKey = CFNumberRef(CFArrayGetValueAtIndex(pKeys, i)); |
if(pKey != nullptr) |
{ |
pValue = CFStringRef(CFArrayGetValueAtIndex(pValues, i)); |
bSuccess = pValue != nullptr; |
bSuccess = bSuccess && CFNumberGetValue(pKey, kCFNumberSInt32Type, &key); |
if(bSuccess) |
{ |
locs[GLuint(key)] = CF::StringCreateCStringCopy(pValue); |
} // ikf |
} // if |
} // for |
} // if |
} // if |
return locs; |
} // GLUProgramLocationsCreate |
// Applier function for converting a CFDictionary to a STL map |
static void GLUProgramLocationsApplyFunction(const void *pKey, |
const void *pValue, |
void *pContext) |
{ |
if(pKey && pValue) |
{ |
GLuint key = 0; |
if(CFNumberGetValue(CFNumberRef(pKey), kCFNumberSInt32Type, &key)) |
{ |
GLU::String value = CF::StringCreateCStringCopy(CFStringRef(pValue)); |
GLU::Locations *pLocs = (GLU::Locations *)pContext; |
pLocs->insert(GLU::Location(GLuint(key),value)); |
} // if |
} // if |
} // GLUProgramLocationsApplyFunction |
// Create an associative array (a.k.a. map) from key-value pairs |
static GLU::Locations GLUProgramLocationsCreate(CFDictionaryRef pLocations) |
{ |
GLU::Locations locs; |
if(pLocations != nullptr) |
{ |
GLuint nCount = CFDictionaryGetCount(pLocations); |
if(nCount) |
{ |
CFDictionaryApplyFunction(pLocations,GLUProgramLocationsApplyFunction,&locs); |
} // if |
} // if |
return locs; |
} // GLUProgramLocationsCreate |
#pragma mark - |
#pragma mark Private - Utilities - Inputs |
// Acquire inputs for a geometry shader |
static bool GLUProgramAddInputs(const GLenum& nInputType, |
const GLenum& nOutputType, |
const GLuint& nVerticesOut, |
GLU::ProgramRef pProgram) |
{ |
pProgram->m_Inputs[GL_GEOMETRY_INPUT_TYPE] = nInputType; |
pProgram->m_Inputs[GL_GEOMETRY_OUTPUT_TYPE] = nOutputType; |
pProgram->m_Inputs[GL_GEOMETRY_VERTICES_OUT] = nVerticesOut; |
return pProgram->m_Inputs.size() == 3; |
} // GLUProgramInputsAcquire |
// Set geometry shader stage parameters |
static void GLUProgramBindInputs(GLU::ProgramRef pProgram) |
{ |
if(!pProgram->m_Inputs.empty()) |
{ |
GLenum nInputType = pProgram->m_Inputs[GL_GEOMETRY_INPUT_TYPE]; |
GLenum nOutputType = pProgram->m_Inputs[GL_GEOMETRY_OUTPUT_TYPE]; |
GLuint nVertices = pProgram->m_Inputs[GL_GEOMETRY_VERTICES_OUT]; |
glProgramParameteri(pProgram->mnPID, GL_GEOMETRY_INPUT_TYPE, nInputType); |
glProgramParameteri(pProgram->mnPID, GL_GEOMETRY_OUTPUT_TYPE, nOutputType); |
glProgramParameteri(pProgram->mnPID, GL_GEOMETRY_VERTICES_OUT, nVertices); |
} // if |
} // GLUProgramBindInputs |
#pragma mark - |
#pragma mark Private - Utilities - Shader Sources |
// Compile vertex and fragment shaders, with/without optional |
// geometry shader |
static bool GLUProgramAcquireShaderSources(const GLU::Source& rVertex, |
const GLU::Source& rFragment, |
const GLU::Source& rGeometry, |
GLU::ProgramRef pProgram) |
{ |
bool bSuccess = !rVertex.empty() && !rFragment.empty(); |
if(bSuccess) |
{ |
pProgram->m_Sources[GL_VERTEX_SHADER] = rVertex; |
pProgram->m_Sources[GL_FRAGMENT_SHADER] = rFragment; |
if(!rGeometry.empty()) |
{ |
pProgram->m_Sources[GL_GEOMETRY_SHADER] = rGeometry; |
} // if |
} // if |
return bSuccess; |
} // GLUProgramAcquireShaderSources |
// Compile vertex and fragment shaders |
static bool GLUProgramAcquireShaderSources(const GLU::Source& rVertex, |
const GLU::Source& rFragment, |
GLU::ProgramRef pProgram) |
{ |
return GLUProgramAcquireShaderSources(rVertex, rFragment, "", pProgram); |
} // GLUProgramAcquireShaderSources |
// Compile vertex and fragment shaders, with/without optional |
// geometry shader |
static bool GLUProgramAcquireShaderSources(CFStringRef pVertex, |
CFStringRef pFragment, |
CFStringRef pGeometry, |
GLU::ProgramRef pProgram) |
{ |
GLchar *vertex = CF::StringCreateBufferCopy(pVertex); |
GLchar *fragment = CF::StringCreateBufferCopy(pFragment); |
bool bSuccess = (vertex != nullptr) && (fragment != nullptr); |
if(bSuccess) |
{ |
pProgram->m_Sources[GL_VERTEX_SHADER] = vertex; |
pProgram->m_Sources[GL_FRAGMENT_SHADER] = fragment; |
GLchar *geometry = CF::StringCreateBufferCopy(pGeometry); |
if(geometry != nullptr) |
{ |
pProgram->m_Sources[GL_GEOMETRY_SHADER] = geometry; |
free(geometry); |
} // if |
} // if |
if(vertex != nullptr) |
{ |
free(vertex); |
} // if |
if(fragment != nullptr) |
{ |
free(fragment); |
} // if |
return bSuccess; |
} // GLUProgramAcquireShaderSources |
// Compile vertex and fragment shaders |
static bool GLUProgramAcquireShaderSources(CFStringRef pVertex, |
CFStringRef pFragment, |
GLU::ProgramRef pProgram) |
{ |
return GLUProgramAcquireShaderSources(pVertex, pFragment, nullptr, pProgram); |
} // GLUProgramAcquireShaderSources |
#pragma mark - |
#pragma mark Private - Utilities - Shaders |
// Compile a shader from source string |
static void GLUProgramCompileShader(GLuint nShader, |
const GLU::Source &rShaderSource) |
{ |
GLint nInfoLogLength = 0; |
if(!rShaderSource.empty()) |
{ |
const GLchar *pShaderSource = rShaderSource.c_str(); |
glShaderSource(nShader, 1, &pShaderSource, nullptr); |
glCompileShader(nShader); |
glGetShaderiv(nShader, GL_INFO_LOG_LENGTH, &nInfoLogLength); |
if(nInfoLogLength) |
{ |
GLchar *pInfoLog = NULL; |
try |
{ |
pInfoLog = new GLchar[nInfoLogLength]; |
glGetShaderInfoLog(nShader, |
nInfoLogLength, |
&nInfoLogLength, |
pInfoLog); |
NSLog(@">> INFO: OpenGL Shader - Shader compile log:\n%s\n", pInfoLog); |
delete [] pInfoLog; |
} // try |
catch(std::bad_alloc& ba) |
{ |
NSLog(@">> ERROR: Failed allocating memory for shader compilation info. log: \"%s\"", ba.what()); |
} // catch |
} // if |
} // if |
} // GLUProgramCompileShader |
// Validate a compiled shader |
static bool GLUProgramValidateShader(const GLuint nShader, |
const GLU::Source &rShaderSource) |
{ |
GLint nIsCompiled = 0; |
glGetShaderiv(nShader, GL_COMPILE_STATUS, &nIsCompiled); |
if(nIsCompiled == 0) |
{ |
if(!rShaderSource.empty()) |
{ |
NSLog(@">> WARNING: OpenGL Shader - Failed to compile shader!\n%s\n", rShaderSource.c_str()); |
} // if |
NSLog(@">> WARNING: OpenGL Shader - Deleted shader object with id = %d", nShader); |
glDeleteShader(nShader); |
} // if |
return nIsCompiled != 0; |
} // GLUProgramValidateShader |
// Create, and validate, a shader from a source string |
static GLuint GLUProgramCreateShader(const GLenum nShaderType, |
GLU::ProgramRef pProgram) |
{ |
GLuint nShader = glCreateShader(nShaderType); |
if(nShader) |
{ |
GLUProgramCompileShader(nShader, pProgram->m_Sources[nShaderType]); |
if(!GLUProgramValidateShader(nShader, pProgram->m_Sources[nShaderType])) |
{ |
nShader = 0; |
} // if |
} // if |
return nShader; |
} // GLUProgramCreateShader |
// Compile vertex and fragment shaders, with/without optional geometry shader |
static bool GLUProgramAcquireShaders(GLU::ProgramRef pProgram) |
{ |
bool bSuccess = |
(!pProgram->m_Sources[GL_VERTEX_SHADER].empty()) |
&& (!pProgram->m_Sources[GL_FRAGMENT_SHADER].empty()); |
if(bSuccess) |
{ |
// Compile the mandatory vertex and fragment shaders |
// Create a vertex shader |
GLuint shaderID = GLUProgramCreateShader(GL_VERTEX_SHADER, pProgram); |
bool bSuccess = bool(shaderID); |
if(bSuccess) |
{ |
// Insert vertex shader id into the vector |
pProgram->m_Shaders.push_back(shaderID); |
// Create a fragment shader |
shaderID = GLUProgramCreateShader(GL_FRAGMENT_SHADER, pProgram); |
bSuccess = bool(shaderID); |
if(bSuccess) |
{ |
// Insert fragment shader id into the vector |
pProgram->m_Shaders.push_back(shaderID); |
// If optional geometry shader stage is required |
if(pProgram->m_Sources.size() == 3) |
{ |
shaderID = GLUProgramCreateShader(GL_GEOMETRY_SHADER, pProgram); |
bSuccess = bool(shaderID); |
if(bSuccess) |
{ |
// Insert optional geometry shader id into the vector |
pProgram->m_Shaders.push_back(shaderID); |
} // if |
} // if |
} // if |
} // if |
if(!bSuccess) |
{ |
GLUProgramDeleteShaders(pProgram); |
} // if |
} // if |
return bSuccess; |
} // GLUProgramAcquireShaders |
#pragma mark - |
#pragma mark Private - Utilities - Attaching |
// Attach the (optional) geometry shader stage |
static void GLUProgramAttachGeometryShader(GLU::ProgramRef pProgram) |
{ |
if(pProgram->m_Shaders.size() == 3) |
{ |
glAttachShader(pProgram->mnPID, pProgram->m_Shaders[2]); |
GLUProgramBindInputs(pProgram); |
} // if |
} // GLUProgramAttachGeometryShader |
// Create a program object and attach shaders |
static bool GLUProgramAttachShaders(GLU::ProgramRef pProgram) |
{ |
pProgram->mnPID = glCreateProgram(); |
if(pProgram->mnPID) |
{ |
// Attach the vertex shader |
glAttachShader(pProgram->mnPID, pProgram->m_Shaders[0]); |
// Attach the fragment shader |
glAttachShader(pProgram->mnPID, pProgram->m_Shaders[1]); |
// Attach the optional geometry shader |
GLUProgramAttachGeometryShader(pProgram); |
} // if |
return bool(pProgram->mnPID); |
} // GLUProgramAttachShaders |
#pragma mark - |
#pragma mark Private - Utilities - Linker |
// Get the program log |
static void GLUProgramGetInfoLog(GLU::ProgramRef pProgram) |
{ |
GLint nInfoLogLength = 0; |
glGetProgramiv(pProgram->mnPID, GL_INFO_LOG_LENGTH, &nInfoLogLength); |
if(nInfoLogLength) |
{ |
GLchar *pInfoLog = NULL; |
try |
{ |
pInfoLog = new GLchar[nInfoLogLength]; |
glGetProgramInfoLog(pProgram->mnPID, |
nInfoLogLength, |
&nInfoLogLength, |
pInfoLog); |
NSLog(@">> INFO: OpenGL Program - Link log:\n%s\n", pInfoLog); |
delete [] pInfoLog; |
} // try |
catch(std::bad_alloc& ba) |
{ |
NSLog(@">> ERROR: OpenGL Program - Failed allocating memory for program link info. log: \"%s\"", ba.what()); |
} // catch |
} // if |
} // GLUProgramGetInfoLog |
// Validate the program object |
static bool GLUProgramValidate(GLU::ProgramRef pProgram) |
{ |
GLint nIsLinked = 0; |
glGetProgramiv(pProgram->mnPID, GL_LINK_STATUS, &nIsLinked); |
if(!nIsLinked) |
{ |
NSLog(@">> WARNING: OpenGL Program - Deleted program object with id = %d", pProgram->mnPID); |
glDeleteProgram(pProgram->mnPID); |
pProgram->mnPID = 0; |
} // if |
return nIsLinked != 0; |
} // GLUProgramValidate |
// Bind generic vertex attribute locations |
static bool GLUProgramBindAttributes(GLU::ProgramRef pProgram) |
{ |
return GLUProgramBindLocations(pProgram->mnPID, |
pProgram->m_Attributes, |
glBindAttribLocation); |
} // GLUProgramBindAttributes |
// Bind fragment data locations |
static bool GLUProgramBindFragments(GLU::ProgramRef pProgram) |
{ |
return GLUProgramBindLocations(pProgram->mnPID, |
pProgram->m_Fragments, |
glBindFragDataLocation); |
} // GLUProgramBindFragments |
// Create a program object from shaders (that may include an optional geometry shader) |
static bool GLUProgramLink(GLU::ProgramRef pProgram) |
{ |
// Create the program object |
bool bSuccess = GLUProgramAttachShaders(pProgram); |
if(bSuccess) |
{ |
// Bind attribute locations |
GLUProgramBindAttributes(pProgram); |
// Bind fragment data locations |
GLUProgramBindFragments(pProgram); |
// Link to the program object |
glLinkProgram(pProgram->mnPID); |
// Get the program log |
GLUProgramGetInfoLog(pProgram); |
// Validate the program object |
bSuccess = GLUProgramValidate(pProgram); |
} // if |
return bSuccess; |
} // GLUProgramLink |
// Compile and link shaders to acquire a program object |
static bool GLUProgramFinalize(GLU::ProgramRef pProgram) |
{ |
bool bSuccess = GLUProgramAcquireShaders(pProgram); |
if(bSuccess) |
{ |
bSuccess = GLUProgramLink(pProgram); |
} // if |
return bSuccess; |
} // GLUProgramFinalize |
// Use a compiled and linked program object |
static bool GLUProgramBind(GLU::ProgramRef pProgram) |
{ |
glUseProgram(pProgram->mnPID); |
return bool(pProgram->mnPID); |
} // GLUProgramBind |
#pragma mark - |
#pragma mark Private - Utilities - Copy |
static bool GLUProgramCopy(const GLU::ProgramRef pProgramSrc, |
GLU::ProgramRef pProgramDst) |
{ |
// Copy shader sources |
pProgramDst->m_Sources = pProgramSrc->m_Sources; |
// Copy fragment locations |
pProgramDst->m_Fragments = pProgramSrc->m_Fragments; |
// Copy attribute locations |
pProgramDst->m_Attributes = pProgramSrc->m_Attributes; |
// Copy geometry shader inputs |
pProgramDst->m_Inputs = pProgramSrc->m_Inputs; |
bool bSuccess = GLUProgramFinalize(pProgramDst); |
// Compile link and acquire a program object |
if(!bSuccess) |
{ |
GLUProgramClearInputs(pProgramDst); |
GLUProgramClearLocations(pProgramDst); |
GLUProgramClearSources(pProgramDst); |
} // if |
return bSuccess; |
} // GLUProgramCopy |
#pragma mark - |
#pragma mark Private - Utilities - Constructors |
// Compile vertex and fragment shaders, with/without optional |
// geometry shader |
static GLU::ProgramRef GLUProgramCreate(const GLU::String &rVertex, |
const GLU::String &rFragment, |
const GLU::String &rGeometry) |
{ |
GLU::ProgramRef pProgram = nullptr; |
try |
{ |
pProgram = new GLU::Program; |
if(!GLUProgramAcquireShaderSources(rVertex, rFragment, rGeometry, pProgram)) |
{ |
throw @"OpenGL Program - Failed acquiring shader sources!"; |
} // if |
} // try |
catch(std::bad_alloc& ba) |
{ |
NSLog(@">> ERROR: OpenGL Program - Failed creating program object backing-store: \"%s\"", ba.what()); |
} // catch |
catch(NSString *pString) |
{ |
GLUProgramDelete(pProgram); |
NSLog(@">> ERROR: %@", pString); |
} // catch |
return pProgram; |
} // GLUProgramCreate |
// Compile vertex and fragment shaders, with/without optional |
// geometry shader |
static GLU::ProgramRef GLUProgramCreate(CFStringRef pVertex, |
CFStringRef pFragment, |
CFStringRef pGeometry) |
{ |
GLU::ProgramRef pProgram = nullptr; |
try |
{ |
pProgram = new GLU::Program; |
if(!GLUProgramAcquireShaderSources(pVertex, pFragment, pGeometry, pProgram)) |
{ |
throw @"OpenGL Program - Failed acquiring shader sources!"; |
} // if |
} // try |
catch(std::bad_alloc& ba) |
{ |
NSLog(@">> ERROR: OpenGL Program - Failed creating program object backing-store: \"%s\"", ba.what()); |
} // catch |
catch(NSString *pString) |
{ |
GLUProgramDelete(pProgram); |
NSLog(@">> ERROR: %@", pString); |
} // catch |
return pProgram; |
} // GLUProgramCreate |
// Compile vertex and fragment shaders, with/without optional geometry shader |
// geometry shader at a pathname |
static GLU::ProgramRef GLUProgramCreateAtPath(const GLU::String &rVertex, |
const GLU::String &rFragment, |
const GLU::String &rGeometry) |
{ |
GLU::ProgramRef pProgram = nullptr; |
CF::IFStreamRef vertex = CF::IFStreamCreate(rVertex); |
CF::IFStreamRef fragment = CF::IFStreamCreate(rFragment); |
if((vertex != nullptr) && (fragment != nullptr)) |
{ |
CF::IFStreamRef geometry = CF::IFStreamCreate(rGeometry); |
pProgram = GLU::ProgramCreate(CF::IFStreamGetBuffer(vertex), |
CF::IFStreamGetBuffer(fragment), |
CF::IFStreamGetBuffer(geometry)); |
CF::IFStreamDelete(vertex); |
CF::IFStreamDelete(fragment); |
CF::IFStreamDelete(geometry); |
} // if |
return pProgram; |
} // GLUProgramsCreateAtPath |
// Compile vertex and fragment shaders, with/without optional geometry shader |
// geometry shader at a pathname |
static GLU::ProgramRef GLUProgramCreateAtPath(CFStringRef pVertex, |
CFStringRef pFragment, |
CFStringRef pGeometry) |
{ |
GLU::ProgramRef pProgram = nullptr; |
CF::IFStreamRef vertex = CF::IFStreamCreate(pVertex); |
CF::IFStreamRef fragment = CF::IFStreamCreate(pFragment); |
if((vertex != nullptr) && (fragment != nullptr)) |
{ |
CF::IFStreamRef geometry = CF::IFStreamCreate(pGeometry); |
pProgram = GLU::ProgramCreate(CF::IFStreamGetBuffer(vertex), |
CF::IFStreamGetBuffer(fragment), |
CF::IFStreamGetBuffer(geometry)); |
CF::IFStreamDelete(vertex); |
CF::IFStreamDelete(fragment); |
CF::IFStreamDelete(geometry); |
} // if |
return pProgram; |
} // GLUProgramsCreateAtPath |
#pragma mark - |
#pragma mark Public - Utilities - Constructors |
// Compile vertex and fragment shaders |
GLU::ProgramRef GLU::ProgramCreate(const bool& bUseAsPath, |
const GLU::String& rVertex, |
const GLU::String& rFragment) |
{ |
return (bUseAsPath) |
? GLUProgramCreateAtPath(rVertex, rFragment, "") |
: GLUProgramCreate(rVertex, rFragment, ""); |
} // ProgramCreate |
// Compile vertex and fragment shaders, with/without optional |
// geometry shader |
GLU::ProgramRef GLU::ProgramCreate(const bool& bUseAsPath, |
const GLU::String& rVertex, |
const GLU::String& rFragment, |
const GLU::String& rGeometry) |
{ |
return (bUseAsPath) |
? GLUProgramCreateAtPath(rVertex, rFragment, rGeometry) |
: GLUProgramCreate(rVertex, rFragment, rGeometry); |
} // ProgramCreate |
// Compile vertex and fragment shaders |
GLU::ProgramRef GLU::ProgramCreate(const bool& bUseAsPath, |
CFStringRef pVertex, |
CFStringRef pFragment) |
{ |
return (bUseAsPath) |
? GLUProgramCreateAtPath(pVertex, pFragment, nullptr) |
: GLUProgramCreate(pVertex, pFragment, nullptr); |
} // ProgramCreate |
// Compile vertex and fragment shaders, with/without optional |
// geometry shader |
GLU::ProgramRef GLU::ProgramCreate(const bool& bUseAsPath, |
CFStringRef pVertex, |
CFStringRef pFragment, |
CFStringRef pGeometry) |
{ |
return (bUseAsPath) |
? GLUProgramCreateAtPath(pVertex, pFragment, pGeometry) |
: GLUProgramCreate(pVertex, pFragment, pGeometry); |
} // ProgramCreate |
#pragma mark - |
#pragma mark Public - Utilities - Copy Constructor |
// Make a deep copy of the program object |
GLU::ProgramRef GLU::ProgramCreateCopy(GLU::ProgramRef pProgramSrc) |
{ |
GLU::ProgramRef pProgramDst = nullptr; |
if(pProgramSrc != nullptr) |
{ |
try |
{ |
pProgramDst = new GLU::Program; |
if(!GLUProgramCopy(pProgramSrc, pProgramDst)) |
{ |
throw @"OpenGL Program - Failed copying the source to destination program object!"; |
} // if |
} // try |
catch(std::bad_alloc& ba) |
{ |
NSLog(@">> ERROR: OpenGL Program - Failed creating program object copy backing-store: \"%s\"", ba.what()); |
} // catch |
catch(NSString *pString) |
{ |
GLUProgramDelete(pProgramDst); |
NSLog(@">> ERROR: %@", pString); |
} // catch |
} // if |
return pProgramDst; |
} // ProgramCreateCopy |
#pragma mark - |
#pragma mark Public - Utilities - Attributes |
// Delete all the program object and shaders |
void GLU::ProgramDelete(GLU::ProgramRef pProgram) |
{ |
if(pProgram != nullptr) |
{ |
GLUProgramDelete(pProgram); |
} // if |
} // GLUProgramDelete |
#pragma mark - |
#pragma mark Public - Utilities - Attributes |
bool GLU::ProgramAddAttributes(const GLU::UInts &rKeys, |
const GLU::Strings &rValues, |
GLU::ProgramRef pProgram) |
{ |
bool bSuccess = pProgram != nullptr; |
if(bSuccess) |
{ |
pProgram->m_Attributes = GLUProgramLocationsCreate(rKeys, rValues); |
bSuccess = pProgram->m_Attributes.size() == rKeys.size(); |
} // if |
return bSuccess; |
} // GLUProgramAddAttributes |
bool GLU::ProgramAddAttributes(CFArrayRef pKeys, |
CFArrayRef pValues, |
GLU::ProgramRef pProgram) |
{ |
bool bSuccess = pProgram != nullptr; |
if(bSuccess) |
{ |
pProgram->m_Attributes = GLUProgramLocationsCreate(pKeys, pValues); |
bSuccess = pProgram->m_Attributes.size() == ((pKeys) ? CFArrayGetCount(pKeys) : 0); |
} // if |
return bSuccess; |
} // GLUProgramAddAttributes |
bool GLU::ProgramAddAttributes(CFDictionaryRef pLocations, |
GLU::ProgramRef pProgram) |
{ |
bool bSuccess = pProgram != nullptr; |
if(bSuccess) |
{ |
pProgram->m_Attributes = GLUProgramLocationsCreate(pLocations); |
bSuccess = pProgram->m_Attributes.size() == ((pLocations) ? CFDictionaryGetCount(pLocations) : 0); |
} // if |
return bSuccess; |
} // GLUProgramAddAttributes |
#pragma mark - |
#pragma mark Public - Utilities - Fragments |
bool GLU::ProgramAddFragments(const UInts& rKeys, |
const Strings& rValues, |
ProgramRef pProgram) |
{ |
bool bSuccess = pProgram != nullptr; |
if(bSuccess) |
{ |
pProgram->m_Fragments = GLUProgramLocationsCreate(rKeys, rValues); |
bSuccess = pProgram->m_Fragments.size() == rKeys.size(); |
} // if |
return bSuccess; |
} // GLUProgramAddFragments |
bool GLU::ProgramAddFragments(CFArrayRef pKeys, |
CFArrayRef pValues, |
GLU::ProgramRef pProgram) |
{ |
bool bSuccess = pProgram != nullptr; |
if(bSuccess) |
{ |
pProgram->m_Fragments = GLUProgramLocationsCreate(pKeys, pValues); |
bSuccess = pProgram->m_Fragments.size() == ((pKeys) ? CFArrayGetCount(pKeys) : 0); |
} // if |
return bSuccess; |
} // GLUProgramAddFragments |
bool GLU::ProgramAddFragments(CFDictionaryRef pLocations, |
GLU::ProgramRef pProgram) |
{ |
bool bSuccess = pProgram != nullptr; |
if(bSuccess) |
{ |
pProgram->m_Fragments = GLUProgramLocationsCreate(pLocations); |
bSuccess = pProgram->m_Fragments.size() == ((pLocations) ? CFDictionaryGetCount(pLocations) : 0); |
} // if |
return bSuccess; |
} // GLUProgramAddFragments |
#pragma mark - |
#pragma mark Public - Utilities - Inputs |
// Add geometry shader inputs |
bool GLU::ProgramAddInputs(const GLenum& nInputType, |
const GLenum& nOutputType, |
const GLuint& nVerticesOut, |
GLU::ProgramRef pProgram) |
{ |
return (pProgram != nullptr) ? GLUProgramAddInputs(nInputType, nOutputType, nVerticesOut, pProgram) : false; |
} // ProgramAddInputs |
#pragma mark - |
#pragma mark Public - Utilities - Shaders |
// Get the id associated with the program object |
GLuint GLU::ProgramGetHandle(GLU::ProgramRef pProgram) |
{ |
return (pProgram != nullptr) ? pProgram->mnPID : 0; |
} // ProgramGetHandle |
// Compile and link shaders to acquire a program object |
bool GLU::ProgramFinalize(GLU::ProgramRef pProgram) |
{ |
return (pProgram != nullptr) ? GLUProgramFinalize(pProgram) : false; |
} // GLUProgramFinalize |
// Use a compiled and linked program object |
bool GLU::ProgramBind(GLU::ProgramRef pProgram) |
{ |
return (pProgram != nullptr) ? GLUProgramBind(pProgram) : false; |
} // GLUProgramBind |
Copyright © 2014 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2014-10-16