Kaydet (Commit) df290c63 authored tarafından Luboš Luňák's avatar Luboš Luňák

make it possible to easily have variants of glsl programs

Now it's possible to add a preamble to the compiled program, so there can
be just one program with #ifdef's inside and the small variants can be
selected using #define in the preamble instead of having several almost
identical programs.

Change-Id: I6c5112313b91b6269ebdecdfc896e0f96209ea2b
üst d3ac5c2d
...@@ -161,8 +161,6 @@ struct GLWindow ...@@ -161,8 +161,6 @@ struct GLWindow
~GLWindow(); ~GLWindow();
}; };
typedef std::pair<OUString, OUString> ProgramKey;
class VCLOPENGL_DLLPUBLIC OpenGLContext class VCLOPENGL_DLLPUBLIC OpenGLContext
{ {
public: public:
...@@ -203,8 +201,8 @@ public: ...@@ -203,8 +201,8 @@ public:
void ReleaseFramebuffers(); void ReleaseFramebuffers();
// retrieve a program from the cache or compile/link it // retrieve a program from the cache or compile/link it
OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
bool isCurrent(); bool isCurrent();
static void clearCurrent(); static void clearCurrent();
...@@ -266,6 +264,14 @@ private: ...@@ -266,6 +264,14 @@ private:
OpenGLFramebuffer* mpFirstFramebuffer; OpenGLFramebuffer* mpFirstFramebuffer;
OpenGLFramebuffer* mpLastFramebuffer; OpenGLFramebuffer* mpLastFramebuffer;
struct ProgramKey
{
ProgramKey( const OUString& vertexShader, const OUString& fragmentShader, const OString& preamble );
bool operator< ( const ProgramKey& other ) const;
OUString vertexShader;
OUString fragmentShader;
OString preamble;
};
boost::ptr_map<ProgramKey, OpenGLProgram> maPrograms; boost::ptr_map<ProgramKey, OpenGLProgram> maPrograms;
OpenGLProgram* mpCurrentProgram; OpenGLProgram* mpCurrentProgram;
#ifdef DBG_UTIL #ifdef DBG_UTIL
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
class VCLOPENGL_DLLPUBLIC OpenGLHelper class VCLOPENGL_DLLPUBLIC OpenGLHelper
{ {
public: public:
static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName); static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName, const OString& preamble = "" );
/** /**
* The caller is responsible for allocate the memory for the RGBA buffer, before call * The caller is responsible for allocate the memory for the RGBA buffer, before call
......
...@@ -43,7 +43,7 @@ public: ...@@ -43,7 +43,7 @@ public:
OpenGLProgram(); OpenGLProgram();
~OpenGLProgram(); ~OpenGLProgram();
bool Load( const OUString& rVertexShader, const OUString& rFragmentShader ); bool Load( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
bool Use(); bool Use();
bool Clean(); bool Clean();
......
...@@ -73,7 +73,7 @@ protected: ...@@ -73,7 +73,7 @@ protected:
bool CheckOffscreenTexture(); bool CheckOffscreenTexture();
public: public:
bool UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); bool UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
bool UseSolid( SalColor nColor, sal_uInt8 nTransparency ); bool UseSolid( SalColor nColor, sal_uInt8 nTransparency );
bool UseSolid( SalColor nColor, double fTransparency ); bool UseSolid( SalColor nColor, double fTransparency );
bool UseSolid( SalColor nColor ); bool UseSolid( SalColor nColor );
......
...@@ -373,11 +373,11 @@ bool OpenGLSalGraphicsImpl::CheckOffscreenTexture() ...@@ -373,11 +373,11 @@ bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
return true; return true;
} }
bool OpenGLSalGraphicsImpl::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ) bool OpenGLSalGraphicsImpl::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
{ {
if( mpProgram != NULL ) if( mpProgram != NULL )
mpProgram->Clean(); mpProgram->Clean();
mpProgram = mpContext->UseProgram( rVertexShader, rFragmentShader ); mpProgram = mpContext->UseProgram( rVertexShader, rFragmentShader, preamble );
#ifdef DBG_UTIL #ifdef DBG_UTIL
mProgramIsSolidColor = false; // UseSolid() will set to true if needed mProgramIsSolidColor = false; // UseSolid() will set to true if needed
#endif #endif
......
...@@ -31,9 +31,9 @@ OpenGLProgram::~OpenGLProgram() ...@@ -31,9 +31,9 @@ OpenGLProgram::~OpenGLProgram()
glDeleteProgram( mnId ); glDeleteProgram( mnId );
} }
bool OpenGLProgram::Load( const OUString& rVertexShader, const OUString& rFragmentShader ) bool OpenGLProgram::Load( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
{ {
mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader ); mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble );
return ( mnId != 0 ); return ( mnId != 0 );
} }
......
...@@ -1582,9 +1582,9 @@ void OpenGLContext::ReleaseFramebuffers() ...@@ -1582,9 +1582,9 @@ void OpenGLContext::ReleaseFramebuffers()
} }
} }
OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader ) OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
{ {
ProgramKey aKey( rVertexShader, rFragmentShader ); ProgramKey aKey( rVertexShader, rFragmentShader, preamble );
boost::ptr_map<ProgramKey, OpenGLProgram>::iterator boost::ptr_map<ProgramKey, OpenGLProgram>::iterator
it = maPrograms.find( aKey ); it = maPrograms.find( aKey );
...@@ -1592,7 +1592,7 @@ OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const O ...@@ -1592,7 +1592,7 @@ OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const O
return it->second; return it->second;
OpenGLProgram* pProgram = new OpenGLProgram; OpenGLProgram* pProgram = new OpenGLProgram;
if( !pProgram->Load( rVertexShader, rFragmentShader ) ) if( !pProgram->Load( rVertexShader, rFragmentShader, preamble ) )
{ {
delete pProgram; delete pProgram;
return NULL; return NULL;
...@@ -1602,9 +1602,9 @@ OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const O ...@@ -1602,9 +1602,9 @@ OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const O
return pProgram; return pProgram;
} }
OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ) OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
{ {
OpenGLProgram* pProgram = GetProgram( rVertexShader, rFragmentShader ); OpenGLProgram* pProgram = GetProgram( rVertexShader, rFragmentShader, preamble );
if( pProgram == mpCurrentProgram ) if( pProgram == mpCurrentProgram )
return pProgram; return pProgram;
...@@ -1615,4 +1615,20 @@ OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const O ...@@ -1615,4 +1615,20 @@ OpenGLProgram* OpenGLContext::UseProgram( const OUString& rVertexShader, const O
return mpCurrentProgram; return mpCurrentProgram;
} }
inline
OpenGLContext::ProgramKey::ProgramKey( const OUString& v, const OUString& f, const OString& p )
: vertexShader( v ), fragmentShader( f ), preamble( p )
{
}
inline
bool OpenGLContext::ProgramKey::operator< ( const ProgramKey& other ) const
{
if( vertexShader != other.vertexShader )
return vertexShader < other.vertexShader;
if( fragmentShader != other.fragmentShader )
return fragmentShader < other.fragmentShader;
return preamble < other.preamble;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -97,7 +97,7 @@ namespace { ...@@ -97,7 +97,7 @@ namespace {
} }
} }
GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString& rFragmentShaderName) GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString& rFragmentShaderName, const OString& preamble)
{ {
// Create the shaders // Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
...@@ -107,6 +107,8 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString ...@@ -107,6 +107,8 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString
// Compile Vertex Shader // Compile Vertex Shader
OString aVertexShaderSource = loadShader(rVertexShaderName); OString aVertexShaderSource = loadShader(rVertexShaderName);
if( !preamble.isEmpty())
aVertexShaderSource = preamble + "\n" + aVertexShaderSource;
char const * VertexSourcePointer = aVertexShaderSource.getStr(); char const * VertexSourcePointer = aVertexShaderSource.getStr();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL); glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID); glCompileShader(VertexShaderID);
...@@ -119,6 +121,8 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString ...@@ -119,6 +121,8 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString
// Compile Fragment Shader // Compile Fragment Shader
OString aFragmentShaderSource = loadShader(rFragmentShaderName); OString aFragmentShaderSource = loadShader(rFragmentShaderName);
if( !preamble.isEmpty())
aFragmentShaderSource = preamble + "\n" + aFragmentShaderSource;
char const * FragmentSourcePointer = aFragmentShaderSource.getStr(); char const * FragmentSourcePointer = aFragmentShaderSource.getStr();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL); glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID); glCompileShader(FragmentShaderID);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment