Files
glest-source/source/shared_lib/sources/graphics/md5/ArbProgram.cpp

263 lines
8.0 KiB
C++

// ==============================================================
// This file is part of MegaGlest (www.glest.org)
//
// ArbProgram.cpp -- Copyright (c) 2007 David Henry
// changed for use with MegaGlest: Copyright (C) 2011- by Mark Vejvoda
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// below is included in the resulting source code.
//
// Implementation of ARB program related classes.
//
/////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include "ArbProgram.h"
namespace Shared { namespace Graphics { namespace md5 {
using std::cout;
using std::cerr;
using std::endl;
/////////////////////////////////////////////////////////////////////////////
//
// Global ARB program related functions.
//
/////////////////////////////////////////////////////////////////////////////
static GLboolean ArbVpCapable = GL_FALSE;
static GLboolean ArbFpCapable = GL_FALSE;
// --------------------------------------------------------------------------
// hasArbVertexProgramSupport
// hasArbFragmentProgramSupport
//
// Return true if the host has ARB program support (vertex or fragment).
// --------------------------------------------------------------------------
GLboolean hasArbVertexProgramSupport () {
return ArbVpCapable;
}
GLboolean hasArbFragmentProgramSupport () {
return ArbFpCapable;
}
// --------------------------------------------------------------------------
// initArbProgramHandling
//
// Initialize variables and extensions needed for using ARB Programs.
// This function should be called before any shader usage (at application
// initialization for example).
// --------------------------------------------------------------------------
void initArbProgramHandling () {
// Check for extensions needed for ARB program support on host
ArbVpCapable = glewIsSupported ("GL_ARB_vertex_program");
ArbFpCapable = glewIsSupported ("GL_ARB_fragment_program");
if (!hasArbVertexProgramSupport ())
cerr << "* missing GL_ARB_vertex_program extension" << endl;
if (!hasArbFragmentProgramSupport ())
cerr << "* missing GL_ARB_fragment_program extension" << endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// class ArbProgram implementation.
//
/////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------
// ArbProgram::ArbProgram
//
// Constructor.
// --------------------------------------------------------------------------
ArbProgram::ArbProgram (const string &filename)
: _name (filename), _handle (0), _fail (true) {
}
// --------------------------------------------------------------------------
// ArbProgram::~ArbProgram
//
// Destructor. Destroy the program handle.
// --------------------------------------------------------------------------
ArbProgram::~ArbProgram () {
if (glIsProgramARB (_handle))
glDeleteProgramsARB (1, &_handle);
}
// -------------------------------------------------------------------------
// ArbProgram::use
// ArbProgram::unuse
//
// Bind/unbind the program.
// -------------------------------------------------------------------------
void ArbProgram::use () const {
const GLenum target = programType ();
glEnable (target);
glBindProgramARB (target, _handle);
}
void ArbProgram::unuse () const {
const GLenum target = programType ();
glBindProgramARB (target, 0);
glDisable (target);
}
// -------------------------------------------------------------------------
// ArbProgram::printProgramString
//
// Print the ARB program string until a given position. This is
// usefull for printing code until error position.
// -------------------------------------------------------------------------
void ArbProgram::printProgramString (int errPos) {
int i = 0;
cerr << endl << " > ";
for (i = 0; i < (errPos + 1) && _code[i]; i++) {
cerr.put (_code[i]);
if (_code[i] == '\n')
cerr << " > ";
}
cerr << " <---" << endl << endl;
}
// -------------------------------------------------------------------------
// ArbProgram::load
//
// Create and load the program.
// -------------------------------------------------------------------------
void ArbProgram::load () throw (std::runtime_error) {
const GLchar *code = _code.c_str ();
const GLenum target = programType ();
// Generate a program object handle
glGenProgramsARB (1, &_handle);
// Make the "current" program object progid
glBindProgramARB (target, _handle);
// Specify the program for the current object
glProgramStringARB (target, GL_PROGRAM_FORMAT_ASCII_ARB,
_code.size (), code);
// Check for errors and warnings...
if (GL_INVALID_OPERATION == glGetError ()) {
const GLubyte *errString;
GLint errPos;
// Find the error position
glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
// Print implementation-dependent program
// errors and warnings string
errString = glGetString (GL_PROGRAM_ERROR_STRING_ARB);
cerr << "Error in " << ((GL_VERTEX_PROGRAM_ARB == target) ?
"vertex" : "fragment");
cerr << " program at position: " << errPos << endl << errString;
printProgramString (errPos);
_fail = true;
throw std::runtime_error ("Compilation failed");
}
}
// -------------------------------------------------------------------------
// ArbProgram::loadProgramFile
//
// Load program's code from file. The code is stored into the
// _code string member variable.
// -------------------------------------------------------------------------
void ArbProgram::loadProgramFile (const string &filename) throw (std::runtime_error) {
// Open the file
std::ifstream ifs (filename.c_str (), std::ios::in | std::ios::binary);
if (ifs.fail ())
throw std::runtime_error ("Couldn't open prog file: " + filename);
// Read whole file into string
_code.assign (std::istreambuf_iterator<char>(ifs),
std::istreambuf_iterator<char>());
// Close file
ifs.close ();
}
/////////////////////////////////////////////////////////////////////////////
//
// class ArbVertexProgram implementation.
//
/////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------
// ArbVertexProgram::ArbVertexProgram
//
// Constructor. Read vertex program code from file and load it.
// --------------------------------------------------------------------------
ArbVertexProgram::ArbVertexProgram (const string &filename) : ArbProgram (filename) {
try {
// Load program code from file
loadProgramFile (filename);
// load the program from code buffer
load ();
cout << "* Vertex program \"" << _name << "\" loaded" << endl;
}
catch (std::runtime_error &err) {
cerr << "Error: Faild to create vertex program from " << _name;
cerr << endl << "Reason: " << err.what () << endl;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// class ArbFragmentProgram implementation.
//
/////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------
// ArbFragmentProgram::ArbFragmentProgram
//
// Constructor. Read fragment program code from file and load it.
// --------------------------------------------------------------------------
ArbFragmentProgram::ArbFragmentProgram (const string &filename) : ArbProgram (filename) {
try {
// Load program code from file
loadProgramFile (filename);
// load the program from code buffer
load ();
cout << "* Fragment program \"" << _name << "\" loaded" << endl;
}
catch (std::runtime_error &err) {
cerr << "Error: Faild to create fragment program from " << _name;
cerr << endl << "Reason: " << err.what () << endl;
}
}
}}} //end namespace