Bug 750862 - Implement WEBGL_compressed_texture_pvrtc - r=jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 25 Sep 2012 08:49:28 -0400
changeset 108120 33f80363eab3ef603820cd3cc257005874bb25e2
parent 108119 c066bfd5d4e8117c5d40088146a8a3364a7b73a9
child 108121 b8c267074d6293e6f613ca01338be06ff6278801
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersjgilbert
bugs750862
milestone18.0a1
Bug 750862 - Implement WEBGL_compressed_texture_pvrtc - r=jgilbert
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextUtils.cpp
content/canvas/src/WebGLContextValidate.cpp
content/canvas/src/WebGLExtensionCompressedTexturePVRTC.cpp
content/canvas/src/WebGLExtensions.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
dom/tests/mochitest/general/test_interfaces.html
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLDefs.h
js/xpconnect/src/dom_quickstubs.qsconf
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -48,16 +48,17 @@ CPPSRCS += \
 	WebGLContextReporter.cpp \
 	WebGLContextValidate.cpp \
 	WebGLExtensionStandardDerivatives.cpp \
 	WebGLExtensionTextureFilterAnisotropic.cpp \
 	WebGLExtensionLoseContext.cpp \
 	WebGLTexelConversions.cpp \
 	WebGLExtensionCompressedTextureS3TC.cpp \
 	WebGLExtensionCompressedTextureATC.cpp \
+	WebGLExtensionCompressedTexturePVRTC.cpp \
 	WebGLExtensionDepthTexture.cpp \
 	WebGLElementArrayCache.cpp \
 	$(NULL)
 
 DEFINES += -DUSE_ANGLE
 USE_ANGLE=1
 
 else
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -963,16 +963,21 @@ bool WebGLContext::IsExtensionSupported(
                 isSupported = true;
             }
             break;
         case WEBGL_compressed_texture_atc:
             if (gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture)) {
                 isSupported = true;
             }
             break;
+        case WEBGL_compressed_texture_pvrtc:
+            if (gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc)) {
+                isSupported = true;
+            }
+            break;
         case WEBGL_depth_texture:
             if (gl->IsGLES2() && 
                 gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil) &&
                 gl->IsExtensionSupported(GLContext::OES_depth_texture)) 
             {
                 isSupported = true;
             } else if (!gl->IsGLES2() &&
                        gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) 
@@ -1030,16 +1035,22 @@ WebGLContext::GetExtension(const nsAStri
             ext = WEBGL_compressed_texture_s3tc;
     }
     else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"),
              nsCaseInsensitiveStringComparator()))
     {
         if (IsExtensionSupported(WEBGL_compressed_texture_atc))
             ext = WEBGL_compressed_texture_atc;
     }
+    else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"),
+             nsCaseInsensitiveStringComparator()))
+    {
+        if (IsExtensionSupported(WEBGL_compressed_texture_pvrtc))
+            ext = WEBGL_compressed_texture_pvrtc;
+    }
     else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"),
              nsCaseInsensitiveStringComparator()))
     {
         if (IsExtensionSupported(WEBGL_depth_texture))
             ext = WEBGL_depth_texture;
     }
 
     if (ext == WebGLExtensionID_unknown_extension) {
@@ -1058,16 +1069,19 @@ WebGLContext::GetExtension(const nsAStri
                 mExtensions[ext] = new WebGLExtensionLoseContext(this);
                 break;
             case WEBGL_compressed_texture_s3tc:
                 mExtensions[ext] = new WebGLExtensionCompressedTextureS3TC(this);
                 break;
             case WEBGL_compressed_texture_atc:
                 mExtensions[ext] = new WebGLExtensionCompressedTextureATC(this);
                 break;
+            case WEBGL_compressed_texture_pvrtc:
+                mExtensions[ext] = new WebGLExtensionCompressedTexturePVRTC(this);
+                break;
             case WEBGL_depth_texture:
                 mExtensions[ext] = new WebGLExtensionDepthTexture(this);
                 break;
             default:
                 // create a generic WebGLExtension object for any extensions that don't
                 // have any additional tokens or methods. We still need these to be separate
                 // objects in case the user might extend the corresponding JS objects with custom
                 // properties.
@@ -1581,11 +1595,13 @@ WebGLContext::GetSupportedExtensions(Nul
         arr.AppendElement(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"));
     }
     if (IsExtensionSupported(WEBGL_lose_context))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
     if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
     if (IsExtensionSupported(WEBGL_compressed_texture_atc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
+    if (IsExtensionSupported(WEBGL_compressed_texture_pvrtc))
+        arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
     if (IsExtensionSupported(WEBGL_depth_texture))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
 }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -456,22 +456,23 @@ struct WebGLContextOptions {
 class WebGLContext :
     public nsIDOMWebGLRenderingContext,
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
     public nsITimerCallback,
     public WebGLRectangleObject,
     public nsWrapperCache
 {
+    friend class WebGLContextUserData;
+    friend class WebGLMemoryPressureObserver;
     friend class WebGLMemoryMultiReporterWrapper;
     friend class WebGLExtensionLoseContext;
     friend class WebGLExtensionCompressedTextureS3TC;
     friend class WebGLExtensionCompressedTextureATC;
-    friend class WebGLContextUserData;
-    friend class WebGLMemoryPressureObserver;
+    friend class WebGLExtensionCompressedTexturePVRTC;
     friend class WebGLExtensionDepthTexture;
 
     enum {
         UNPACK_FLIP_Y_WEBGL = 0x9240,
         UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241,
         CONTEXT_LOST_WEBGL = 0x9242,
         UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243,
         BROWSER_DEFAULT_WEBGL = 0x9244
@@ -1167,16 +1168,17 @@ protected:
     // extensions
     enum WebGLExtensionID {
         OES_texture_float,
         OES_standard_derivatives,
         EXT_texture_filter_anisotropic,
         WEBGL_lose_context,
         WEBGL_compressed_texture_s3tc,
         WEBGL_compressed_texture_atc,
+        WEBGL_compressed_texture_pvrtc,
         WEBGL_depth_texture,
         WebGLExtensionID_number_of_extensions,
         WebGLExtensionID_unknown_extension
     };
     nsAutoTArray<nsRefPtr<WebGLExtension>, WebGLExtensionID_number_of_extensions> mExtensions;
 
     // returns true if the extension has been enabled by calling getExtension.
     bool IsExtensionEnabled(WebGLExtensionID ext) {
@@ -1206,17 +1208,17 @@ protected:
     bool ValidateAttribIndex(WebGLuint index, const char *info);
     bool ValidateStencilParamsForDrawCall();
     
     bool ValidateGLSLVariableName(const nsAString& name, const char *info);
     bool ValidateGLSLCharacter(PRUnichar c);
     bool ValidateGLSLString(const nsAString& string, const char *info);
 
     bool ValidateTexImage2DTarget(WebGLenum target, WebGLsizei width, WebGLsizei height, const char* info);
-    bool ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info);
+    bool ValidateCompressedTextureSize(WebGLenum target, WebGLint level, WebGLenum format, WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info);
     bool ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width, WebGLsizei height, const char* info);
 
     static uint32_t GetBitsPerTexel(WebGLenum format, WebGLenum type);
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
     void MakeContextCurrent() { gl->MakeCurrent(); }
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -4220,27 +4220,23 @@ WebGLContext::CompressedTexImage2D(WebGL
         return;
     }
 
     if (!mCompressedTextureFormats.Contains(internalformat)) {
         ErrorInvalidEnum("compressedTexImage2D: compressed texture format 0x%x is not supported", internalformat);
         return;
     }
 
-    if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "compressedTexImage2D")) {
-        return;
-    }
-
     if (border) {
         ErrorInvalidValue("compressedTexImage2D: border is not 0");
         return;
     }
 
     uint32_t byteLength = view.Length();
-    if (!ValidateCompressedTextureSize(level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
+    if (!ValidateCompressedTextureSize(target, level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
         return;
     }
 
     gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
     tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
 }
 
 void
@@ -4276,17 +4272,17 @@ WebGLContext::CompressedTexSubImage2D(We
         return;
     }
 
     if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "compressedTexSubImage2D")) {
         return;
     }
 
     uint32_t byteLength = view.Length();
-    if (!ValidateCompressedTextureSize(level, format, width, height, byteLength, "compressedTexSubImage2D")) {
+    if (!ValidateCompressedTextureSize(target, level, format, width, height, byteLength, "compressedTexSubImage2D")) {
         return;
     }
 
     size_t face = WebGLTexture::FaceForTarget(target);
 
     if (!tex->HasImageInfoAt(level, face)) {
         ErrorInvalidOperation("compressedTexSubImage2D: no texture image previously defined for this level and face");
         return;
@@ -4318,16 +4314,29 @@ WebGLContext::CompressedTexSubImage2D(We
                 return;
             }
             if (height % 4 != 0 && height != imageInfo.Height()) {
                 ErrorInvalidOperation("compressedTexSubImage2D: height is not a multiple of 4 or equal to texture height");
                 return;
             }
             break;
         }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        {
+            if (xoffset || yoffset ||
+                width != imageInfo.Width() ||
+                height != imageInfo.Height())
+            {
+                ErrorInvalidValue("compressedTexSubImage2D: the update rectangle doesn't match the existing image");
+                return;
+            }
+        }
     }
 
     gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
 
     return;
 }
 
 JS::Value
--- a/content/canvas/src/WebGLContextUtils.cpp
+++ b/content/canvas/src/WebGLContextUtils.cpp
@@ -196,15 +196,19 @@ WebGLContext::IsTextureFormatCompressed(
 
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
         case LOCAL_GL_ATC_RGB:
         case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
         case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
             return true;
     }
 
     NS_NOTREACHED("Invalid WebGL texture format?");
     NS_ABORT();
     return false;
 }
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -366,19 +366,27 @@ bool WebGLContext::ValidateTexImage2DTar
         default:
             ErrorInvalidEnum("%s: invalid target enum 0x%x", info, target);
             return false;
     }
 
     return true;
 }
 
-bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width,
-                                                 WebGLsizei height, uint32_t byteLength, const char* info)
+bool WebGLContext::ValidateCompressedTextureSize(WebGLenum target, WebGLint level,
+                                                 WebGLenum format,
+                                                 WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info)
 {
+    if (!ValidateLevelWidthHeightForTarget(target, level, width, height, info)) {
+        return false;
+    }
+
+    // negative width and height must already have been handled above
+    MOZ_ASSERT(width >= 0 && height >= 0);
+
     CheckedUint32 required_byteLength = 0;
 
     switch (format) {
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         case LOCAL_GL_ATC_RGB:
         {
             required_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
@@ -387,16 +395,28 @@ bool WebGLContext::ValidateCompressedTex
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
         case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
         case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
         {
             required_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
             break;
         }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        {
+            required_byteLength = CheckedUint32(NS_MAX(width, 8)) * CheckedUint32(NS_MAX(height, 8)) / 2;
+            break;
+        }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        {
+            required_byteLength = CheckedUint32(NS_MAX(width, 16)) * CheckedUint32(NS_MAX(height, 8)) / 4;
+            break;
+        }
     }
 
     if (!required_byteLength.isValid() || required_byteLength.value() != byteLength) {
         ErrorInvalidValue("%s: data size does not match dimensions", info);
         return false;
     }
 
     switch (format) {
@@ -412,16 +432,28 @@ bool WebGLContext::ValidateCompressedTex
                 && (width == 0 || width == 1 || width == 2 || width % 4 == 0)
                 && (height == 0 || height == 1 || height == 2 || height % 4 == 0))
             {
                 break;
             }
             ErrorInvalidOperation("%s: level parameter does not match width and height", info);
             return false;
         }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        {
+            if (!is_pot_assuming_nonnegative(width) ||
+                !is_pot_assuming_nonnegative(height))
+            {
+                ErrorInvalidValue("%s: width and height must be powers of two", info);
+                return false;
+            }
+        }
     }
 
     return true;
 }
 
 bool WebGLContext::ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width,
                                                      WebGLsizei height, const char* info)
 {
@@ -474,19 +506,24 @@ uint32_t WebGLContext::GetBitsPerTexel(W
             case LOCAL_GL_LUMINANCE:
                 return 1 * multiplier;
             case LOCAL_GL_LUMINANCE_ALPHA:
                 return 2 * multiplier;
             case LOCAL_GL_RGB:
                 return 3 * multiplier;
             case LOCAL_GL_RGBA:
                 return 4 * multiplier;
+            case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+                return 2;
             case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
             case LOCAL_GL_ATC_RGB:
+            case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
                 return 4;
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
             case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
             case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
                 return 8;
             default:
                 break;
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLExtensionCompressedTexturePVRTC.cpp
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebGLContext.h"
+#include "WebGLExtensions.h"
+
+using namespace mozilla;
+
+WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(WebGLContext* context)
+    : WebGLExtension(context)
+{
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1);
+}
+
+WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
+{
+
+}
+
+NS_IMPL_ADDREF_INHERITED(WebGLExtensionCompressedTexturePVRTC, WebGLExtension)
+NS_IMPL_RELEASE_INHERITED(WebGLExtensionCompressedTexturePVRTC, WebGLExtension)
+
+DOMCI_DATA(WebGLExtensionCompressedTexturePVRTC, WebGLExtensionCompressedTexturePVRTC)
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionCompressedTexturePVRTC)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionCompressedTexturePVRTC)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionCompressedTexturePVRTC)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
--- a/content/canvas/src/WebGLExtensions.h
+++ b/content/canvas/src/WebGLExtensions.h
@@ -63,16 +63,28 @@ class WebGLExtensionCompressedTextureATC
 public:
     WebGLExtensionCompressedTextureATC(WebGLContext* context);
     virtual ~WebGLExtensionCompressedTextureATC();
 
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBGLEXTENSION
 };
 
+class WebGLExtensionCompressedTexturePVRTC :
+    public nsIWebGLExtensionCompressedTexturePVRTC,
+    public WebGLExtension
+{
+public:
+    WebGLExtensionCompressedTexturePVRTC(WebGLContext* context);
+    virtual ~WebGLExtensionCompressedTexturePVRTC();
+
+    NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_NSIWEBGLEXTENSION
+};
+
 class WebGLExtensionDepthTexture :
     public nsIWebGLExtensionDepthTexture,
     public WebGLExtension
 {
 public:
     WebGLExtensionDepthTexture(WebGLContext* context);
     virtual ~WebGLExtensionDepthTexture();
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1582,16 +1582,19 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureS3TC, WebGLExtensionSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureATC, WebGLExtensionSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTexturePVRTC, WebGLExtensionSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
+                           nsIXPCScriptable::WANT_ADDPROPERTY)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionDepthTexture, WebGLExtensionSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
 
   NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PaintRequestList, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -4283,16 +4286,20 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTextureS3TC, nsIWebGLExtensionCompressedTextureS3TC)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureS3TC)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTextureATC, nsIWebGLExtensionCompressedTextureATC)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureATC)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTexturePVRTC, nsIWebGLExtensionCompressedTexturePVRTC)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTexturePVRTC)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionDepthTexture, nsIWebGLExtensionDepthTexture)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionDepthTexture)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
    DOM_CLASSINFO_MAP_END
  
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -455,16 +455,17 @@ DOMCI_CLASS(WebGLUniformLocation)
 DOMCI_CLASS(WebGLShaderPrecisionFormat)
 DOMCI_CLASS(WebGLActiveInfo)
 DOMCI_CLASS(WebGLExtension)
 DOMCI_CLASS(WebGLExtensionStandardDerivatives)
 DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
 DOMCI_CLASS(WebGLExtensionLoseContext)
 DOMCI_CLASS(WebGLExtensionCompressedTextureS3TC)
 DOMCI_CLASS(WebGLExtensionCompressedTextureATC)
+DOMCI_CLASS(WebGLExtensionCompressedTexturePVRTC)
 DOMCI_CLASS(WebGLExtensionDepthTexture)
 
 DOMCI_CLASS(PaintRequest)
 DOMCI_CLASS(PaintRequestList)
 
 DOMCI_CLASS(ScrollAreaEvent)
 
 DOMCI_CLASS(EventListenerInfo)
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
+++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
@@ -159,16 +159,26 @@ interface nsIWebGLExtensionCompressedTex
 interface nsIWebGLExtensionCompressedTextureATC : nsIWebGLExtension
 {
     /* Compressed Texture Formats */
     const WebGLenum COMPRESSED_RGB_ATC_WEBGL                     = 0x8C92;
     const WebGLenum COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL     = 0x8C93;
     const WebGLenum COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
 };
 
+[scriptable, builtinclass, uuid(c33aa5a1-035c-4dfa-b240-df71395ad0f8)]
+interface nsIWebGLExtensionCompressedTexturePVRTC : nsIWebGLExtension
+{
+    /* Compressed Texture Formats */
+    const WebGLenum COMPRESSED_RGB_PVRTC_4BPPV1  = 0x8C00;
+    const WebGLenum COMPRESSED_RGB_PVRTC_2BPPV1  = 0x8C01;
+    const WebGLenum COMPRESSED_RGBA_PVRTC_4BPPV1 = 0x8C02;
+    const WebGLenum COMPRESSED_RGBA_PVRTC_2BPPV1 = 0x8C03;
+};
+
 [scriptable, builtinclass, uuid(ef36f000-c1b2-11e1-afa7-0800200c9a66)]
 interface nsIWebGLExtensionDepthTexture : nsIWebGLExtension
 {
   const WebGLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 };
 
 [builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
 interface nsIDOMWebGLRenderingContext : nsISupports
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -286,16 +286,17 @@ var interfaceNamesInGlobalScope =
     "HTMLAreaElement",
     "XULLabelElement",
     "FormData",
     "IDBDatabase",
     "CSSPrimitiveValue",
     "SVGStopElement",
     "WebGLExtensionCompressedTextureS3TC",
     "WebGLExtensionCompressedTextureATC",
+    "WebGLExtensionCompressedTexturePVRTC",
     "XULCommandEvent",
     "HTMLMediaElement",
     "SVGPathSegLinetoHorizontalAbs",
     "SVGAnimatedRect",
     "SVGTextContentElement",
     "WebGLRenderbuffer",
     "TreeColumn",
     "WebGLExtensionStandardDerivatives",
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -65,16 +65,17 @@ static const char *sExtensionNames[] = {
     "GL_EXT_unpack_subimage",
     "GL_OES_standard_derivatives",
     "GL_EXT_texture_filter_anisotropic",
     "GL_EXT_texture_compression_s3tc",
     "GL_EXT_texture_compression_dxt1",
     "GL_ANGLE_texture_compression_dxt3",
     "GL_ANGLE_texture_compression_dxt5",
     "GL_AMD_compressed_ATC_texture",
+    "GL_IMG_texture_compression_pvrtc",
     "GL_EXT_framebuffer_blit",
     "GL_ANGLE_framebuffer_blit",
     "GL_EXT_framebuffer_multisample",
     "GL_ANGLE_framebuffer_multisample",
     "GL_OES_rgb8_rgba8",
     "GL_ARB_robustness",
     "GL_EXT_robustness",
     "GL_ARB_sync",
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -1654,16 +1654,17 @@ public:
         EXT_unpack_subimage,
         OES_standard_derivatives,
         EXT_texture_filter_anisotropic,
         EXT_texture_compression_s3tc,
         EXT_texture_compression_dxt1,
         ANGLE_texture_compression_dxt3,
         ANGLE_texture_compression_dxt5,
         AMD_compressed_ATC_texture,
+        IMG_texture_compression_pvrtc,
         EXT_framebuffer_blit,
         ANGLE_framebuffer_blit,
         EXT_framebuffer_multisample,
         ANGLE_framebuffer_multisample,
         OES_rgb8_rgba8,
         ARB_robustness,
         EXT_robustness,
         ARB_sync,
--- a/gfx/gl/GLDefs.h
+++ b/gfx/gl/GLDefs.h
@@ -3093,16 +3093,22 @@ typedef void* GLeglImage;
 #define LOCAL_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB     0x00000002
 #define LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB             0x00000004
 
 // AMD_compressed_ATC_texture
 #define LOCAL_GL_ATC_RGB                                0x8C92
 #define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA                0x8C93
 #define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA            0x87EE
 
+// IMG_texture_compression_pvrtc
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1            0x8C00
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1            0x8C01
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1           0x8C02
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1           0x8C03
+
 #define LOCAL_WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
 #define LOCAL_WGL_DRAW_TO_WINDOW_ARB 0x2001
 #define LOCAL_WGL_DRAW_TO_BITMAP_ARB 0x2002
 #define LOCAL_WGL_ACCELERATION_ARB 0x2003
 #define LOCAL_WGL_NEED_PALETTE_ARB 0x2004
 #define LOCAL_WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
 #define LOCAL_WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
 #define LOCAL_WGL_SWAP_METHOD_ARB 0x2007
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -472,16 +472,17 @@ irregularFilenames = {
     'nsIWebGLActiveInfo': 'nsIDOMWebGLRenderingContext',
     'nsIWebGLUniformLocation': 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtension': 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionStandardDerivatives' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionTextureFilterAnisotropic' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionLoseContext' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionCompressedTextureS3TC' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionCompressedTextureATC' : 'nsIDOMWebGLRenderingContext',
+    'nsIWebGLExtensionCompressedTexturePVRTC' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionDepthTexture' : 'nsIDOMWebGLRenderingContext',
 
     'nsIIndexedDatabaseUsageCallback': 'nsIIndexedDatabaseManager',
 
     'nsIDOMTouch': 'nsIDOMTouchEvent',
     'nsIDOMTouchList': 'nsIDOMTouchEvent',
 
     'nsIDOMMutationRecord': 'nsIDOMMutationObserver',