Bug 716439; compile OGL shaders lazily. r=BenWa

This commit is contained in:
Nicholas Cameron 2012-05-02 14:54:40 +12:00
Родитель b4264df38c
Коммит 79a33df6e6
4 изменённых файлов: 60 добавлений и 37 удалений

Просмотреть файл

@ -182,25 +182,17 @@ LayerManagerOGL::CreateContext()
return context.forget();
}
bool
LayerManagerOGL::InitAndAddPrograms(ShaderProgramType aType)
void
LayerManagerOGL::AddPrograms(ShaderProgramType aType)
{
for (PRUint32 maskType = MaskNone; maskType < NumMaskTypes; ++maskType) {
if (ProgramProfileOGL::ProgramExists(aType, static_cast<MaskType>(maskType))) {
ShaderProgramOGL* p = new ShaderProgramOGL(this->gl(),
mPrograms[aType].mVariations[maskType] = new ShaderProgramOGL(this->gl(),
ProgramProfileOGL::GetProfileFor(aType, static_cast<MaskType>(maskType)));
if (!p->Initialize()) {
delete p;
mPrograms[aType].mVariations[maskType] = nsnull;
return false;
}
mPrograms[aType].mVariations[maskType] = p;
} else {
mPrograms[aType].mVariations[maskType] = nsnull;
}
}
return true;
}
bool
@ -227,13 +219,17 @@ LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext, bool force)
LOCAL_GL_ONE, LOCAL_GL_ONE);
mGLContext->fEnable(LOCAL_GL_BLEND);
// we must initialise shaders in order
mPrograms.AppendElements(NumProgramTypes);
for (int type = 0; type < NumProgramTypes; ++type) {
if (!InitAndAddPrograms(static_cast<ShaderProgramType>(type)))
return false;
AddPrograms(static_cast<ShaderProgramType>(type));
}
// initialise a common shader to check that we can actually compile a shader
if (!mPrograms[gl::RGBALayerProgramType].mVariations[MaskNone]->Initialize()) {
return false;
}
mGLContext->fGenFramebuffers(1, &mBackBufferFBO);
if (mGLContext->WorkAroundDriverBugs()) {
@ -678,6 +674,7 @@ LayerManagerOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
GLenum aWrapMode /* = LOCAL_GL_REPEAT */,
bool aFlipped /* = false */)
{
NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
GLuint vertAttribIndex =
aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
GLuint texCoordAttribIndex =

Просмотреть файл

@ -331,6 +331,7 @@ public:
void BindAndDrawQuad(ShaderProgramOGL *aProg,
bool aFlipped = false)
{
NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
BindAndDrawQuad(aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib),
aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib),
aFlipped);
@ -447,22 +448,14 @@ private:
/**
* Updates all layer programs with a new projection matrix.
*
* XXX we need a way to be able to delay setting this until
* the program is actually used. Maybe a DelayedSetUniform
* on Program, that will delay the set until the next Activate?
*
* XXX this is only called once per frame, so it's not awful.
* If we have any more similar updates, then we should delay.
*/
void SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix);
/**
* Helper method for Initialize, creates all valid variations of a program,
* initialises them, and adds them to mPrograms
* returns false if any initialisation fails
* Helper method for Initialize, creates all valid variations of a program
* and adds them to mPrograms
*/
bool InitAndAddPrograms(gl::ShaderProgramType aType);
void AddPrograms(gl::ShaderProgramType aType);
/* Thebes layer callbacks; valid at the end of a transaciton,
* while rendering */

Просмотреть файл

@ -198,11 +198,16 @@ const char* const ShaderProgramOGL::TexCoordAttrib = "aTexCoord";
bool
ShaderProgramOGL::Initialize()
{
NS_ASSERTION(mProgramState == STATE_NEW, "Shader program has already been initialised");
if (!CreateProgram(mProfile.mVertexShaderString,
mProfile.mFragmentShaderString)) {
mProgramState = STATE_ERROR;
return false;
}
mProgramState = STATE_OK;
for (PRUint32 i = 0; i < mProfile.mUniforms.Length(); ++i) {
mProfile.mUniforms[i].mLocation =
mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mName);
@ -322,15 +327,6 @@ ShaderProgramOGL::CreateProgram(const char *aVertexShaderString,
mProgram = result;
return true;
}
void
ShaderProgramOGL::CheckAndSetProjectionMatrix(const gfx3DMatrix& aMatrix)
{
if (mProfile.mHasMatrixProj) {
Activate();
SetProjectionMatrix(aMatrix);
}
}
bool
ShaderProgramOGL::LoadMask(Layer* aMaskLayer)

Просмотреть файл

@ -170,10 +170,15 @@ public:
typedef mozilla::gl::GLContext GLContext;
ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile) :
mGL(aGL), mProgram(-1), mProfile(aProfile) { }
mGL(aGL), mProgram(0), mProgramState(STATE_NEW),
mIsProjectionMatrixStale(false), mProfile(aProfile) { }
~ShaderProgramOGL() {
if (mProgram <= 0) {
return;
}
nsRefPtr<GLContext> ctx = mGL->GetSharedContext();
if (!ctx) {
ctx = mGL;
@ -182,12 +187,27 @@ public:
ctx->fDeleteProgram(mProgram);
}
bool HasInitialized() {
NS_ASSERTION(mProgramState != STATE_OK || mProgram > 0, "Inconsistent program state");
return mProgramState == STATE_OK;
}
void Activate() {
NS_ASSERTION(mProgram != 0, "Attempting to activate a program that's not in use!");
if (mProgramState == STATE_NEW) {
if (!Initialize()) {
NS_WARNING("Shader could not be initialised");
return;
}
}
NS_ASSERTION(HasInitialized(), "Attempting to activate a program that's not in use!");
mGL->fUseProgram(mProgram);
#if CHECK_CURRENT_PROGRAM
mGL->SetUserData(&sCurrentProgramKey, this);
#endif
// check and set the projection matrix
if (mIsProjectionMatrixStale) {
SetProjectionMatrix(mProjectionMatrix);
}
}
bool Initialize();
@ -244,10 +264,17 @@ public:
}
// activates this program and sets its projection matrix, if the program uses one
void CheckAndSetProjectionMatrix(const gfx3DMatrix& aMatrix);
void CheckAndSetProjectionMatrix(const gfx3DMatrix& aMatrix)
{
if (mProfile.mHasMatrixProj) {
mIsProjectionMatrixStale = true;
mProjectionMatrix = aMatrix;
}
}
void SetProjectionMatrix(const gfx3DMatrix& aMatrix) {
SetMatrixUniform(mProfile.LookupUniformLocation("uMatrixProj"), aMatrix);
mIsProjectionMatrixStale = false;
}
void SetRenderOffset(const nsIntPoint& aOffset) {
@ -307,9 +334,19 @@ public:
static const char* const TexCoordAttrib;
protected:
gfx3DMatrix mProjectionMatrix;
// true if the projection matrix needs setting
bool mIsProjectionMatrixStale;
nsRefPtr<GLContext> mGL;
// the OpenGL id of the program
GLuint mProgram;
ProgramProfileOGL mProfile;
enum {
STATE_NEW,
STATE_OK,
STATE_ERROR
} mProgramState;
GLint mTexCoordMultiplierUniformLocation;
#ifdef CHECK_CURRENT_PROGRAM