From c228ddb5ecf2d27752fc7144cb0884a396608548 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 5 Jan 2011 13:08:53 -0800 Subject: [PATCH] b=621986; fix webgl is-object test; r=bjacob --- content/canvas/src/WebGLContext.h | 43 ++++++++++++++--- content/canvas/src/WebGLContextGL.cpp | 67 +++++++++++++++++++++------ 2 files changed, 90 insertions(+), 20 deletions(-) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 8c283b644c7..32332e6f23b 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -510,7 +510,10 @@ protected: WebGLObjectRefPtr mBoundArrayBuffer; WebGLObjectRefPtr mBoundElementArrayBuffer; - WebGLObjectRefPtr mCurrentProgram; + // note nsRefPtr -- this stays alive even after being deleted, + // and is only explicitly removed from the current state via + // a call to UseProgram. + nsRefPtr mCurrentProgram; PRUint32 mMaxFramebufferColorAttachments; @@ -1145,7 +1148,7 @@ public: WebGLShader(WebGLContext *context, WebGLuint name, WebGLenum stype) : WebGLContextBoundObject(context), mName(name), mDeleted(PR_FALSE), mType(stype), - mNeedsTranslation(true) + mNeedsTranslation(true), mAttachCount(0) { } void Delete() { @@ -1155,10 +1158,14 @@ public: mDeleted = PR_TRUE; } - PRBool Deleted() { return mDeleted; } + PRBool Deleted() { return mDeleted && mAttachCount == 0; } WebGLuint GLName() { return mName; } WebGLenum ShaderType() { return mType; } + PRUint32 AttachCount() { return mAttachCount; } + void IncrementAttachCount() { mAttachCount++; } + void DecrementAttachCount() { mAttachCount--; } + void SetSource(const nsCString& src) { // XXX do some quick gzip here maybe -- getting this will be very rare mSource.Assign(src); @@ -1189,6 +1196,7 @@ protected: nsCString mSource; nsCString mTranslationLog; bool mNeedsTranslation; + PRUint32 mAttachCount; }; NS_DEFINE_STATIC_IID_ACCESSOR(WebGLShader, WEBGLSHADER_PRIVATE_IID) @@ -1205,7 +1213,8 @@ public: WebGLProgram(WebGLContext *context, WebGLuint name) : WebGLContextBoundObject(context), - mName(name), mDeleted(PR_FALSE), mLinkStatus(PR_FALSE), mGeneration(0), + mName(name), mDeleted(PR_FALSE), mDeletePending(PR_FALSE), + mLinkStatus(PR_FALSE), mGeneration(0), mUniformMaxNameLength(0), mAttribMaxNameLength(0), mUniformCount(0), mAttribCount(0) { @@ -1219,7 +1228,18 @@ public: mDeleted = PR_TRUE; } - PRBool Deleted() { return mDeleted; } + void DetachShaders() { + for (PRUint32 i = 0; i < mAttachedShaders.Length(); ++i) { + mAttachedShaders[i]->DecrementAttachCount(); + } + mAttachedShaders.Clear(); + } + + PRBool Deleted() { return mDeleted && !mDeletePending; } + void SetDeletePending() { mDeletePending = PR_TRUE; } + void ClearDeletePending() { mDeletePending = PR_FALSE; } + PRBool HasDeletePending() { return mDeletePending; } + WebGLuint GLName() { return mName; } const nsTArray& AttachedShaders() const { return mAttachedShaders; } PRBool LinkStatus() { return mLinkStatus; } @@ -1235,12 +1255,17 @@ public: if (ContainsShader(shader)) return PR_FALSE; mAttachedShaders.AppendElement(shader); + shader->IncrementAttachCount(); return PR_TRUE; } // return true if the shader was found and removed PRBool DetachShader(WebGLShader *shader) { - return mAttachedShaders.RemoveElement(shader); + if (mAttachedShaders.RemoveElement(shader)) { + shader->DecrementAttachCount(); + return PR_TRUE; + } + return PR_FALSE; } PRBool HasAttachedShaderOfType(GLenum shaderType) { @@ -1285,10 +1310,14 @@ public: protected: WebGLuint mName; PRPackedBool mDeleted; + PRPackedBool mDeletePending; PRPackedBool mLinkStatus; + // attached shaders of the program object nsTArray mAttachedShaders; - nsRefPtrHashtable mMapUniformLocations; CheckedUint32 mGeneration; + + // post-link data + nsRefPtrHashtable mMapUniformLocations; GLint mUniformMaxNameLength; GLint mAttribMaxNameLength; GLint mUniformCount; diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 27f9392611c..cc6bfecdcfc 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -169,6 +169,8 @@ WebGLContext::AttachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj) gl->fAttachShader(progname, shadername); + printf_stderr("AttachShader: %p AttachCount after attach %d\n", shader, shader->AttachCount()); + return NS_OK; } @@ -869,6 +871,13 @@ WebGLContext::DeleteProgram(nsIWebGLProgram *pobj) MakeContextCurrent(); gl->fDeleteProgram(progname); + + if (prog == mCurrentProgram) { + prog->SetDeletePending(); + } else { + prog->DetachShaders(); + } + prog->Delete(); mMapPrograms.Remove(progname); @@ -890,6 +899,7 @@ WebGLContext::DeleteShader(nsIWebGLShader *sobj) MakeContextCurrent(); gl->fDeleteShader(shadername); + printf_stderr("DeleteShader: shader %p AttachCount in delete %d\n", shader, shader->AttachCount()); shader->Delete(); mMapShaders.Remove(shadername); @@ -902,10 +912,13 @@ WebGLContext::DetachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj) WebGLuint progname, shadername; WebGLProgram *program; WebGLShader *shader; + PRBool shaderDeleted; if (!GetConcreteObjectAndGLName("detachShader: program", pobj, &program, &progname) || - !GetConcreteObjectAndGLName("detachShader: shader", shobj, &shader, &shadername)) + !GetConcreteObjectAndGLName("detachShader: shader", shobj, &shader, &shadername, nsnull, &shaderDeleted)) return NS_OK; + // shaderDeleted is ignored -- it's valid to attempt to detach a + // deleted shader, since it's still a shader if (!program->DetachShader(shader)) return ErrorInvalidOperation("DetachShader: shader is not attached"); @@ -1426,7 +1439,7 @@ WebGLContext::GetAttachedShaders(nsIWebGLProgram *pobj, nsIVariant **retval) MakeContextCurrent(); if (isNull) { - wrval->SetAsVoid(); + wrval->SetAsEmpty(); // note no return, we still want to return the variant ErrorInvalidValue("getAttachedShaders: invalid program"); } else if (prog->AttachedShaders().Length() == 0) { @@ -1956,7 +1969,8 @@ WebGLContext::GetProgramParameter(nsIWebGLProgram *pobj, PRUint32 pname, nsIVari *retval = nsnull; WebGLuint progname; - if (!GetGLName("getProgramParameter: program", pobj, &progname)) + PRBool isDeleted; + if (!GetGLName("getProgramParameter: program", pobj, &progname, nsnull, &isDeleted)) return NS_OK; nsCOMPtr wrval = do_CreateInstance("@mozilla.org/variant;1"); @@ -2430,7 +2444,18 @@ NS_IMETHODIMP WebGLContext::IsProgram(nsIWebGLProgram *pobj, WebGLboolean *retval) { PRBool isDeleted; - *retval = CanGetConcreteObject("isProgram", pobj, 0, &isDeleted) && !isDeleted; + WebGLProgram *prog = nsnull; + PRBool ok = GetConcreteObject("isProgram", pobj, &prog, 0, &isDeleted, PR_FALSE); + if (!ok) { + *retval = PR_FALSE; + return NS_OK; + } + + if (isDeleted) { + *retval = PR_FALSE; + } else { + *retval = PR_TRUE; + } return NS_OK; } @@ -2454,7 +2479,18 @@ NS_IMETHODIMP WebGLContext::IsShader(nsIWebGLShader *sobj, WebGLboolean *retval) { PRBool isDeleted; - *retval = CanGetConcreteObject("isShader", sobj, 0, &isDeleted) && !isDeleted; + WebGLShader *shader = nsnull; + PRBool ok = GetConcreteObject("isShader", sobj, &shader, 0, &isDeleted, PR_FALSE); + if (!ok) { + *retval = PR_FALSE; + return NS_OK; + } + + if (isDeleted) { + *retval = PR_FALSE; + } else { + *retval = PR_TRUE; + } return NS_OK; } @@ -3332,16 +3368,18 @@ WebGLContext::UseProgram(nsIWebGLProgram *pobj) MakeContextCurrent(); - if (isNull) { - gl->fUseProgram(0); - mCurrentProgram = nsnull; - } else { - if (!prog->LinkStatus()) - return ErrorInvalidOperation("UseProgram: program was not linked successfully"); - gl->fUseProgram(progname); - mCurrentProgram = prog; + if (prog && !prog->LinkStatus()) + return ErrorInvalidOperation("UseProgram: program was not linked successfully"); + + gl->fUseProgram(progname); + + if (mCurrentProgram && mCurrentProgram->HasDeletePending()) { + mCurrentProgram->DetachShaders(); + mCurrentProgram->ClearDeletePending(); } + mCurrentProgram = prog; + return NS_OK; } @@ -3419,6 +3457,9 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj) WebGLuint shadername; if (!GetConcreteObjectAndGLName("compileShader", sobj, &shader, &shadername)) return NS_OK; + + printf_stderr("CompileShader: shader %p AttachCount %d\n", shader, shader->AttachCount()); + MakeContextCurrent(); #if defined(USE_ANGLE)