b=571172; import and use ANGLE GLSL ES shader validator (disabled by default for now); r=joe
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 14 Jul 2010 20:52:34 -0700
changeset 47653 0895c4370e7ac3d485999e16b4cb6811e0642844
parent 47652 8d003a6c5cb88631a371a1de84b06c18be1d480e
child 47654 42029b6d627ee8c0d5face9cafa2bf7fe8950305
push idunknown
push userunknown
push dateunknown
reviewersjoe
bugs571172
milestone2.0b2pre
b=571172; import and use ANGLE GLSL ES shader validator (disabled by default for now); r=joe
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextValidate.cpp
gfx/Makefile.in
gfx/angle/Makefile.in
gfx/angle/README.mozilla
gfx/angle/angle-nspr.patch
gfx/angle/include/GLSLANG/ShaderLang.h
gfx/angle/src/compiler/MozAngleLink.cpp
gfx/angle/src/compiler/osinclude.h
gfx/angle/src/compiler/ossource_nspr.cpp
gfx/thebes/GLDefs.h
modules/libpref/src/init/all.js
toolkit/library/libxul-config.mk
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -74,16 +74,24 @@ ifdef MOZ_WEBGL
 CPPSRCS += \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
 	WebGLContextValidate.cpp \
 	NativeJSContext.cpp \
 	$(NULL)
 
+ifndef MOZ_ENABLE_LIBXUL
+
+SHARED_LIBRARY_LIBS += \
+	$(DEPTH)/gfx/angle/$(LIB_PREFIX)angle.$(LIB_SUFFIX) \
+	$(NULL)
+
+endif
+
 else
 
 CPPSRCS += WebGLContextNotSupported.cpp
 
 endif
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -69,25 +69,30 @@ NS_NewCanvasRenderingContextWebGL(nsICan
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = ctx);
     return NS_OK;
 }
 
 WebGLContext::WebGLContext()
     : mCanvasElement(nsnull),
-      gl(nsnull),
-      mWidth(0), mHeight(0),
-      mGeneration(0),
-      mInvalidated(PR_FALSE),
-      mActiveTexture(0),
-      mSynthesizedGLError(LOCAL_GL_NO_ERROR),
-      mPixelStoreFlipY(PR_FALSE),
-      mPixelStorePremultiplyAlpha(PR_FALSE)
+      gl(nsnull)
 {
+    mWidth = mHeight = 0;
+    mGeneration = 0;
+    mInvalidated = PR_FALSE;
+
+    mActiveTexture = 0;
+    mSynthesizedGLError = LOCAL_GL_NO_ERROR;
+    mPixelStoreFlipY = PR_FALSE;
+    mPixelStorePremultiplyAlpha = PR_FALSE;
+
+    // eventually true
+    mShaderValidation = PR_FALSE;
+
     mMapBuffers.Init();
     mMapTextures.Init();
     mMapPrograms.Init();
     mMapShaders.Init();
     mMapFramebuffers.Init();
     mMapRenderbuffers.Init();
 }
 
@@ -161,16 +166,27 @@ WebGLContext::SetDimensions(PRInt32 widt
     }
 
     GLContextProvider::ContextFormat format(GLContextProvider::ContextFormat::BasicRGBA32);
     format.depth = 16;
     format.minDepth = 1;
 
     gl = gl::sGLContextProvider.CreatePBuffer(gfxIntSize(width, height), format);
 
+#ifdef USE_GLES2
+    // On native GLES2, no need to validate, the compiler will do it
+    mShaderValidation = PR_FALSE;
+#else
+    // Check the shader validator pref
+    nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
+    NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
+
+    prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
+#endif
+
     if (!InitAndValidateGL()) {
         gl = gl::GLContextProviderOSMesa::CreatePBuffer(gfxIntSize(width, height), format);
         if (!InitAndValidateGL()) {
             LogMessage("WebGL: Can't get a usable OpenGL context.");
             return NS_ERROR_FAILURE;
         }
         else {
             LogMessage("WebGL: Using software rendering via OSMesa");
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -321,16 +321,30 @@ protected:
     PRInt32 mWidth, mHeight;
     CheckedUint32 mGeneration;
 
     PRBool mInvalidated;
 
     WebGLuint mActiveTexture;
     WebGLenum mSynthesizedGLError;
 
+    // whether shader validation is supported
+    PRBool mShaderValidation;
+
+    // some GL constants
+    PRUint32 mGLMaxVertexAttribs;
+    PRUint32 mGLMaxTextureUnits;
+    PRUint32 mGLMaxTextureSize;
+    PRUint32 mGLMaxCubeMapTextureSize;
+    PRUint32 mGLMaxTextureImageUnits;
+    PRUint32 mGLMaxVertexTextureImageUnits;
+    PRUint32 mGLMaxVaryingVectors;
+    PRUint32 mGLMaxFragmentUniformVectors;
+    PRUint32 mGLMaxVertexUniformVectors;
+
     PRBool SafeToCreateCanvas3DContext(nsHTMLCanvasElement *canvasElement);
     PRBool InitAndValidateGL();
     PRBool ValidateBuffers(PRUint32 count);
     PRBool ValidateCapabilityEnum(WebGLenum cap, const char *info);
     PRBool ValidateBlendEquationEnum(WebGLuint cap, const char *info);
     PRBool ValidateBlendFuncDstEnum(WebGLuint mode, const char *info);
     PRBool ValidateBlendFuncSrcEnum(WebGLuint mode, const char *info);
     PRBool ValidateTextureTargetEnum(WebGLenum target, const char *info);
@@ -649,36 +663,61 @@ class WebGLShader :
     public WebGLZeroingObject,
     public WebGLContextBoundObject
 {
 public:
     NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLSHADER_PRIVATE_IID)
 
     WebGLShader(WebGLContext *context, WebGLuint name, WebGLenum stype) :
         WebGLContextBoundObject(context),
-        mName(name), mDeleted(PR_FALSE), mType(stype)
+        mName(name), mDeleted(PR_FALSE), mType(stype),
+        mNeedsTranslation(true)
     { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
     }
 
     PRBool Deleted() { return mDeleted; }
     WebGLuint GLName() { return mName; }
     WebGLenum ShaderType() { return mType; }
 
+    void SetSource(const nsCString& src) {
+        // XXX do some quick gzip here maybe -- getting this will be very rare
+        mSource.Assign(src);
+    }
+
+    const nsCString& Source() const { return mSource; }
+
+    void SetNeedsTranslation() { mNeedsTranslation = true; }
+    bool NeedsTranslation() const { return mNeedsTranslation; }
+
+    void SetTranslationSuccess() {
+        mTranslationLog.SetIsVoid(PR_TRUE);
+        mNeedsTranslation = false;
+    }
+
+    void SetTranslationFailure(const nsCString& msg) {
+        mTranslationLog.Assign(msg);
+    }
+
+    const nsCString& TranslationLog() const { return mTranslationLog; }
+
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLSHADER
 protected:
     WebGLuint mName;
     PRBool mDeleted;
     WebGLenum mType;
+    nsCString mSource;
+    nsCString mTranslationLog;
+    bool mNeedsTranslation;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(WebGLShader, WEBGLSHADER_PRIVATE_IID)
 
 #define WEBGLPROGRAM_PRIVATE_IID \
     {0xb3084a5b, 0xa5b4, 0x4ee0, {0xa0, 0xf0, 0xfb, 0xdd, 0x64, 0xaf, 0x8e, 0x82}}
 class WebGLProgram :
     public nsIWebGLProgram,
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -51,16 +51,21 @@
 #include "nsDOMError.h"
 #include "nsLayoutUtils.h"
 
 #include "CanvasUtils.h"
 #include "NativeJSContext.h"
 
 #include "jstypedarray.h"
 
+#ifndef USE_GLES2
+// shader translator
+#include "angle/ShaderLang.h"
+#endif
+
 using namespace mozilla;
 
 static PRBool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize);
 
 /* Helper macros for when we're just wrapping a gl method, so that
  * we can avoid having to type this 500 times.  Note that these MUST
  * NOT BE USED if we need to check any of the parameters.
  */
@@ -2814,50 +2819,98 @@ WebGLContext::Viewport(WebGLint x, WebGL
     MakeContextCurrent();
     gl->fViewport(x, y, width, height);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CompileShader(nsIWebGLShader *sobj)
 {
+    WebGLShader *shader;
     WebGLuint shadername;
-    if (!GetGLName<WebGLShader>(sobj, &shadername))
+    if (!GetConcreteObjectAndGLName(sobj, &shader, &shadername))
         return ErrorInvalidOperation("CompileShader: invalid shader");
 
     MakeContextCurrent();
 
+#ifndef USE_GLES2
+    if (shader->NeedsTranslation() && mShaderValidation) {
+        ShHandle compiler = 0;
+        int debugFlags = 0;
+        EShLanguage lang = (shader->ShaderType() == LOCAL_GL_VERTEX_SHADER) ?
+            EShLangVertex : EShLangFragment;
+
+        TBuiltInResource resources;
+
+        resources.maxVertexAttribs = mGLMaxVertexAttribs;
+        resources.maxVertexUniformVectors = mGLMaxVertexUniformVectors;
+        resources.maxVaryingVectors = mGLMaxVaryingVectors;
+        resources.maxVertexTextureImageUnits = mGLMaxVertexTextureImageUnits;
+        resources.maxCombinedTextureImageUnits = mGLMaxTextureUnits;
+        resources.maxTextureImageUnits = mGLMaxTextureImageUnits;
+        resources.maxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
+        resources.maxDrawBuffers = 1;
+
+        compiler = ShConstructCompiler(lang, debugFlags);
+
+        nsDependentCString src(shader->Source());
+        const char *s = src.get();
+
+        if (!ShCompile(compiler, &s, 1, EShOptNone, &resources, debugFlags)) {
+            shader->SetTranslationFailure(nsDependentCString(ShGetInfoLog(compiler)));
+            ShDestruct(compiler);
+            return NS_OK;
+        }
+
+        s = ShGetObjectCode(compiler);
+        gl->fShaderSource(shadername, 1, &s, NULL);
+        shader->SetTranslationSuccess();
+
+        ShDestruct(compiler);
+    } else
+#endif
+    {
+        const char *s = nsDependentCString(shader->Source()).get();
+        gl->fShaderSource(shadername, 1, &s, NULL);
+        shader->SetTranslationSuccess();
+    }
+
     gl->fCompileShader(shadername);
 
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
 WebGLContext::GetShaderParameter(nsIWebGLShader *sobj, WebGLenum pname, nsIVariant **retval)
 {
+    WebGLShader *shader;
     WebGLuint shadername;
-    if (!GetGLName<WebGLShader>(sobj, &shadername))
+    if (!GetConcreteObjectAndGLName(sobj, &shader, &shadername))
         return ErrorInvalidOperation("GetShaderParameter: invalid shader");
 
     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_SHADER_TYPE:
         case LOCAL_GL_INFO_LOG_LENGTH:
-        case LOCAL_GL_SHADER_SOURCE_LENGTH:
         {
             GLint i = 0;
             gl->fGetShaderiv(shadername, pname, &i);
             wrval->SetAsInt32(i);
         }
             break;
+        case LOCAL_GL_SHADER_SOURCE_LENGTH:
+        {
+            wrval->SetAsInt32(PRInt32(shader->Source().Length()) + 1);
+        }
+            break;
         case LOCAL_GL_DELETE_STATUS:
         case LOCAL_GL_COMPILE_STATUS:
         {
             GLint i = 0;
             gl->fGetShaderiv(shadername, pname, &i);
             wrval->SetAsBool(PRBool(i));
         }
             break;
@@ -2869,20 +2922,27 @@ WebGLContext::GetShaderParameter(nsIWebG
     *retval = wrval.forget().get();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetShaderInfoLog(nsIWebGLShader *sobj, nsAString& retval)
 {
+    WebGLShader *shader;
     WebGLuint shadername;
-    if (!GetGLName<WebGLShader>(sobj, &shadername))
+    if (!GetConcreteObjectAndGLName(sobj, &shader, &shadername))
         return ErrorInvalidOperation("GetShaderInfoLog: invalid shader");
 
+    const nsCString& tlog = shader->TranslationLog();
+    if (!tlog.IsVoid()) {
+        CopyASCIItoUTF16(tlog, retval);
+        return NS_OK;
+    }
+
     MakeContextCurrent();
 
     PRInt32 k = -1;
     gl->fGetShaderiv(shadername, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &k);
     if (k == -1)
         return NS_ERROR_FAILURE; // XXX GL Error? should never happen.
 
     if (k == 0) {
@@ -2900,57 +2960,38 @@ WebGLContext::GetShaderInfoLog(nsIWebGLS
     CopyASCIItoUTF16(log, retval);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetShaderSource(nsIWebGLShader *sobj, nsAString& retval)
 {
+    WebGLShader *shader;
     WebGLuint shadername;
-    if (!GetGLName<WebGLShader>(sobj, &shadername))
+    if (!GetConcreteObjectAndGLName(sobj, &shader, &shadername))
         return ErrorInvalidOperation("GetShaderSource: invalid shader");
 
-    MakeContextCurrent();
-
-    GLint slen = -1;
-    gl->fGetShaderiv(shadername, LOCAL_GL_SHADER_SOURCE_LENGTH, &slen);
-    if (slen == -1)
-        return NS_ERROR_FAILURE;
-
-    if (slen == 0) {
-        retval.Truncate();
-        return NS_OK;
-    }
-
-    nsCAutoString src;
-    src.SetCapacity(slen);
-
-    gl->fGetShaderSource(shadername, slen, NULL, (char*) src.BeginWriting());
-
-    src.SetLength(slen);
-
-    CopyASCIItoUTF16(src, retval);
+    CopyASCIItoUTF16(shader->Source(), retval);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::ShaderSource(nsIWebGLShader *sobj, const nsAString& source)
 {
+    WebGLShader *shader;
     WebGLuint shadername;
-    if (!GetGLName<WebGLShader>(sobj, &shadername))
+    if (!GetConcreteObjectAndGLName(sobj, &shader, &shadername))
         return ErrorInvalidOperation("ShaderSource: invalid shader");
     
-    MakeContextCurrent();
-
-    NS_LossyConvertUTF16toASCII asciisrc(source);
-    const char *p = asciisrc.get();
-
-    gl->fShaderSource(shadername, 1, &p, NULL);
+    shader->SetSource(NS_LossyConvertUTF16toASCII(source));
+
+    shader->SetNeedsTranslation();
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type,
                                   WebGLboolean normalized, WebGLuint stride,
                                   WebGLuint byteOffset)
 {
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -36,16 +36,20 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "WebGLContext.h"
 
 #include "CheckedInt.h"
 
+#ifndef USE_GLES2
+#include "angle/ShaderLang.h"
+#endif
+
 using namespace mozilla;
 
 /*
  * Pull all the data out of the program that will be used by validate later on
  */
 PRBool
 WebGLProgram::UpdateInfo(gl::GLContext *gl)
 {
@@ -356,52 +360,76 @@ WebGLContext::InitAndValidateGL()
     mMapRenderbuffers.Clear();
 
     // make sure that the opengl stuff that we need is supported
     GLint val = 0;
 
     // XXX this exposes some strange latent bug; what's going on?
     //MakeContextCurrent();
 
-    gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &val);
-    if (val == 0) {
-        LogMessage("GL_MAX_VERTEX_ATTRIBS is 0!");
+    gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, (GLint*) &mGLMaxVertexAttribs);
+    if (mGLMaxVertexAttribs < 8) {
+        LogMessage("GL_MAX_VERTEX_ATTRIBS is < 8!");
         return PR_FALSE;
     }
 
-    mAttribBuffers.SetLength(val);
-
-    //fprintf(stderr, "GL_MAX_VERTEX_ATTRIBS: %d\n", val);
+    mAttribBuffers.SetLength(mGLMaxVertexAttribs);
 
     // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
     // even though the hardware supports much more.  The
-    // GL_MAX_{COMBINED_}TEXTURE_IMAGE_UNITS value is the accurate
-    // value.  For GLES2, GL_MAX_TEXTURE_UNITS is still correct.
-    gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &val);
-    if (val == 0) {
-        LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is 0!");
+    // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
+    gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, (GLint*) &mGLMaxTextureUnits);
+    if (mGLMaxTextureUnits < 8) {
+        LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is < 8!");
         return PR_FALSE;
     }
 
-    mBound2DTextures.SetLength(val);
-    mBoundCubeMapTextures.SetLength(val);
+    mBound2DTextures.SetLength(mGLMaxTextureUnits);
+    mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
+
+    gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
+    gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*) &mGLMaxCubeMapTextureSize);
+
+    gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*) &mGLMaxTextureImageUnits);
+    gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, (GLint*) &mGLMaxVertexTextureImageUnits);
 
-    //fprintf(stderr, "GL_MAX_TEXTURE_UNITS: %d\n", val);
+#ifdef USE_GLES2
+    gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, (GLint*) &mGLMaxFragmentUniformVectors);
+    gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, (GLint*) &mGLMaxVertexUniformVectors);
+    gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, (GLint*) &mGLMaxVaryingVectors);
+#else
+    gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, (GLint*) &mGLMaxFragmentUniformVectors);
+    mGLMaxFragmentUniformVectors /= 4;
+    gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, (GLint*) &mGLMaxVertexUniformVectors);
+    mGLMaxVertexUniformVectors /= 4;
+    gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_FLOATS, (GLint*) &mGLMaxVaryingVectors);
+    mGLMaxVaryingVectors /= 4;
+#endif
 
-    gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &val);
+    gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, (GLint*) &val);
     mFramebufferColorAttachments.SetLength(val);
 
 #if defined(DEBUG_vladimir) && defined(USE_GLES2)
-    gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &val);
+    gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, (GLint*) &val);
     fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_FORMAT: 0x%04x\n", val);
 
-    gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &val);
+    gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, (GLint*) &val);
     fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_TYPE: 0x%04x\n", val);
 #endif
 
 #ifndef USE_GLES2
     // gl_PointSize is always available in ES2 GLSL, but has to be
     // specifically enabled on desktop GLSL.
     gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
+
+    // initialize shader translator
+    static bool didTranslatorInit = false;
+    if (!didTranslatorInit && mShaderValidation) {
+        if (!ShInitialize()) {
+            LogMessage("GLSL translator initialization failed!");
+            return PR_FALSE;
+        }
+        didTranslatorInit = true;
+    }
 #endif
 
     return PR_TRUE;
 }
--- a/gfx/Makefile.in
+++ b/gfx/Makefile.in
@@ -51,16 +51,18 @@ endif
 # In static builds, ycbcr must appear after layers in
 # the link line on linux. This order is defined by the
 # order listed in DIRS. On shared builds ycbcr must
 # be built first so the order is reversed.
 ifndef BUILD_STATIC_LIBS
 DIRS		+= ycbcr
 endif
 
+DIRS		+= angle
+
 DIRS		+= src qcms layers harfbuzz/src thebes src/thebes
 
 ifdef BUILD_STATIC_LIBS
 DIRS		+= ycbcr
 endif
 
 ifdef MOZ_IPC
 DIRS		+= ipc
new file mode 100644
--- /dev/null
+++ b/gfx/angle/Makefile.in
@@ -0,0 +1,126 @@
+# 
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is gecko.
+#
+# The Initial Developer of the Original Code is
+#   Mozilla 
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= angle
+LIBRARY_NAME	= angle
+LIBXUL_LIBRARY  = 1
+EXPORT_LIBRARY  = 1
+
+EXPORTS_NAMESPACES = angle
+
+EXPORTS_angle = \
+	include/GLSLANG/ShaderLang.h \
+	include/GLSLANG/ResourceLimits.h \
+	$(NULL)
+
+LOCAL_INCLUDES += -I$(srcdir)/include -I$(srcdir)/src
+
+VPATH += $(srcdir)/src
+VPATH += $(srcdir)/src/compiler
+VPATH += $(srcdir)/src/compiler/preprocessor
+VPATH += $(srcdir)/generated
+
+CPPSRCS = \
+        InfoSink.cpp \
+        Initialize.cpp \
+        InitializeDll.cpp \
+        Intermediate.cpp \
+        intermOut.cpp \
+        IntermTraverse.cpp \
+        MozAngleLink.cpp \
+        parseConst.cpp \
+        ParseHelper.cpp \
+        PoolAlloc.cpp \
+        QualifierAlive.cpp \
+        RemoveTree.cpp \
+        ShaderLang.cpp \
+        SymbolTable.cpp \
+	debug.cpp \
+	ossource_nspr.cpp \
+	$(NULL)
+
+# flex/yacc generated files
+CPPSRCS += \
+	glslang.cpp \
+	glslang_tab.cpp \
+	$(NULL)
+
+# GLSL translator backend
+CPPSRCS += \
+	CodeGenGLSL.cpp \
+	OutputGLSL.cpp \
+	TranslatorGLSL.cpp \
+	$(NULL)
+
+# Currently, only one or the other
+# can be selected.
+
+## HLSL translator backend
+##CPPSRCS += \
+##	CodeGenHLSL.cpp \
+##	OutputHLSL.cpp \
+##	TranslatorHLSL.cpp \
+##	UnfoldSelect.cpp \
+##	$(NULL)
+
+CSRCS   = \
+        atom.c \
+        cpp.c \
+        cppstruct.c \
+        memory.c \
+        scanner.c \
+        symbols.c \
+        tokens.c \
+	$(NULL)
+
+DEFINES += -DANGLE_USE_NSPR
+
+include $(topsrcdir)/config/rules.mk
+
+# We have to filter out -pedantic, because of
+# comma-at-end-of-enumerator list failures.  We can try to get this fixed
+# upstream at some point.
+CXXFLAGS := $(filter-out -pedantic,$(CXXFLAGS))
+CFLAGS := $(filter-out -pedantic,$(CFLAGS))
+
new file mode 100644
--- /dev/null
+++ b/gfx/angle/README.mozilla
@@ -0,0 +1,12 @@
+This is the ANGLE project, from http://code.google.com/p/angleproject/.
+
+Current revision: r342
+
+Local patches:
+    angle-nspr.patch - use NSPR for TLS
+
+To regenerate the flex/yacc generated files:
+
+flex --noline --nounistd --outfile=generated/glslang.cpp src/compiler/glslang.l
+bison --no-lines --defines=generated/glslang_tab.h --skeleton=yacc.c --output=generated/glslang_tab.cpp src/compiler/glslang.y
+
new file mode 100644
--- /dev/null
+++ b/gfx/angle/angle-nspr.patch
@@ -0,0 +1,100 @@
+Simple ossource implementation using NSPR
+
+diff --git a/gfx/angle/src/compiler/osinclude.h b/gfx/angle/src/compiler/osinclude.h
+--- a/gfx/angle/src/compiler/osinclude.h
++++ b/gfx/angle/src/compiler/osinclude.h
+@@ -7,8 +7,14 @@
+ #ifndef __OSINCLUDE_H
+ #define __OSINCLUDE_H
+ 
++#ifdef ANGLE_USE_NSPR
++
++#include "prthread.h"
++
++#else
++
+ //
+-// This file contains contains the window's specific datatypes and
++// This file contains contains windows specific datatypes and
+ // declares any windows specific functions.
+ //
+ 
+@@ -32,12 +38,17 @@
+ #include <errno.h>
+ #endif  // ANGLE_OS_WIN
+ 
++#endif  // ANGLE_USE_NSPR
++
+ #include "compiler/debug.h"
+ 
+ //
+ // Thread Local Storage Operations
+ //
+-#if defined(ANGLE_OS_WIN)
++#if defined(ANGLE_USE_NSPR)
++typedef PRUintn OS_TLSIndex;
++#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
++#elif defined(ANGLE_OS_WIN)
+ typedef DWORD OS_TLSIndex;
+ #define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+ #elif defined(ANGLE_OS_POSIX)
+@@ -52,7 +63,9 @@ bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+ inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+ {
+     assert(nIndex != OS_INVALID_TLS_INDEX);
+-#if defined(ANGLE_OS_WIN)
++#if defined(ANGLE_USE_NSPR)
++    return PR_GetThreadPrivate(nIndex);
++#elif defined(ANGLE_OS_WIN)
+     return TlsGetValue(nIndex);
+ #elif defined(ANGLE_OS_POSIX)
+     return pthread_getspecific(nIndex);
+diff --git a/gfx/angle/src/compiler/ossource_nspr.cpp b/gfx/angle/src/compiler/ossource_nspr.cpp
+new file mode 100644
+--- /dev/null
++++ b/gfx/angle/src/compiler/ossource_nspr.cpp
+@@ -0,0 +1,44 @@
++//
++// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++//
++
++//
++// This file contains the posix specific functions
++//
++#include "compiler/osinclude.h"
++
++//
++// Thread Local Storage Operations
++//
++OS_TLSIndex OS_AllocTLSIndex()
++{
++    PRUintn index;
++    PRStatus status = PR_NewThreadPrivateIndex(&index, NULL);
++
++    if (status) {
++        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
++        return OS_INVALID_TLS_INDEX;
++    }
++
++    return index;
++}
++
++
++bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
++{
++    if (nIndex == OS_INVALID_TLS_INDEX) {
++        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
++        return false;
++    }
++
++    return PR_SetThreadPrivate(nIndex, lpvValue) == 0;
++}
++
++
++bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
++{
++    // Can't delete TLS keys with nspr
++    return true;
++}
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -33,17 +33,17 @@ int ShInitialize();
 //
 int __fastcall ShFinalize();
 //
 // Types of languages the compiler can consume.
 //
 typedef enum {
 	EShLangVertex,
 	EShLangFragment,
-	EShLangCount,
+	EShLangCount
 } EShLanguage;
 
 //
 // Types of output the linker will create.
 //
 typedef enum {
 	EShExVertexFragment,
 	EShExFragment
@@ -51,17 +51,17 @@ typedef enum {
 
 //
 // Optimization level for the compiler.
 //
 typedef enum {
 	EShOptNoGeneration,
 	EShOptNone,
 	EShOptSimple,       // Optimizations that can be done quickly
-	EShOptFull,         // Optimizations that will take more time
+	EShOptFull          // Optimizations that will take more time
 } EShOptimizationLevel;
 
 //
 // Build a table for bindings.  This can be used for locating
 // attributes, uniforms, globals, etc., as needed.
 //
 typedef struct {
 	const char* name;
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/compiler/MozAngleLink.cpp
@@ -0,0 +1,4 @@
+/* We already have a Link.cpp in content, and our link unpack step
+ * ends up munging the two Link.o's as a result */
+
+#include "Link.cpp"
--- a/gfx/angle/src/compiler/osinclude.h
+++ b/gfx/angle/src/compiler/osinclude.h
@@ -2,18 +2,24 @@
 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #ifndef __OSINCLUDE_H
 #define __OSINCLUDE_H
 
+#ifdef ANGLE_USE_NSPR
+
+#include "prthread.h"
+
+#else
+
 //
-// This file contains contains the window's specific datatypes and
+// This file contains contains windows specific datatypes and
 // declares any windows specific functions.
 //
 
 #if defined(_WIN32) || defined(_WIN64)
 #define ANGLE_OS_WIN
 #elif defined(__APPLE__) || defined(__linux__) || \
       defined(__FreeBSD__) || defined(__OpenBSD__) || \
       defined(__sun)
@@ -27,36 +33,43 @@
 #define VC_EXTRALEAN 1
 #include <windows.h>
 #elif defined(ANGLE_OS_POSIX)
 #include <pthread.h>
 #include <semaphore.h>
 #include <errno.h>
 #endif  // ANGLE_OS_WIN
 
+#endif  // ANGLE_USE_NSPR
+
 #include "compiler/debug.h"
 
 //
 // Thread Local Storage Operations
 //
-#if defined(ANGLE_OS_WIN)
+#if defined(ANGLE_USE_NSPR)
+typedef PRUintn OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#elif defined(ANGLE_OS_WIN)
 typedef DWORD OS_TLSIndex;
 #define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
 #elif defined(ANGLE_OS_POSIX)
 typedef unsigned int OS_TLSIndex;
 #define OS_INVALID_TLS_INDEX 0xFFFFFFFF
 #endif  // ANGLE_OS_WIN
 
 OS_TLSIndex OS_AllocTLSIndex();
 bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
 bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
 
 inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
 {
     assert(nIndex != OS_INVALID_TLS_INDEX);
-#if defined(ANGLE_OS_WIN)
+#if defined(ANGLE_USE_NSPR)
+    return PR_GetThreadPrivate(nIndex);
+#elif defined(ANGLE_OS_WIN)
     return TlsGetValue(nIndex);
 #elif defined(ANGLE_OS_POSIX)
     return pthread_getspecific(nIndex);
 #endif  // ANGLE_OS_WIN
 }
 
 #endif // __OSINCLUDE_H
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/compiler/ossource_nspr.cpp
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// This file contains the posix specific functions
+//
+#include "compiler/osinclude.h"
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+    PRUintn index;
+    PRStatus status = PR_NewThreadPrivateIndex(&index, NULL);
+
+    if (status) {
+        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+        return OS_INVALID_TLS_INDEX;
+    }
+
+    return index;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    return PR_SetThreadPrivate(nIndex, lpvValue) == 0;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+    // Can't delete TLS keys with nspr
+    return true;
+}
--- a/gfx/thebes/GLDefs.h
+++ b/gfx/thebes/GLDefs.h
@@ -3018,16 +3018,19 @@ typedef ptrdiff_t GLintptr;
 #define LOCAL_GL_SUN_vertex 1
 #define LOCAL_GL_WIN_phong_shading 1
 #define LOCAL_GL_PHONG_WIN 0x80EA
 #define LOCAL_GL_PHONG_HINT_WIN 0x80EB
 #define LOCAL_GL_WIN_specular_fog 1
 #define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
 #define LOCAL_GL_WIN_swap_hint 1
 
+#define LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define LOCAL_GL_MAX_VARYING_VECTORS              0x8DFC
+#define LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
 #define LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
 #define LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
 #define LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS    0x9125
 #define LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS     0x9122
 
 #define LOCAL_WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
 #define LOCAL_WGL_DRAW_TO_WINDOW_ARB 0x2001
 #define LOCAL_WGL_DRAW_TO_BITMAP_ARB 0x2002
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3120,16 +3120,17 @@ pref("image.mem.decodeondraw", false);
 
 // Minimum timeout for image discarding (in milliseconds). The actual time in
 // which an image must inactive for it to be discarded will vary between this
 // value and twice this value.
 pref("image.mem.min_discard_timeout_ms", 10000);
 
 // WebGL prefs
 pref("webgl.enabled_for_all_sites", false);
+pref("webgl.shader_validator", false);
 pref("webgl.software_render", false);
 pref("webgl.osmesalib", "");
 
 #ifdef XP_WIN
 #ifndef WINCE
 // The default TCP send window on Windows is too small, and autotuning only occurs on receive
 pref("network.tcp.sendbuffer", 131072);
 #endif
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -296,17 +296,17 @@ ifneq (,$(filter icon,$(MOZ_IMG_DECODERS
 DEFINES += -DICON_DECODER
 COMPONENT_LIBS += imgicon
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
 COMPONENT_LIBS += widget_android
 endif
 
-STATIC_LIBS += thebes ycbcr
+STATIC_LIBS += thebes ycbcr angle
 COMPONENT_LIBS += gkgfxthebes
 
 ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
 COMPONENT_LIBS += gkwidget
 endif
 ifeq (beos,$(MOZ_WIDGET_TOOLKIT))
 COMPONENT_LIBS += widget_beos
 endif