Bug 742781 - Implement WEBGL_debug_renderer_info extension - r=bz,jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Wed, 17 Oct 2012 15:11:51 -0400
changeset 110577 756d555fc3bfab21090da03c6a7e4ed66b573761
parent 110576 df42fa3fb07f05f40d5aa09ab4787f1a76c9e0a6
child 110578 e78db739d5896d2b023f3c05f64169ff4470db47
push id23700
push userryanvm@gmail.com
push dateThu, 18 Oct 2012 02:10:26 +0000
treeherdermozilla-central@5142bbd4da12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, jgilbert
bugs742781
milestone19.0a1
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
Bug 742781 - Implement WEBGL_debug_renderer_info extension - r=bz,jgilbert
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLExtensionDebugRendererInfo.cpp
content/canvas/src/WebGLExtensions.h
dom/bindings/Bindings.conf
dom/webidl/WebGLRenderingContext.webidl
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -48,16 +48,17 @@ CPPSRCS += \
 	WebGLContextUtils.cpp \
 	WebGLContextReporter.cpp \
 	WebGLContextValidate.cpp \
 	WebGLElementArrayCache.cpp \
 	WebGLExtensionBase.cpp \
 	WebGLExtensionCompressedTextureATC.cpp \
 	WebGLExtensionCompressedTexturePVRTC.cpp \
 	WebGLExtensionCompressedTextureS3TC.cpp \
+	WebGLExtensionDebugRendererInfo.cpp \
 	WebGLExtensionDepthTexture.cpp \
 	WebGLExtensionLoseContext.cpp \
 	WebGLExtensionStandardDerivatives.cpp \
 	WebGLExtensionTextureFilterAnisotropic.cpp \
 	WebGLExtensionTextureFloat.cpp \
 	WebGLFramebuffer.cpp \
 	WebGLProgram.cpp \
 	WebGLRenderbuffer.cpp \
@@ -66,16 +67,20 @@ CPPSRCS += \
 	WebGLTexelConversions.cpp \
 	WebGLTexture.cpp \
 	WebGLUniformLocation.cpp \
 	$(NULL)
 
 DEFINES += -DUSE_ANGLE
 USE_ANGLE=1
 
+LOCAL_INCLUDES += \
+	-I$(topsrcdir)/js/xpconnect/wrappers \
+	$(NULL)
+
 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
@@ -2,16 +2,17 @@
 /* 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"
 #include "WebGLContextUtils.h"
 
+#include "AccessCheck.h"
 #include "nsIConsoleService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsError.h"
 #include "nsIGfxInfo.h"
 
@@ -943,17 +944,17 @@ WebGLContext::MozGetUnderlyingParamStrin
 
     default:
         return NS_ERROR_INVALID_ARG;
     }
 
     return NS_OK;
 }
 
-bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
+bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
 {
     if (mDisableExtensions) {
         return false;
     }
 
     switch (ext) {
         case OES_standard_derivatives:
         case WEBGL_lose_context:
@@ -993,16 +994,18 @@ bool WebGLContext::IsExtensionSupported(
                      gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil))
             {
                 return true;
             }
             else
             {
                 return false;
             }
+        case WEBGL_debug_renderer_info:
+            return xpc::AccessCheck::isChrome(js::GetContextCompartment(cx));
         default:
             MOZ_ASSERT(false, "should not get there.");
     }
 
     MOZ_ASSERT(false, "should not get there.");
     return false;
 }
 
@@ -1046,27 +1049,31 @@ WebGLContext::GetExtension(JSContext *cx
     else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc"))
     {
         ext = WEBGL_compressed_texture_atc;
     }
     else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc"))
     {
         ext = WEBGL_compressed_texture_pvrtc;
     }
+    else if (CompareWebGLExtensionName(name, "WEBGL_debug_renderer_info"))
+    {
+        ext = WEBGL_debug_renderer_info;
+    }
     else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture"))
     {
         ext = WEBGL_depth_texture;
     }
 
     if (ext == WebGLExtensionID_unknown_extension) {
       return nullptr;
     }
 
     // step 2: check if the extension is supported
-    if (!IsExtensionSupported(ext)) {
+    if (!IsExtensionSupported(cx, ext)) {
         return nullptr;
     }
 
     // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
     if (!IsExtensionEnabled(ext)) {
         WebGLExtensionBase *obj = nullptr;
         switch (ext) {
             case OES_standard_derivatives:
@@ -1082,16 +1089,19 @@ WebGLContext::GetExtension(JSContext *cx
                 obj = new WebGLExtensionCompressedTextureS3TC(this);
                 break;
             case WEBGL_compressed_texture_atc:
                 obj = new WebGLExtensionCompressedTextureATC(this);
                 break;
             case WEBGL_compressed_texture_pvrtc:
                 obj = new WebGLExtensionCompressedTexturePVRTC(this);
                 break;
+            case WEBGL_debug_renderer_info:
+                obj = new WebGLExtensionDebugRendererInfo(this);
+                break;
             case WEBGL_depth_texture:
                 obj = new WebGLExtensionDepthTexture(this);
                 break;
             case OES_texture_float:
                 obj = new WebGLExtensionTextureFloat(this);
                 break;
             default:
                 MOZ_ASSERT(false, "should not get there.");
@@ -1347,39 +1357,41 @@ WebGLContext::ForceLoseContext()
 
 void
 WebGLContext::ForceRestoreContext()
 {
     mContextStatus = ContextLostAwaitingRestore;
 }
 
 void
-WebGLContext::GetSupportedExtensions(Nullable< nsTArray<nsString> > &retval)
+WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval)
 {
     retval.SetNull();
     if (!IsContextStable())
         return;
 
     nsTArray<nsString>& arr = retval.SetValue();
 
-    if (IsExtensionSupported(OES_texture_float))
+    if (IsExtensionSupported(cx, OES_texture_float))
         arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
-    if (IsExtensionSupported(OES_standard_derivatives))
+    if (IsExtensionSupported(cx, OES_standard_derivatives))
         arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives"));
-    if (IsExtensionSupported(EXT_texture_filter_anisotropic))
+    if (IsExtensionSupported(cx, EXT_texture_filter_anisotropic))
         arr.AppendElement(NS_LITERAL_STRING("EXT_texture_filter_anisotropic"));
-    if (IsExtensionSupported(WEBGL_lose_context))
+    if (IsExtensionSupported(cx, WEBGL_lose_context))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
-    if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
+    if (IsExtensionSupported(cx, WEBGL_compressed_texture_s3tc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
-    if (IsExtensionSupported(WEBGL_compressed_texture_atc))
+    if (IsExtensionSupported(cx, WEBGL_compressed_texture_atc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
-    if (IsExtensionSupported(WEBGL_compressed_texture_pvrtc))
+    if (IsExtensionSupported(cx, WEBGL_compressed_texture_pvrtc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
-    if (IsExtensionSupported(WEBGL_depth_texture))
+    if (IsExtensionSupported(cx, WEBGL_debug_renderer_info))
+        arr.AppendElement(NS_LITERAL_STRING("WEBGL_debug_renderer_info"));
+    if (IsExtensionSupported(cx, WEBGL_depth_texture))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
 }
 
 //
 // XPCOM goop
 //
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -482,17 +482,19 @@ class WebGLContext :
     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
+        BROWSER_DEFAULT_WEBGL = 0x9244,
+        UNMASKED_VENDOR_WEBGL = 0x9245,
+        UNMASKED_RENDERER_WEBGL = 0x9246
     };
 
 public:
     WebGLContext();
     virtual ~WebGLContext();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
@@ -637,18 +639,18 @@ public:
     WebGLsizei DrawingBufferHeight() const {
         if (!IsContextStable())
             return 0;
         return mHeight;
     }
         
     JSObject *GetContextAttributes(ErrorResult &rv);
     bool IsContextLost() const { return !IsContextStable(); }
-    void GetSupportedExtensions(dom::Nullable< nsTArray<nsString> > &retval);
-    JSObject* GetExtension(JSContext* ctx, const nsAString& aName, ErrorResult& rv);
+    void GetSupportedExtensions(JSContext *cx, dom::Nullable< nsTArray<nsString> > &retval);
+    JSObject* GetExtension(JSContext* cx, const nsAString& aName, ErrorResult& rv);
     void ActiveTexture(WebGLenum texture);
     void AttachShader(WebGLProgram* program, WebGLShader* shader);
     void BindAttribLocation(WebGLProgram* program, WebGLuint location,
                             const nsAString& name);
     void BindBuffer(WebGLenum target, WebGLBuffer* buf);
     void BindFramebuffer(WebGLenum target, WebGLFramebuffer* wfb);
     void BindRenderbuffer(WebGLenum target, WebGLRenderbuffer* wrb);
     void BindTexture(WebGLenum target, WebGLTexture *tex);
@@ -1182,33 +1184,34 @@ protected:
         // The context is lost, an event has been sent to the script, and the
         // script correctly handled the event. We are waiting for the context to
         // be restored.
         ContextLostAwaitingRestore
     };
 
     // extensions
     enum WebGLExtensionID {
-        OES_texture_float,
+        EXT_texture_filter_anisotropic,
         OES_standard_derivatives,
-        EXT_texture_filter_anisotropic,
-        WEBGL_lose_context,
-        WEBGL_compressed_texture_s3tc,
+        OES_texture_float,
         WEBGL_compressed_texture_atc,
         WEBGL_compressed_texture_pvrtc,
+        WEBGL_compressed_texture_s3tc,
+        WEBGL_debug_renderer_info,
         WEBGL_depth_texture,
+        WEBGL_lose_context,
         WebGLExtensionID_unknown_extension
     };
     nsTArray<nsRefPtr<WebGLExtensionBase> > mExtensions;
 
     // returns true if the extension has been enabled by calling getExtension.
     bool IsExtensionEnabled(WebGLExtensionID ext) const;
 
-    // returns true if the extension is supported (as returned by getSupportedExtensions)
-    bool IsExtensionSupported(WebGLExtensionID ext) const;
+    // returns true if the extension is supported for this JSContext (this decides what getSupportedExtensions exposes)
+    bool IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const;
 
     nsTArray<WebGLenum> mCompressedTextureFormats;
 
     bool InitAndValidateGL();
     bool ValidateBuffers(int32_t *maxAllowedCount, const char *info);
     bool ValidateCapabilityEnum(WebGLenum cap, const char *info);
     bool ValidateBlendEquationEnum(WebGLenum cap, const char *info);
     bool ValidateBlendFuncDstEnum(WebGLenum mode, const char *info);
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1897,16 +1897,36 @@ WebGLContext::GetParameter(JSContext* cx
             return StringValue(cx, "Mozilla", rv);
         case LOCAL_GL_RENDERER:
             return StringValue(cx, "Mozilla", rv);
         case LOCAL_GL_VERSION:
             return StringValue(cx, "WebGL 1.0", rv);
         case LOCAL_GL_SHADING_LANGUAGE_VERSION:
             return StringValue(cx, "WebGL GLSL ES 1.0", rv);
 
+        // Privileged string params exposed by WEBGL_debug_renderer_info:
+        case UNMASKED_VENDOR_WEBGL:
+        case UNMASKED_RENDERER_WEBGL:
+        {
+            // The privilege check is done in WebGLContext::IsExtensionSupported.
+            // So here we just have to check that the extension is enabled.
+            if (!IsExtensionEnabled(WEBGL_debug_renderer_info)) {
+                ErrorInvalidEnumInfo("getParameter: parameter", pname);
+                return JS::NullValue();
+            }
+            GLenum glstringname = LOCAL_GL_NONE;
+            if (pname == UNMASKED_VENDOR_WEBGL) {
+                glstringname = LOCAL_GL_VENDOR;
+            } else if (pname == UNMASKED_RENDERER_WEBGL) {
+                glstringname = LOCAL_GL_RENDERER;
+            }
+            const char* string = reinterpret_cast<const char*>(gl->fGetString(glstringname));
+            return StringValue(cx, string, rv);
+        }
+
         //
         // Single-value params
         //
 
         // unsigned int
         case LOCAL_GL_CULL_FACE_MODE:
         case LOCAL_GL_FRONT_FACE:
         case LOCAL_GL_ACTIVE_TEXTURE:
@@ -2006,17 +2026,17 @@ WebGLContext::GetParameter(JSContext* cx
 
 // float
         case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
             if (IsExtensionEnabled(EXT_texture_filter_anisotropic)) {
                 GLfloat f = 0.f;
                 gl->fGetFloatv(pname, &f);
                 return JS::DoubleValue(f);
             } else {
-                ErrorInvalidEnum("getParameter: parameter", pname);
+                ErrorInvalidEnumInfo("getParameter: parameter", pname);
                 return JS::NullValue();
             }
         case LOCAL_GL_DEPTH_CLEAR_VALUE:
         case LOCAL_GL_LINE_WIDTH:
         case LOCAL_GL_POLYGON_OFFSET_FACTOR:
         case LOCAL_GL_POLYGON_OFFSET_UNITS:
         case LOCAL_GL_SAMPLE_COVERAGE_VALUE:
         {
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLExtensionDebugRendererInfo.cpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+
+using namespace mozilla;
+
+WebGLExtensionDebugRendererInfo::WebGLExtensionDebugRendererInfo(WebGLContext* context)
+    : WebGLExtensionBase(context)
+{
+}
+
+WebGLExtensionDebugRendererInfo::~WebGLExtensionDebugRendererInfo()
+{
+}
+
+IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo)
--- a/content/canvas/src/WebGLExtensions.h
+++ b/content/canvas/src/WebGLExtensions.h
@@ -61,16 +61,26 @@ class WebGLExtensionCompressedTextureS3T
 {
 public:
     WebGLExtensionCompressedTextureS3TC(WebGLContext*);
     virtual ~WebGLExtensionCompressedTextureS3TC();
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
+class WebGLExtensionDebugRendererInfo
+    : public WebGLExtensionBase
+{
+public:
+    WebGLExtensionDebugRendererInfo(WebGLContext*);
+    virtual ~WebGLExtensionDebugRendererInfo();
+
+    DECL_WEBGL_EXTENSION_GOOP
+};
+
 class WebGLExtensionDepthTexture
     : public WebGLExtensionBase
 {
 public:
     WebGLExtensionDepthTexture(WebGLContext*);
     virtual ~WebGLExtensionDepthTexture();
 
     DECL_WEBGL_EXTENSION_GOOP
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -381,16 +381,21 @@ DOMInterfaces = {
    'headerFile': 'WebGLExtensions.h'
 },
 
 'WebGLExtensionDepthTexture': {
    'nativeType': 'mozilla::WebGLExtensionDepthTexture',
    'headerFile': 'WebGLExtensions.h'
 },
 
+'WebGLExtensionDebugRendererInfo': {
+   'nativeType': 'mozilla::WebGLExtensionDebugRendererInfo',
+   'headerFile': 'WebGLExtensions.h'
+},
+
 'WebGLExtensionLoseContext': {
    'nativeType': 'mozilla::WebGLExtensionLoseContext',
    'headerFile': 'WebGLExtensions.h'
 },
 
 'WebGLExtensionStandardDerivatives': {
    'nativeType': 'mozilla::WebGLExtensionStandardDerivatives',
    'headerFile': 'WebGLExtensions.h'
@@ -421,17 +426,17 @@ DOMInterfaces = {
    'headerFile': 'WebGLContext.h'
 },
 
 'WebGLRenderingContext': {
   'nativeType': 'mozilla::WebGLContext',
   'headerFile': 'WebGLContext.h',
   'resultNotAddRefed': [ 'canvas', 'getContextAttributes', 'getExtension',
                          'getAttachedShaders' ],
-  'implicitJSContext': [ 'texImage2D', 'texSubImage2D' ],
+  'implicitJSContext': [ 'texImage2D', 'texSubImage2D', 'getSupportedExtensions' ],
 },
 
 'WebGLShader': {
    'nativeType': 'mozilla::WebGLShader',
    'headerFile': 'WebGLContext.h'
 },
 
 'WebGLShaderPrecisionFormat': {
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -772,34 +772,16 @@ interface WebGLContextEvent : Event {
 /*dictionary WebGLContextEventInit : EventInit {
     DOMString statusMessage;
     };*/
 
 
 // specific extension interfaces
 
 [NoInterfaceObject]
-interface WebGLExtensionStandardDerivatives {
-    const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
-};
-
-[NoInterfaceObject]
-interface WebGLExtensionLoseContext {
-    void loseContext();
-    void restoreContext();
-};
-
-[NoInterfaceObject]
-interface WebGLExtensionTextureFilterAnisotropic
-{
-    const GLenum TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
-    const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
-};
-
-[NoInterfaceObject]
 interface WebGLExtensionCompressedTextureS3TC
 {
     const GLenum COMPRESSED_RGB_S3TC_DXT1_EXT  = 0x83F0;
     const GLenum COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
     const GLenum COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
     const GLenum COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
 };
 
@@ -816,17 +798,42 @@ interface WebGLExtensionCompressedTextur
 {
     const GLenum COMPRESSED_RGB_PVRTC_4BPPV1  = 0x8C00;
     const GLenum COMPRESSED_RGB_PVRTC_2BPPV1  = 0x8C01;
     const GLenum COMPRESSED_RGBA_PVRTC_4BPPV1 = 0x8C02;
     const GLenum COMPRESSED_RGBA_PVRTC_2BPPV1 = 0x8C03;
 };
 
 [NoInterfaceObject]
+interface WebGLExtensionDebugRendererInfo
+{
+    const GLenum UNMASKED_VENDOR_WEBGL        = 0x9245;
+    const GLenum UNMASKED_RENDERER_WEBGL      = 0x9246;
+};
+
+[NoInterfaceObject]
 interface WebGLExtensionDepthTexture
 {
     const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 };
 
 [NoInterfaceObject]
+interface WebGLExtensionLoseContext {
+    void loseContext();
+    void restoreContext();
+};
+
+[NoInterfaceObject]
+interface WebGLExtensionTextureFilterAnisotropic
+{
+    const GLenum TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
+    const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
+};
+
+[NoInterfaceObject]
+interface WebGLExtensionStandardDerivatives {
+    const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
+};
+
+[NoInterfaceObject]
 interface WebGLExtensionTextureFloat
 {
 };