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 id14386
push uservladimir@mozilla.com
push dateThu, 15 Jul 2010 03:53:24 +0000
treeherdermozilla-central@42029b6d627e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs571172
milestone2.0b2pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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