Bug 742781 - Implement WEBGL_debug_renderer_info extension - r=bz,jgilbert, a=akeybl
authorBenoit Jacob <bjacob@mozilla.com>
Wed, 17 Oct 2012 15:11:51 -0400
changeset 113944 b77766bbadc13340a540aedc4ca481887d032f41
parent 113943 edf686a532b7d7e5e55dfee3b24cc40deba749c7
child 113945 76d096e915c76e09403376d197381ddb4d72034f
push id2570
push userryanvm@gmail.com
push dateSat, 03 Nov 2012 15:51:11 +0000
treeherdermozilla-aurora@2a2c5e00b5f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, jgilbert, akeybl
bugs742781
milestone18.0a2
Bug 742781 - Implement WEBGL_debug_renderer_info extension - r=bz,jgilbert, a=akeybl
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
@@ -49,32 +49,37 @@ 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 \
 	WebGLShader.cpp \
 	WebGLTexelConversions.cpp \
 	WebGLTexture.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"
 
@@ -945,17 +946,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:
@@ -995,16 +996,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;
 }
 
@@ -1048,27 +1051,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:
@@ -1084,16 +1091,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.");
@@ -1475,33 +1485,35 @@ WebGLActiveInfo::GetType(WebGLenum *aTyp
 NS_IMETHODIMP
 WebGLActiveInfo::GetName(nsAString & aName)
 {
     aName = mName;
     return NS_OK;
 }
 
 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"));
 }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -469,17 +469,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
 
@@ -629,18 +631,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);
@@ -1166,33 +1168,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
@@ -362,16 +362,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'
@@ -402,17 +407,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
@@ -764,31 +764,16 @@ interface WebGLContextEvent : Event {
 // EventInit is defined in the DOM4 specification.
 /*dictionary WebGLContextEventInit : EventInit {
     DOMString statusMessage;
     };*/
 
 
 // specific extension interfaces
 
-interface WebGLExtensionStandardDerivatives {
-    const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
-};
-
-interface WebGLExtensionLoseContext {
-    void loseContext();
-    void restoreContext();
-};
-
-interface WebGLExtensionTextureFilterAnisotropic
-{
-    const GLenum TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
-    const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
-};
-
 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;
 };
 
@@ -802,16 +787,37 @@ interface WebGLExtensionCompressedTextur
 interface WebGLExtensionCompressedTexturePVRTC
 {
     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;
 };
 
+interface WebGLExtensionDebugRendererInfo
+{
+    const GLenum UNMASKED_VENDOR_WEBGL        = 0x9245;
+    const GLenum UNMASKED_RENDERER_WEBGL      = 0x9246;
+};
+
 interface WebGLExtensionDepthTexture
 {
     const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 };
 
+interface WebGLExtensionLoseContext {
+    void loseContext();
+    void restoreContext();
+};
+
+interface WebGLExtensionTextureFilterAnisotropic
+{
+    const GLenum TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
+    const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
+};
+
+interface WebGLExtensionStandardDerivatives {
+    const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
+};
+
 interface WebGLExtensionTextureFloat
 {
 };