зеркало из https://github.com/mozilla/gecko-dev.git
Bug 716439; compile OGL shaders lazily. r=BenWa
This commit is contained in:
Родитель
b4264df38c
Коммит
79a33df6e6
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче