Web Inspector: provide way for ShaderPrograms to be enabled/disabled
authorwebkit@devinrousso.com <webkit@devinrousso.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 Aug 2017 18:08:50 +0000 (18:08 +0000)
committerwebkit@devinrousso.com <webkit@devinrousso.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 Aug 2017 18:08:50 +0000 (18:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175400

Reviewed by Matt Baker.

Source/JavaScriptCore:

* inspector/protocol/Canvas.json:
Add `setShaderProgramDisabled` command that sets the `disabled` flag on the given shader
program to the supplied boolean value. If this value is true, calls to `drawArrays` and
`drawElements` when that program is in use will have no effect.

Source/WebCore:

Test: inspector/canvas/setShaderProgramDisabled.html

* inspector/InspectorShaderProgram.h:
(WebCore::InspectorShaderProgram::disabled):
(WebCore::InspectorShaderProgram::setDisabled):

* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::drawArrays):
(WebCore::WebGLRenderingContextBase::drawElements):
If the current program is disabled, return early. This will prevent the current shader
program from drawing anything to the canvas.

* inspector/InspectorCanvasAgent.h:
* inspector/InspectorCanvasAgent.cpp:
(WebCore::InspectorCanvasAgent::setShaderProgramDisabled):
(WebCore::InspectorCanvasAgent::isShaderProgramDisabled):
* inspector/InspectorInstrumentation.h:
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::isShaderProgramDisabled):
(WebCore::InspectorInstrumentation::isShaderProgramDisabledImpl):

Source/WebInspectorUI:

Adds a status element to ShaderProgramTreeElement that, when clicked, will toggle the
disabled state of the corresponding ShaderProgram. Disabled shader programs will not draw
anything to the context.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Main.html:

* UserInterface/Models/ShaderProgram.js:
(WI.ShaderProgram):
(WI.ShaderProgram.prototype.get disabled):
(WI.ShaderProgram.prototype.toggleDisabled):

* UserInterface/Views/ShaderProgramTreeElement.js:
(WI.ShaderProgramTreeElement):
(WI.ShaderProgramTreeElement.prototype.selectOnMouseDown):
(WI.ShaderProgramTreeElement.prototype._disabledImageElementClicked):
* UserInterface/Views/ShaderProgramTreeElement.css: Added.
(.item.shader-program .status > img):
(.item.shader-program:not(:hover, .selected, .disabled) .status > img):
(.tree-outline:matches(:focus, .force-focus) .item.shader-program.selected .status > img):
(.item.shader-program.disabled > *):

LayoutTests:

* inspector/canvas/setShaderProgramDisabled-expected.txt: Added.
* inspector/canvas/setShaderProgramDisabled.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221025 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/canvas/setShaderProgramDisabled-expected.txt [new file with mode: 0644]
LayoutTests/inspector/canvas/setShaderProgramDisabled.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/Canvas.json
Source/WebCore/ChangeLog
Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
Source/WebCore/inspector/InspectorCanvasAgent.cpp
Source/WebCore/inspector/InspectorCanvasAgent.h
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/InspectorShaderProgram.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Models/ShaderProgram.js
Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.css [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.js

index 58f6fc8..68e0842 100644 (file)
@@ -1,3 +1,13 @@
+2017-08-22  Devin Rousso  <webkit@devinrousso.com>
+
+        Web Inspector: provide way for ShaderPrograms to be enabled/disabled
+        https://bugs.webkit.org/show_bug.cgi?id=175400
+
+        Reviewed by Matt Baker.
+
+        * inspector/canvas/setShaderProgramDisabled-expected.txt: Added.
+        * inspector/canvas/setShaderProgramDisabled.html: Added.
+
 2017-08-22  Youenn Fablet  <youenn@apple.com>
 
         [Cache API] Add support for overwriting responses with put on an existing record
diff --git a/LayoutTests/inspector/canvas/setShaderProgramDisabled-expected.txt b/LayoutTests/inspector/canvas/setShaderProgramDisabled-expected.txt
new file mode 100644 (file)
index 0000000..5626b32
--- /dev/null
@@ -0,0 +1,20 @@
+Test disabling and re-enabling of shader programs.
+
+
+== Running test suite: Canvas.setShaderProgramDisabled
+-- Running test case: Canvas.setShaderProgramDisabled.disabledDrawArrays
+PASS: Disabling a shader program should prevent it from drawing.
+
+-- Running test case: Canvas.setShaderProgramDisabled.disabledDrawElements
+PASS: Disabling a shader program should prevent it from drawing.
+
+-- Running test case: Canvas.setShaderProgramDisabled.reenabledDrawArrays
+PASS: Re-enabling a shader program should allow it to draw.
+
+-- Running test case: Canvas.setShaderProgramDisabled.reenabledDrawElements
+PASS: Re-enabling a shader program should allow it to draw.
+
+-- Running test case: Canvas.setShaderProgramDisabled.invalidProgramId
+PASS: Should produce an error.
+Error: No shader program for given identifier.
+
diff --git a/LayoutTests/inspector/canvas/setShaderProgramDisabled.html b/LayoutTests/inspector/canvas/setShaderProgramDisabled.html
new file mode 100644 (file)
index 0000000..657a3ab
--- /dev/null
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="resources/shaderProgram-utilities.js"></script>
+<script id="vertex-shader" type="x-shader/x-vertex">
+    attribute vec3 position;
+    void main(void) {
+        gl_Position = vec4(position, 1.0);
+    }
+</script>
+<script id="fragment-shader" type="x-shader/x-fragment">
+    precision mediump float;
+
+    void main(void) {
+        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+    }
+</script>
+<script>
+function load() {
+    createProgram("webgl");
+    linkProgram("vertex-shader", "fragment-shader");
+    context.useProgram(program);
+
+    clearContext();
+
+    runTest();
+}
+
+function clearContext() {
+    context.clearColor(0.0, 0.0, 0.0, 1.0);
+    context.clear(context.COLOR_BUFFER_BIT);
+}
+
+function drawArrays() {
+    clearContext();
+
+    let vertexes = [
+        -0.5,  0.5,  0.0,
+        -0.5, -0.5,  0.0,
+         0.5, -0.5,  0.0, 
+    ];
+    let vertexBuffer = context.createBuffer();
+    context.bindBuffer(context.ARRAY_BUFFER, vertexBuffer);
+    context.bufferData(context.ARRAY_BUFFER, new Float32Array(vertexes), context.STATIC_DRAW);
+
+    let position = context.getAttribLocation(program, "position");
+    context.vertexAttribPointer(position, 3, context.FLOAT, false, 0, 0); 
+    context.enableVertexAttribArray(position);
+
+    context.drawArrays(context.TRIANGLES, 0, 3);
+}
+
+function drawElements() {
+    clearContext();
+
+    let vertexes = [
+         0.5,  0.5,  0.0,
+        -0.5, -0.5,  0.0,
+         0.5, -0.5,  0.0, 
+    ];
+    let vertexBuffer = context.createBuffer();
+    context.bindBuffer(context.ARRAY_BUFFER, vertexBuffer);
+    context.bufferData(context.ARRAY_BUFFER, new Float32Array(vertexes), context.STATIC_DRAW);
+
+    let indexes = [0, 1, 2];
+    let indexBuffer = context.createBuffer();
+    context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indexBuffer);
+    context.bufferData(context.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexes), context.STATIC_DRAW);
+
+    let position = context.getAttribLocation(program, "position");
+    context.vertexAttribPointer(position, 3, context.FLOAT, false, 0, 0); 
+    context.enableVertexAttribArray(position);
+
+    context.drawElements(context.TRIANGLES, indexes.length, context.UNSIGNED_SHORT, 0);
+}
+
+function test() {
+    let suite = InspectorTest.createAsyncSuite("Canvas.setShaderProgramDisabled");
+
+    let shaderProgram = WI.canvasManager.shaderPrograms[0];
+    let originalContent = null;
+
+    function validTest({name, disabled, evaluateString}) {
+        suite.addTestCase({
+            name,
+            test(resolve, reject) {
+                CanvasAgent.setShaderProgramDisabled(shaderProgram.identifier, disabled, (error) => {
+                    if (error) {
+                        reject(error);
+                        return;
+                    }
+
+                    InspectorTest.evaluateInPage(evaluateString, (error) => {
+                        if (error) {
+                            reject(error);
+                            return;
+                        }
+
+                        CanvasAgent.requestContent(shaderProgram.canvas.identifier)
+                        .then(({content}) => {
+                            if (disabled)
+                                InspectorTest.expectEqual(content, originalContent, "Disabling a shader program should prevent it from drawing.");
+                            else
+                                InspectorTest.expectNotEqual(content, originalContent, "Re-enabling a shader program should allow it to draw.");
+                        })
+                        .then(resolve, reject);
+                    });
+                });
+            }
+        });
+    }
+
+    validTest({
+        name: "Canvas.setShaderProgramDisabled.disabledDrawArrays",
+        disabled: true,
+        evaluateString: `drawArrays()`,
+    });
+
+    validTest({
+        name: "Canvas.setShaderProgramDisabled.disabledDrawElements",
+        disabled: true,
+        evaluateString: `drawElements()`,
+    });
+
+    validTest({
+        name: "Canvas.setShaderProgramDisabled.reenabledDrawArrays",
+        disabled: false,
+        evaluateString: `drawArrays()`,
+    });
+
+    validTest({
+        name: "Canvas.setShaderProgramDisabled.reenabledDrawElements",
+        disabled: false,
+        evaluateString: `drawElements()`,
+    });
+
+    suite.addTestCase({
+        name: "Canvas.setShaderProgramDisabled.invalidProgramId",
+        description: "Invalid program identifiers should cause an error.",
+        test(resolve, reject) {
+            const programId = "INVALID_PROGRAM_ID";
+            const disabled = false;
+            CanvasAgent.setShaderProgramDisabled(programId, disabled, (error) => {
+                InspectorTest.expectThat(error, "Should produce an error.");
+                InspectorTest.log("Error: " + error);
+                resolve();
+            });
+        }
+    });
+
+    CanvasAgent.requestContent(shaderProgram.canvas.identifier, (error, content) => {
+        originalContent = content;
+
+        suite.runTestCasesAndFinish();
+    });
+}
+</script>
+</head>
+<body onload="load()">
+    <p>Test disabling and re-enabling of shader programs.</p>
+</body>
+</html>
index 7634e19..9b949c9 100644 (file)
@@ -1,3 +1,15 @@
+2017-08-22  Devin Rousso  <webkit@devinrousso.com>
+
+        Web Inspector: provide way for ShaderPrograms to be enabled/disabled
+        https://bugs.webkit.org/show_bug.cgi?id=175400
+
+        Reviewed by Matt Baker.
+
+        * inspector/protocol/Canvas.json:
+        Add `setShaderProgramDisabled` command that sets the `disabled` flag on the given shader
+        program to the supplied boolean value. If this value is true, calls to `drawArrays` and
+        `drawElements` when that program is in use will have no effect.
+
 2017-08-22  Keith Miller  <keith_miller@apple.com>
 
         Unriviewed, fix windows build... for realz.
index b01b833..64c310a 100644 (file)
                 { "name": "shaderType", "$ref": "ShaderType" },
                 { "name": "source", "type": "string" }
             ]
+        },
+        {
+            "name": "setShaderProgramDisabled",
+            "description": "Enable/disable the visibility of the given shader program.",
+            "parameters": [
+                { "name": "programId", "$ref": "ProgramId" },
+                { "name": "disabled", "type": "boolean" }
+            ]
         }
     ],
     "events": [
index 0fa5318..4372047 100644 (file)
@@ -1,3 +1,31 @@
+2017-08-22  Devin Rousso  <webkit@devinrousso.com>
+
+        Web Inspector: provide way for ShaderPrograms to be enabled/disabled
+        https://bugs.webkit.org/show_bug.cgi?id=175400
+
+        Reviewed by Matt Baker.
+
+        Test: inspector/canvas/setShaderProgramDisabled.html
+
+        * inspector/InspectorShaderProgram.h:
+        (WebCore::InspectorShaderProgram::disabled):
+        (WebCore::InspectorShaderProgram::setDisabled):
+
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::drawArrays):
+        (WebCore::WebGLRenderingContextBase::drawElements):
+        If the current program is disabled, return early. This will prevent the current shader
+        program from drawing anything to the canvas.
+
+        * inspector/InspectorCanvasAgent.h:
+        * inspector/InspectorCanvasAgent.cpp:
+        (WebCore::InspectorCanvasAgent::setShaderProgramDisabled):
+        (WebCore::InspectorCanvasAgent::isShaderProgramDisabled):
+        * inspector/InspectorInstrumentation.h:
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::isShaderProgramDisabled):
+        (WebCore::InspectorInstrumentation::isShaderProgramDisabledImpl):
+
 2017-08-22  Youenn Fablet  <youenn@apple.com>
 
         [Cache API] Add support for overwriting responses with put on an existing record
index 1696428..5b72ea1 100644 (file)
@@ -2003,6 +2003,9 @@ void WebGLRenderingContextBase::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsiz
     if (!validateDrawArrays("drawArrays", mode, first, count, 0))
         return;
 
+    if (m_currentProgram && InspectorInstrumentation::isShaderProgramDisabled(*this, *m_currentProgram))
+        return;
+
     clearIfComposited();
 
     bool vertexAttrib0Simulated = false;
@@ -2027,6 +2030,9 @@ void WebGLRenderingContextBase::drawElements(GC3Denum mode, GC3Dsizei count, GC3
     if (!validateDrawElements("drawElements", mode, count, type, offset, numElements, 0))
         return;
 
+    if (m_currentProgram && InspectorInstrumentation::isShaderProgramDisabled(*this, *m_currentProgram))
+        return;
+
     clearIfComposited();
 
     bool vertexAttrib0Simulated = false;
index 2b0ee71..1bba806 100644 (file)
@@ -324,6 +324,21 @@ void InspectorCanvasAgent::updateShader(ErrorString& errorString, const String&
 #endif
 }
 
+void InspectorCanvasAgent::setShaderProgramDisabled(ErrorString& errorString, const String& programId, bool disabled)
+{
+#if ENABLE(WEBGL)
+    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
+    if (!inspectorProgram)
+        return;
+
+    inspectorProgram->setDisabled(disabled);
+#else
+    UNUSED_PARAM(programId);
+    UNUSED_PARAM(disabled);
+    errorString = ASCIILiteral("WebGL is not supported.");
+#endif
+}
+
 void InspectorCanvasAgent::frameNavigated(Frame& frame)
 {
     if (frame.isMainFrame()) {
@@ -505,6 +520,15 @@ void InspectorCanvasAgent::willDeleteProgram(WebGLProgram& program)
     if (m_enabled)
         m_frontendDispatcher->programDeleted(identifier);
 }
+
+bool InspectorCanvasAgent::isShaderProgramDisabled(WebGLProgram& program)
+{
+    auto* inspectorProgram = findInspectorProgram(program);
+    if (!inspectorProgram)
+        return false;
+
+    return inspectorProgram->disabled();
+}
 #endif
 
 void InspectorCanvasAgent::canvasDestroyedTimerFired()
index aa10042..427d243 100644 (file)
@@ -77,6 +77,7 @@ public:
     void cancelRecording(ErrorString&, const String& canvasId) override;
     void requestShaderSource(ErrorString&, const String& programId, const String& shaderType, String*) override;
     void updateShader(ErrorString&, const String& programId, const String& shaderType, const String& source) override;
+    void setShaderProgramDisabled(ErrorString&, const String& programId, bool disabled) override;
 
     // InspectorInstrumentation
     void frameNavigated(Frame&);
@@ -89,6 +90,7 @@ public:
 #if ENABLE(WEBGL)
     void didCreateProgram(WebGLRenderingContextBase&, WebGLProgram&);
     void willDeleteProgram(WebGLProgram&);
+    bool isShaderProgramDisabled(WebGLProgram&);
 #endif
 
     // CanvasObserver
index 13569b5..11662c1 100644 (file)
@@ -1048,6 +1048,13 @@ void InspectorInstrumentation::willDeleteProgramImpl(InstrumentingAgents& instru
     if (InspectorCanvasAgent* canvasAgent = instrumentingAgents.inspectorCanvasAgent())
         canvasAgent->willDeleteProgram(program);
 }
+
+bool InspectorInstrumentation::isShaderProgramDisabledImpl(InstrumentingAgents& instrumentingAgents, WebGLProgram& program)
+{
+    if (InspectorCanvasAgent* canvasAgent = instrumentingAgents.inspectorCanvasAgent())
+        return canvasAgent->isShaderProgramDisabled(program);
+    return false;
+}
 #endif
 
 #if ENABLE(RESOURCE_USAGE)
index d94a2b2..250fa84 100644 (file)
@@ -248,6 +248,7 @@ public:
 #if ENABLE(WEBGL)
     static void didCreateProgram(WebGLRenderingContextBase&, WebGLProgram&);
     static void willDeleteProgram(WebGLRenderingContextBase&, WebGLProgram&);
+    static bool isShaderProgramDisabled(WebGLRenderingContextBase&, WebGLProgram&);
 #endif
 
     static void networkStateChanged(Page&);
@@ -417,6 +418,7 @@ private:
 #if ENABLE(WEBGL)
     static void didCreateProgramImpl(InstrumentingAgents&, WebGLRenderingContextBase&, WebGLProgram&);
     static void willDeleteProgramImpl(InstrumentingAgents&, WebGLProgram&);
+    static bool isShaderProgramDisabledImpl(InstrumentingAgents&, WebGLProgram&);
 #endif
 
     static void layerTreeDidChangeImpl(InstrumentingAgents&);
@@ -1196,6 +1198,14 @@ inline void InspectorInstrumentation::willDeleteProgram(WebGLRenderingContextBas
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(context.canvas().document()))
         willDeleteProgramImpl(*instrumentingAgents, program);
 }
+
+inline bool InspectorInstrumentation::isShaderProgramDisabled(WebGLRenderingContextBase& context, WebGLProgram& program)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(context.canvas().document()))
+        return isShaderProgramDisabledImpl(*instrumentingAgents, program);
+    return false;
+}
 #endif
 
 inline void InspectorInstrumentation::networkStateChanged(Page& page)
index e368be6..6877f2f 100644 (file)
@@ -47,6 +47,9 @@ public:
     WebGLProgram& program() const { return m_program; }
     WebGLShader* shaderForType(const String&);
 
+    bool disabled() const { return m_disabled; }
+    void setDisabled(bool disabled) { m_disabled = disabled; }
+
     ~InspectorShaderProgram() { }
 
 private:
@@ -55,6 +58,8 @@ private:
     String m_identifier;
     WebGLProgram& m_program;
     InspectorCanvas& m_canvas;
+
+    bool m_disabled { false };
 };
 
 } // namespace WebCore
index 4a97ed0..8757088 100644 (file)
@@ -1,3 +1,32 @@
+2017-08-22  Devin Rousso  <webkit@devinrousso.com>
+
+        Web Inspector: provide way for ShaderPrograms to be enabled/disabled
+        https://bugs.webkit.org/show_bug.cgi?id=175400
+
+        Reviewed by Matt Baker.
+
+        Adds a status element to ShaderProgramTreeElement that, when clicked, will toggle the
+        disabled state of the corresponding ShaderProgram. Disabled shader programs will not draw
+        anything to the context.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Main.html:
+
+        * UserInterface/Models/ShaderProgram.js:
+        (WI.ShaderProgram):
+        (WI.ShaderProgram.prototype.get disabled):
+        (WI.ShaderProgram.prototype.toggleDisabled):
+
+        * UserInterface/Views/ShaderProgramTreeElement.js:
+        (WI.ShaderProgramTreeElement):
+        (WI.ShaderProgramTreeElement.prototype.selectOnMouseDown):
+        (WI.ShaderProgramTreeElement.prototype._disabledImageElementClicked):
+        * UserInterface/Views/ShaderProgramTreeElement.css: Added.
+        (.item.shader-program .status > img):
+        (.item.shader-program:not(:hover, .selected, .disabled) .status > img):
+        (.tree-outline:matches(:focus, .force-focus) .item.shader-program.selected .status > img):
+        (.item.shader-program.disabled > *):
+
 2017-08-21  Devin Rousso  <webkit@devinrousso.com>
 
         Web Inspector: Can't copy text from "View variable value" popover in Styles sidebar
index 9ba9ce6..2f8b638 100644 (file)
@@ -284,6 +284,7 @@ localizedStrings["Dimensions"] = "Dimensions";
 localizedStrings["Direction"] = "Direction";
 localizedStrings["Disable Breakpoint"] = "Disable Breakpoint";
 localizedStrings["Disable Breakpoints"] = "Disable Breakpoints";
+localizedStrings["Disable Program"] = "Disable Program";
 localizedStrings["Disable all breakpoints (%s)"] = "Disable all breakpoints (%s)";
 localizedStrings["Disable paint flashing"] = "Disable paint flashing";
 localizedStrings["Disabled"] = "Disabled";
@@ -346,6 +347,7 @@ localizedStrings["Element overlaps other compositing element"] = "Element overla
 localizedStrings["Elements"] = "Elements";
 localizedStrings["Enable Breakpoint"] = "Enable Breakpoint";
 localizedStrings["Enable Breakpoints"] = "Enable Breakpoints";
+localizedStrings["Enable Program"] = "Enable Program";
 localizedStrings["Enable all breakpoints (%s)"] = "Enable all breakpoints (%s)";
 localizedStrings["Enable breakpoints"] = "Enable breakpoints";
 localizedStrings["Enable paint flashing"] = "Enable paint flashing";
index 3bc5e58..32cba00 100644 (file)
     <link rel="stylesheet" href="Views/SearchSidebarPanel.css">
     <link rel="stylesheet" href="Views/SettingsTabContentView.css">
     <link rel="stylesheet" href="Views/ShaderProgramContentView.css">
+    <link rel="stylesheet" href="Views/ShaderProgramTreeElement.css">
     <link rel="stylesheet" href="Views/Sidebar.css">
     <link rel="stylesheet" href="Views/SidebarPanel.css">
     <link rel="stylesheet" href="Views/Slider.css">
index fdca588..f11a51d 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WI.ShaderProgram = class ShaderProgram extends WI.Object
+WI.ShaderProgram = class ShaderProgram
 {
     constructor(identifier, canvas)
     {
-        super();
-
         console.assert(identifier);
         console.assert(canvas instanceof WI.Canvas);
 
         this._identifier = identifier;
         this._canvas = canvas;
         this._uniqueDisplayNumber = canvas.nextShaderProgramDisplayNumber();
+        this._disabled = false;
     }
 
     // Public
 
     get identifier() { return this._identifier; }
     get canvas() { return this._canvas; }
+    get disabled() { return this._disabled; }
 
     get displayName()
     {
@@ -67,6 +67,18 @@ WI.ShaderProgram = class ShaderProgram extends WI.Object
         this._updateShader(CanvasAgent.ShaderType.Fragment, source);
     }
 
+    toggleDisabled(callback)
+    {
+        CanvasAgent.setShaderProgramDisabled(this._identifier, !this._disabled, (error) => {
+            console.assert(!error, error);
+            if (error)
+                return;
+
+            this._disabled = !this._disabled;
+            callback();
+        });
+    }
+
     // Private
 
     _requestShaderSource(shaderType, callback)
@@ -93,8 +105,3 @@ WI.ShaderProgram.ShaderType = {
     Fragment: "shader-type-fragment",
     Vertex: "shader-type-vertex",
 };
-
-WI.ShaderProgram.Event = {
-    ProgramLinked: "shader-program-program-linked",
-    ShaderCompiled: "shader-program-shader-compiled",
-};
diff --git a/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.css b/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.css
new file mode 100644 (file)
index 0000000..69b1db4
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.item.shader-program .status > img {
+    width: 18px;
+    margin-top: 2px;
+    content: url(../Images/Eye.svg);
+}
+
+.item.shader-program:not(:hover, .selected, .disabled) .status > img {
+    display: none;
+}
+
+.tree-outline:matches(:focus, .force-focus) .item.shader-program.selected .status > img {
+    filter: invert();
+}
+
+.item.shader-program.disabled > * {
+    opacity: 0.5;
+}
index 12da64a..dc9e08b 100644 (file)
@@ -31,5 +31,30 @@ WI.ShaderProgramTreeElement = class ShaderProgramTreeElement extends WI.GeneralT
 
         const subtitle = null;
         super("shader-program", shaderProgram.displayName, subtitle, shaderProgram);
+
+        this._disabledImageElement = document.createElement("img");
+        this._disabledImageElement.title = WI.UIString("Disable Program");
+        this._disabledImageElement.addEventListener("click", this._disabledImageElementClicked.bind(this));
+        this.status = this._disabledImageElement;
+    }
+
+    // Protected
+
+    selectOnMouseDown(event)
+    {
+        if (event.target.isSelfOrDescendant(this._statusElement))
+            return;
+
+        super.selectOnMouseDown(event);
+    }
+
+    // Private
+
+    _disabledImageElementClicked(event)
+    {
+        this.representedObject.toggleDisabled(() => {
+            this._listItemNode.classList.toggle("disabled", !!this.representedObject.disabled);
+            this._disabledImageElement.title = this.representedObject.disabled ? WI.UIString("Enable Program") : WI.UIString("Disable Program");
+        });
     }
 };