diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 687c4add404..f6006e0ee91 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -153,7 +153,7 @@ WebGLContext::WebGLContext() mContextStatus = ContextStable; mContextLostErrorSet = false; - mAlreadyReportedMessages = 0; + mAlreadyGeneratedWarnings = 0; } WebGLContext::~WebGLContext() diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 8476234b9f1..055221c8988 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -809,11 +809,13 @@ public: WebGLenum pname, ErrorResult& rv); JS::Value GetProgramParameter(WebGLProgram *prog, WebGLenum pname); + void GetProgramInfoLog(WebGLProgram *prog, nsACString& retval, ErrorResult& rv); void GetProgramInfoLog(WebGLProgram *prog, nsAString& retval, ErrorResult& rv); JS::Value GetRenderbufferParameter(WebGLenum target, WebGLenum pname); JS::Value GetShaderParameter(WebGLShader *shader, WebGLenum pname); already_AddRefed GetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precisiontype); + void GetShaderInfoLog(WebGLShader *shader, nsACString& retval, ErrorResult& rv); void GetShaderInfoLog(WebGLShader *shader, nsAString& retval, ErrorResult& rv); void GetShaderSource(WebGLShader *shader, nsAString& retval); JS::Value GetTexParameter(WebGLenum target, WebGLenum pname); @@ -1362,7 +1364,11 @@ protected: ContextStatus mContextStatus; bool mContextLostErrorSet; - int mAlreadyReportedMessages; + int mAlreadyGeneratedWarnings; + + bool ShouldGenerateWarnings() const { + return mAlreadyGeneratedWarnings < 32; + } #ifdef XP_MACOSX // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 6c46332b64e..c551e2981c5 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2993,6 +2993,15 @@ WebGLContext::GetProgramInfoLog(nsIWebGLProgram *pobj, nsAString& retval) void WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsAString& retval, ErrorResult& rv) +{ + nsCAutoString s; + GetProgramInfoLog(prog, s, rv); + CopyASCIItoUTF16(s, retval); +} + +void +WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsACString& retval, + ErrorResult& rv) { if (!IsContextStable()) { @@ -3022,14 +3031,9 @@ WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsAString& retval, return; } - nsCAutoString log; - log.SetCapacity(k); - - gl->fGetProgramInfoLog(progname, k, &k, (char*) log.BeginWriting()); - - log.SetLength(k); - - CopyASCIItoUTF16(log, retval); + retval.SetCapacity(k); + gl->fGetProgramInfoLog(progname, k, &k, (char*) retval.BeginWriting()); + retval.SetLength(k); } // here we have to support all pnames with both int and float params. @@ -3685,6 +3689,8 @@ WebGLContext::LinkProgram(WebGLProgram *program, ErrorResult& rv) } if (!program->HasBothShaderTypesAttached()) { + GenerateWarning("linkProgram: this program doesn't have both a vertex shader" + " and a fragment shader"); program->SetLinkStatus(false); return; } @@ -3699,6 +3705,53 @@ WebGLContext::LinkProgram(WebGLProgram *program, ErrorResult& rv) program->SetLinkStatus(updateInfoSucceeded); } else { program->SetLinkStatus(false); + + if (ShouldGenerateWarnings()) { + + // report shader/program infoLogs as warnings. + // note that shader compilation errors can be deferred to linkProgram, + // which is why we can't do anything in compileShader. In practice we could + // report in compileShader the translation errors generated by ANGLE, + // but it seems saner to keep a single way of obtaining shader infologs. + + ErrorResult rv; + nsCAutoString log; + + bool alreadyReportedShaderInfoLog = false; + + for (size_t i = 0; i < program->AttachedShaders().Length(); i++) { + + WebGLShader* shader = program->AttachedShaders()[i]; + GetShaderInfoLog(shader, log, rv); + if (rv.Failed() || log.IsEmpty()) + continue; + + const char *shaderTypeName = nsnull; + if (shader->ShaderType() == LOCAL_GL_VERTEX_SHADER) { + shaderTypeName = "vertex"; + } else if (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) { + shaderTypeName = "fragment"; + } else { + // should have been validated earlier + NS_ABORT(); + shaderTypeName = ""; + } + + GenerateWarning("linkProgram: a %s shader used in this program failed to " + "compile, with this log:\n%s\n", + shaderTypeName, + log.get()); + alreadyReportedShaderInfoLog = true; + } + + if (!alreadyReportedShaderInfoLog) { + GetProgramInfoLog(program, log, rv); + if (!(rv.Failed() || log.IsEmpty())) { + GenerateWarning("linkProgram failed, with this log:\n%s\n", + log.get()); + } + } + } } } @@ -5232,6 +5285,15 @@ WebGLContext::GetShaderInfoLog(nsIWebGLShader *sobj, nsAString& retval) void WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsAString& retval, ErrorResult& rv) +{ + nsCAutoString s; + GetShaderInfoLog(shader, s, rv); + CopyASCIItoUTF16(s, retval); +} + +void +WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsACString& retval, + ErrorResult& rv) { if (!IsContextStable()) { @@ -5242,9 +5304,8 @@ WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsAString& retval, if (!ValidateObject("getShaderInfoLog: shader", shader)) return; - const nsCString& tlog = shader->TranslationLog(); - if (!tlog.IsVoid()) { - CopyASCIItoUTF16(tlog, retval); + retval = shader->TranslationLog(); + if (!retval.IsVoid()) { return; } @@ -5262,14 +5323,9 @@ WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsAString& retval, return; } - nsCAutoString log; - log.SetCapacity(k); - - gl->fGetShaderInfoLog(shadername, k, &k, (char*) log.BeginWriting()); - - log.SetLength(k); - - CopyASCIItoUTF16(log, retval); + retval.SetCapacity(k); + gl->fGetShaderInfoLog(shadername, k, &k, (char*) retval.BeginWriting()); + retval.SetLength(k); } NS_IMETHODIMP diff --git a/content/canvas/src/WebGLContextUtils.cpp b/content/canvas/src/WebGLContextUtils.cpp index 4dd5ba339fa..de6a15ee073 100644 --- a/content/canvas/src/WebGLContextUtils.cpp +++ b/content/canvas/src/WebGLContextUtils.cpp @@ -45,12 +45,10 @@ WebGLContext::GenerateWarning(const char *fmt, ...) void WebGLContext::GenerateWarning(const char *fmt, va_list ap) { - const int MaxReportedMessages = 32; - - if (mAlreadyReportedMessages >= MaxReportedMessages) + if (!ShouldGenerateWarnings()) return; - mAlreadyReportedMessages++; + mAlreadyGeneratedWarnings++; char buf[1024]; PR_vsnprintf(buf, 1024, fmt, ap); @@ -61,10 +59,10 @@ WebGLContext::GenerateWarning(const char *fmt, va_list ap) JSContext* ccx = nsnull; if (stack && NS_SUCCEEDED(stack->Peek(&ccx)) && ccx) { JS_ReportWarning(ccx, "WebGL: %s", buf); - if (mAlreadyReportedMessages == MaxReportedMessages) { + if (!ShouldGenerateWarnings()) { JS_ReportWarning(ccx, - "WebGL: no further warnings will be reported for this WebGL context " - "(already reported %d warnings)", mAlreadyReportedMessages); + "WebGL: No further warnings will be reported for this WebGL context " + "(already reported %d warnings)", mAlreadyGeneratedWarnings); } } } diff --git a/content/canvas/src/WebGLContextValidate.cpp b/content/canvas/src/WebGLContextValidate.cpp index a762f50d10d..8fc12f8265f 100644 --- a/content/canvas/src/WebGLContextValidate.cpp +++ b/content/canvas/src/WebGLContextValidate.cpp @@ -54,7 +54,7 @@ WebGLProgram::UpdateInfo() if (loc < mContext->mGLMaxVertexAttribs) { mAttribsInUse[loc] = true; } else { - mContext->ErrorInvalidOperation("program exceeds MAX_VERTEX_ATTRIBS"); + mContext->GenerateWarning("program exceeds MAX_VERTEX_ATTRIBS"); return false; } }