Unreviewed, rolling out r243356.
authorryanhaddad@apple.com <ryanhaddad@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Mar 2019 16:54:54 +0000 (16:54 +0000)
committerryanhaddad@apple.com <ryanhaddad@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Mar 2019 16:54:54 +0000 (16:54 +0000)
Causes assertion failures with WebGL layout tests on macOS and
iOS.

Reverted changeset:

"Web Inspector: Safari Canvas Inspector seems to show the
canvas being rendered twice per frame."
https://bugs.webkit.org/show_bug.cgi?id=196082
https://trac.webkit.org/changeset/243356

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

16 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/canvas/recording-2d.html
LayoutTests/inspector/canvas/recording-bitmaprenderer.html
LayoutTests/inspector/canvas/recording-html-2d.html
LayoutTests/inspector/canvas/recording-webgl.html
LayoutTests/inspector/canvas/setRecordingAutoCaptureFrameCount.html
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLCanvasElement.cpp
Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
Source/WebCore/html/canvas/WebGLRenderingContextBase.h
Source/WebCore/inspector/InspectorCanvas.cpp
Source/WebCore/inspector/InspectorCanvas.h
Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp
Source/WebCore/inspector/agents/InspectorCanvasAgent.h
Source/WebCore/platform/graphics/GraphicsContext3D.h
Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp

index db1c35c..4cc8858 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-22  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r243356.
+
+        Causes assertion failures with WebGL layout tests on macOS and
+        iOS.
+
+        Reverted changeset:
+
+        "Web Inspector: Safari Canvas Inspector seems to show the
+        canvas being rendered twice per frame."
+        https://bugs.webkit.org/show_bug.cgi?id=196082
+        https://trac.webkit.org/changeset/243356
+
 2019-03-22  Antti Koivisto  <antti@apple.com>
 
         Handle UI side hit testing for ScrollPositioningBehavior::Stationary positioned nodes
index df20f0b..0ca9673 100644 (file)
@@ -39,6 +39,8 @@ async function load() {
     pattern = ctx.createPattern(image, "no-repeat");
     bitmap = await createImageBitmap(image);
 
+    document.body.appendChild(canvas);
+
     ctx.save();
     cancelActions();
 
@@ -51,7 +53,7 @@ function ignoreException(func){
     } catch (e) { }
 }
 
-let requestAnimationFrameId = NaN;
+let timeoutID = NaN;
 let saveCount = 1;
 
 function cancelActions() {
@@ -59,8 +61,8 @@ function cancelActions() {
         ctx.restore();
     ctx.restore(); // Ensures the state is reset between test cases.
 
-    cancelAnimationFrame(requestAnimationFrameId);
-    requestAnimationFrameId = NaN;
+    clearTimeout(timeoutID);
+    timeoutID = NaN;
 
     ctx.save(); // Ensures the state is reset between test cases.
     ctx.save(); // This matches the `restore` call in `performActions`.
@@ -397,7 +399,7 @@ function performActions() {
     function executeFrameFunction() {
         frames[index++]();
         if (index < frames.length)
-            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
+            timeoutID = setTimeout(executeFrameFunction, 0);
     };
     executeFrameFunction();
 }
index 5c1055f..3b0bff4 100644 (file)
@@ -23,7 +23,7 @@ canvas.height = 2;
 function load() {
     ctx = canvas.getContext("bitmaprenderer");
 
-    cancelActions();
+    document.body.appendChild(canvas);
 
     runTest();
 }
@@ -34,11 +34,11 @@ function ignoreException(func){
     } catch (e) { }
 }
 
-let requestAnimationFrameId = NaN;
+let timeoutID = NaN;
 
 function cancelActions() {
-    cancelAnimationFrame(requestAnimationFrameId);
-    requestAnimationFrameId = NaN;
+    clearTimeout(timeoutID);
+    timeoutID = NaN;
 
     createImageBitmap(transparentImage).then((transparentBitmap) => {
         ctx.transferFromImageBitmap(transparentBitmap);
@@ -68,7 +68,7 @@ async function performActions() {
     function executeFrameFunction() {
         frames[index++]();
         if (index < frames.length)
-            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
+            timeoutID = setTimeout(executeFrameFunction, 0);
     };
     executeFrameFunction();
 }
index 6d7a403..f4b6cd3 100644 (file)
@@ -39,7 +39,7 @@ async function load() {
 
     imageBitmap = await createImageBitmap(image);
 
-    cancelActions();
+    document.body.appendChild(canvas);
 
     context.strokeStyle = "red";
     context.save();
@@ -56,15 +56,7 @@ function ignoreException(func){
     } catch (e) { }
 }
 
-let requestAnimationFrameId = NaN;
-
 function cancelActions() {
-    cancelAnimationFrame(requestAnimationFrameId);
-    requestAnimationFrameId = NaN;
-
-    context.resetTransform();
-    context.beginPath();
-    context.clearRect(0, 0, context.canvas.width, context.canvas.height);
 }
 
 function performActions() {
@@ -105,7 +97,7 @@ function performActions() {
     function executeFrameFunction() {
         frames[index++]();
         if (index < frames.length)
-            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
+            timeoutID = setTimeout(executeFrameFunction, 0);
     };
     executeFrameFunction();
 }
index 7672d76..5867438 100644 (file)
@@ -49,7 +49,7 @@ function load() {
     shader = context.createShader(context.VERTEX_SHADER);
     texture = context.createTexture();
 
-    cancelActions();
+    document.body.appendChild(context.canvas);
 
     runTest();
 }
@@ -60,11 +60,11 @@ function ignoreException(func){
     } catch (e) { }
 }
 
-let requestAnimationFrameId = NaN;
+let timeoutID = NaN;
 
 function cancelActions() {
-    cancelAnimationFrame(requestAnimationFrameId);
-    requestAnimationFrameId = NaN;
+    clearTimeout(timeoutID);
+    timeoutID = NaN;
 
     context.clearColor(0.0, 0.0, 0.0, 0.0);
     context.clear(context.COLOR_BUFFER_BIT);
@@ -502,7 +502,7 @@ function performActions() {
     function executeFrameFunction() {
         frames[index++]();
         if (index < frames.length)
-            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
+            timeoutID = setTimeout(executeFrameFunction, 0);
     };
     executeFrameFunction();
 }
index d98f0fe..040c21d 100644 (file)
@@ -6,11 +6,11 @@
 if (window.internals)
     window.internals.settings.setWebGLErrorsToConsoleEnabled(false);
 
-let requestAnimationFrameId = NaN;
+let timeoutID = NaN;
 
 function cancelActions() {
-    cancelAnimationFrame(requestAnimationFrameId);
-    requestAnimationFrameId = NaN;
+    clearTimeout(timeoutID);
+    timeoutID = NaN;
 }
 
 function performActions(frames) {
@@ -19,7 +19,7 @@ function performActions(frames) {
         frames[index++]();
 
         if (index < frames.length)
-            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
+            timeoutID = setTimeout(executeFrameFunction, 0);
         else {
             setTimeout(() => {
                 TestPage.dispatchEventToFrontend("LastFrame");
index a972427..883b35c 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-22  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r243356.
+
+        Causes assertion failures with WebGL layout tests on macOS and
+        iOS.
+
+        Reverted changeset:
+
+        "Web Inspector: Safari Canvas Inspector seems to show the
+        canvas being rendered twice per frame."
+        https://bugs.webkit.org/show_bug.cgi?id=196082
+        https://trac.webkit.org/changeset/243356
+
 2019-03-22  Antti Koivisto  <antti@apple.com>
 
         Handle UI side hit testing for ScrollPositioningBehavior::Stationary positioned nodes
index b5981cf..665615f 100644 (file)
@@ -668,40 +668,38 @@ bool HTMLCanvasElement::paintsIntoCanvasBuffer() const
 
 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r)
 {
+    if (UNLIKELY(m_context && m_context->callTracingActive()))
+        InspectorInstrumentation::didFinishRecordingCanvasFrame(*m_context);
+
     // Clear the dirty rect
     m_dirtyRect = FloatRect();
 
-    if (!context.paintingDisabled()) {
-        bool shouldPaint = true;
+    if (context.paintingDisabled())
+        return;
+    
+    if (m_context) {
+        if (!paintsIntoCanvasBuffer() && !document().printing())
+            return;
 
-        if (m_context) {
-            shouldPaint = paintsIntoCanvasBuffer() || document().printing();
-            if (shouldPaint)
-                m_context->paintRenderingResultsToCanvas();
-        }
+        m_context->paintRenderingResultsToCanvas();
+    }
 
-        if (shouldPaint) {
-            if (hasCreatedImageBuffer()) {
-                ImageBuffer* imageBuffer = buffer();
-                if (imageBuffer) {
-                    if (m_presentedImage) {
-                        ImageOrientationDescription orientationDescription;
+    if (hasCreatedImageBuffer()) {
+        ImageBuffer* imageBuffer = buffer();
+        if (imageBuffer) {
+            if (m_presentedImage) {
+                ImageOrientationDescription orientationDescription;
 #if ENABLE(CSS_IMAGE_ORIENTATION)
-                        orientationDescription.setImageOrientationEnum(renderer()->style().imageOrientation());
-#endif
-                        context.drawImage(*m_presentedImage, snappedIntRect(r), ImagePaintingOptions(orientationDescription));
-                    } else
-                        context.drawImageBuffer(*imageBuffer, snappedIntRect(r));
-                }
-            }
-
-            if (isGPUBased())
-                downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited();
+                orientationDescription.setImageOrientationEnum(renderer()->style().imageOrientation());
+#endif 
+                context.drawImage(*m_presentedImage, snappedIntRect(r), ImagePaintingOptions(orientationDescription));
+            } else
+                context.drawImageBuffer(*imageBuffer, snappedIntRect(r));
         }
     }
 
-    if (UNLIKELY(m_context && m_context->callTracingActive()))
-        InspectorInstrumentation::didFinishRecordingCanvasFrame(*m_context);
+    if (isGPUBased())
+        downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited();
 }
 
 bool HTMLCanvasElement::isGPUBased() const
index 1c0f58a..f52158f 100644 (file)
@@ -661,7 +661,7 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(CanvasBase& canvas, Ref<Gra
     m_contextGroup = WebGLContextGroup::create();
     m_contextGroup->addContext(*this);
     
-    m_context->addClient(*this);
+    m_context->setWebGLContext(this);
 
     m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
 
@@ -914,7 +914,6 @@ void WebGLRenderingContextBase::destroyGraphicsContext3D()
     removeActivityStateChangeObserver();
 
     if (m_context) {
-        m_context->removeClient(*this);
         m_context->setContextLostCallback(nullptr);
         m_context->setErrorMessageCallback(nullptr);
         m_context = nullptr;
@@ -5043,6 +5042,15 @@ void WebGLRenderingContextBase::forceLostContext(WebGLRenderingContextBase::Lost
     m_contextGroup->loseContextGroup(mode);
 }
 
+void WebGLRenderingContextBase::recycleContext()
+{
+    printToConsole(MessageLevel::Error, "There are too many active WebGL contexts on this page, the oldest context will be lost.");
+    // Using SyntheticLostContext means the developer won't be able to force the restoration
+    // of the context by calling preventDefault() in a "webglcontextlost" event handler.
+    forceLostContext(SyntheticLostContext);
+    destroyGraphicsContext3D();
+}
+
 void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode)
 {
     if (isContextLost())
@@ -6217,6 +6225,15 @@ void WebGLRenderingContextBase::maybeRestoreContext()
     canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));
 }
 
+void WebGLRenderingContextBase::dispatchContextChangedEvent()
+{
+    auto* canvas = htmlCanvas();
+    if (!canvas)
+        return;
+
+    canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));
+}
+
 void WebGLRenderingContextBase::simulateContextChanged()
 {
     if (m_context)
@@ -6496,36 +6513,6 @@ void WebGLRenderingContextBase::setFailNextGPUStatusCheck()
     m_context->setFailNextGPUStatusCheck();
 }
 
-void WebGLRenderingContextBase::didComposite()
-{
-    if (UNLIKELY(callTracingActive()))
-        InspectorInstrumentation::didFinishRecordingCanvasFrame(*this);
-}
-
-void WebGLRenderingContextBase::forceContextLost()
-{
-    forceLostContext(WebGLRenderingContextBase::RealLostContext);
-}
-
-void WebGLRenderingContextBase::recycleContext()
-{
-    printToConsole(MessageLevel::Error, "There are too many active WebGL contexts on this page, the oldest context will be lost.");
-    // Using SyntheticLostContext means the developer won't be able to force the restoration
-    // of the context by calling preventDefault() in a "webglcontextlost" event handler.
-    forceLostContext(SyntheticLostContext);
-    destroyGraphicsContext3D();
-}
-
-void WebGLRenderingContextBase::dispatchContextChangedNotification()
-{
-    auto* canvas = htmlCanvas();
-    if (!canvas)
-        return;
-
-    canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));
-}
-
-
 } // namespace WebCore
 
 #endif // ENABLE(WEBGL)
index c7382cb..beb59b5 100644 (file)
@@ -94,7 +94,7 @@ class HTMLVideoElement;
 
 using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>, RefPtr<OffscreenCanvas>>;
 
-class WebGLRenderingContextBase : public GraphicsContext3D::Client, public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
+class WebGLRenderingContextBase : public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
 public:
     static std::unique_ptr<WebGLRenderingContextBase> create(CanvasBase&, WebGLContextAttributes&, const String&);
     virtual ~WebGLRenderingContextBase();
@@ -330,8 +330,10 @@ public:
         SyntheticLostContext
     };
     void forceLostContext(LostContextMode);
+    void recycleContext();
     void forceRestoreContext();
     void loseContextImpl(LostContextMode);
+    void dispatchContextChangedEvent();
     WEBCORE_EXPORT void simulateContextChanged();
 
     GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
@@ -357,12 +359,6 @@ public:
     // Used for testing only, from Internals.
     WEBCORE_EXPORT void setFailNextGPUStatusCheck();
 
-    // GraphicsContext3D::Client
-    void didComposite() override;
-    void forceContextLost() override;
-    void recycleContext() override;
-    void dispatchContextChangedNotification() override;
-
 protected:
     WebGLRenderingContextBase(CanvasBase&, WebGLContextAttributes);
     WebGLRenderingContextBase(CanvasBase&, Ref<GraphicsContext3D>&&, WebGLContextAttributes);
index a84edf3..0095342 100644 (file)
@@ -89,8 +89,9 @@ InspectorCanvas::InspectorCanvas(CanvasRenderingContext& context)
 
 HTMLCanvasElement* InspectorCanvas::canvasElement()
 {
-    if (is<HTMLCanvasElement>(m_context.canvasBase()))
-        return &downcast<HTMLCanvasElement>(m_context.canvasBase());
+    auto* canvasBase = &m_context.canvasBase();
+    if (is<HTMLCanvasElement>(canvasBase))
+        return downcast<HTMLCanvasElement>(canvasBase);
     return nullptr;
 }
 
@@ -136,9 +137,6 @@ static bool shouldSnapshotWebGLAction(const String& name)
 void InspectorCanvas::recordAction(const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
     if (!m_initialState) {
-        // We should only construct the initial state for the first action of the recording.
-        ASSERT(!m_frames && !m_currentActions);
-
         m_initialState = buildInitialState();
         m_bufferUsed += m_initialState->memoryCost();
     }
@@ -173,10 +171,26 @@ void InspectorCanvas::recordAction(const String& name, Vector<RecordCanvasAction
 #endif
 }
 
-void InspectorCanvas::finalizeFrame()
+RefPtr<Inspector::Protocol::Recording::InitialState>&& InspectorCanvas::releaseInitialState()
+{
+    return WTFMove(m_initialState);
+}
+
+RefPtr<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>>&& InspectorCanvas::releaseFrames()
 {
     appendActionSnapshotIfNeeded();
 
+    return WTFMove(m_frames);
+}
+
+RefPtr<JSON::ArrayOf<JSON::Value>>&& InspectorCanvas::releaseData()
+{
+    m_indexedDuplicateData.clear();
+    return WTFMove(m_serializedDuplicateData);
+}
+
+void InspectorCanvas::finalizeFrame()
+{
     if (m_frames && m_frames->length() && !std::isnan(m_currentFrameStartTime)) {
         auto currentFrame = static_cast<Inspector::Protocol::Recording::Frame*>(m_frames->get(m_frames->length() - 1).get());
         currentFrame->setDuration((MonotonicTime::now() - m_currentFrameStartTime).milliseconds());
@@ -297,61 +311,22 @@ Ref<Inspector::Protocol::Canvas::Canvas> InspectorCanvas::buildObjectForCanvas(b
     return canvas;
 }
 
-Ref<Inspector::Protocol::Recording::Recording> InspectorCanvas::releaseObjectForRecording()
+void InspectorCanvas::appendActionSnapshotIfNeeded()
 {
-    ASSERT(!m_currentActions);
-    ASSERT(!m_actionNeedingSnapshot);
-    ASSERT(!m_frames);
-
-    // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext
-
-    Inspector::Protocol::Recording::Type type;
-    if (is<CanvasRenderingContext2D>(m_context))
-        type = Inspector::Protocol::Recording::Type::Canvas2D;
-    else if (is<ImageBitmapRenderingContext>(m_context))
-        type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer;
-#if ENABLE(WEBGL)
-    else if (is<WebGLRenderingContext>(m_context))
-        type = Inspector::Protocol::Recording::Type::CanvasWebGL;
-#endif
-    else {
-        ASSERT_NOT_REACHED();
-        type = Inspector::Protocol::Recording::Type::Canvas2D;
-    }
-
-    auto recording = Inspector::Protocol::Recording::Recording::create()
-        .setVersion(Inspector::Protocol::Recording::VERSION)
-        .setType(type)
-        .setInitialState(m_initialState.releaseNonNull())
-        .setData(m_serializedDuplicateData.releaseNonNull())
-        .release();
-
-    if (!m_recordingName.isEmpty())
-        recording->setName(m_recordingName);
-
-    resetRecordingData();
+    if (!m_actionNeedingSnapshot)
+        return;
 
-    return recording;
+    m_actionNeedingSnapshot->addItem(indexForData(getCanvasContentAsDataURL()));
+    m_actionNeedingSnapshot = nullptr;
 }
 
-String InspectorCanvas::getCanvasContentAsDataURL(ErrorString& errorString)
+String InspectorCanvas::getCanvasContentAsDataURL()
 {
-    // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebMetal context;
-    if (!is<CanvasRenderingContext2D>(m_context)
-#if ENABLE(WEBGL)
-        && !is<WebGLRenderingContextBase>(m_context)
-#endif
-        && !is<ImageBitmapRenderingContext>(m_context)) {
-        errorString = "Unsupported canvas context type"_s;
-        return emptyString();
-    }
-
     // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations
+
     auto* node = canvasElement();
-    if (!node) {
-        errorString = "Context isn't related to an HTMLCanvasElement"_s;
-        return emptyString();
-    }
+    if (!node)
+        return String();
 
 #if ENABLE(WEBGL)
     if (is<WebGLRenderingContextBase>(m_context))
@@ -365,29 +340,12 @@ String InspectorCanvas::getCanvasContentAsDataURL(ErrorString& errorString)
         downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(false);
 #endif
 
-    if (result.hasException()) {
-        errorString = result.releaseException().releaseMessage();
-        return emptyString();
-    }
+    if (result.hasException())
+        return String();
 
     return result.releaseReturnValue().string;
 }
 
-void InspectorCanvas::appendActionSnapshotIfNeeded()
-{
-    if (!m_actionNeedingSnapshot)
-        return;
-
-    m_bufferUsed -= m_actionNeedingSnapshot->memoryCost();
-
-    ErrorString ignored;
-    m_actionNeedingSnapshot->addItem(indexForData(getCanvasContentAsDataURL(ignored)));
-
-    m_bufferUsed += m_actionNeedingSnapshot->memoryCost();
-
-    m_actionNeedingSnapshot = nullptr;
-}
-
 int InspectorCanvas::indexForData(DuplicateDataVariant data)
 {
     size_t index = m_indexedDuplicateData.findMatching([&] (auto item) {
@@ -603,8 +561,7 @@ Ref<Inspector::Protocol::Recording::InitialState> InspectorCanvas::buildInitialS
     if (parametersPayload->length())
         initialStatePayload->setParameters(WTFMove(parametersPayload));
 
-    ErrorString ignored;
-    initialStatePayload->setContent(getCanvasContentAsDataURL(ignored));
+    initialStatePayload->setContent(getCanvasContentAsDataURL());
 
     return initialStatePayload;
 }
index 26c8671..b4b66d0 100644 (file)
@@ -44,8 +44,6 @@ class HTMLVideoElement;
 class ImageBitmap;
 class ImageData;
 
-typedef String ErrorString;
-
 class InspectorCanvas final : public RefCounted<InspectorCanvas> {
 public:
     static Ref<InspectorCanvas> create(CanvasRenderingContext&);
@@ -60,11 +58,14 @@ public:
     bool currentFrameHasData() const;
     void recordAction(const String&, Vector<RecordCanvasActionVariant>&& = { });
 
-    Ref<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>> releaseFrames() { return m_frames.releaseNonNull(); }
+    RefPtr<Inspector::Protocol::Recording::InitialState>&& releaseInitialState();
+    RefPtr<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>>&& releaseFrames();
+    RefPtr<JSON::ArrayOf<JSON::Value>>&& releaseData();
 
     void finalizeFrame();
     void markCurrentFrameIncomplete();
 
+    const String& recordingName() const { return m_recordingName; }
     void setRecordingName(const String& name) { m_recordingName = name; }
 
     void setBufferLimit(long);
@@ -75,13 +76,11 @@ public:
     bool overFrameCount() const;
 
     Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(bool captureBacktrace);
-    Ref<Inspector::Protocol::Recording::Recording> releaseObjectForRecording();
-
-    String getCanvasContentAsDataURL(ErrorString&);
 
 private:
     InspectorCanvas(CanvasRenderingContext&);
     void appendActionSnapshotIfNeeded();
+    String getCanvasContentAsDataURL();
 
     using DuplicateDataVariant = Variant<
         RefPtr<CanvasGradient>,
index d087b05..941e249 100644 (file)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "InspectorCanvasAgent.h"
 
-#include "ActiveDOMCallbackMicrotask.h"
 #include "CanvasRenderingContext.h"
 #include "CanvasRenderingContext2D.h"
 #include "Document.h"
@@ -38,7 +37,6 @@
 #include "JSCanvasRenderingContext2D.h"
 #include "JSExecState.h"
 #include "JSImageBitmapRenderingContext.h"
-#include "Microtasks.h"
 #include "OffscreenCanvas.h"
 #include "ScriptState.h"
 #include "StringAdaptors.h"
@@ -80,6 +78,7 @@ InspectorCanvasAgent::InspectorCanvasAgent(PageAgentContext& context)
     , m_injectedScriptManager(context.injectedScriptManager)
     , m_inspectedPage(context.inspectedPage)
     , m_canvasDestroyedTimer(*this, &InspectorCanvasAgent::canvasDestroyedTimerFired)
+    , m_canvasRecordingTimer(*this, &InspectorCanvasAgent::canvasRecordingTimerFired)
 {
 }
 
@@ -148,7 +147,7 @@ void InspectorCanvasAgent::disable(ErrorString&)
 
 void InspectorCanvasAgent::requestNode(ErrorString& errorString, const String& canvasId, int* nodeId)
 {
-    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
+    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     if (!inspectorCanvas)
         return;
 
@@ -169,16 +168,48 @@ void InspectorCanvasAgent::requestNode(ErrorString& errorString, const String& c
 
 void InspectorCanvasAgent::requestContent(ErrorString& errorString, const String& canvasId, String* content)
 {
-    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
+    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     if (!inspectorCanvas)
         return;
 
-    *content = inspectorCanvas->getCanvasContentAsDataURL(errorString);
+    // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations
+
+    if (auto* node = inspectorCanvas->canvasElement()) {
+        if (is<CanvasRenderingContext2D>(inspectorCanvas->context()) || is<ImageBitmapRenderingContext>(inspectorCanvas->context())) {
+            auto result = node->toDataURL("image/png"_s);
+            if (result.hasException()) {
+                errorString = result.releaseException().releaseMessage();
+                return;
+            }
+            *content = result.releaseReturnValue().string;
+            return;
+        }
+
+#if ENABLE(WEBGL)
+        if (is<WebGLRenderingContextBase>(inspectorCanvas->context())) {
+            WebGLRenderingContextBase& contextWebGLBase = downcast<WebGLRenderingContextBase>(inspectorCanvas->context());
+
+            contextWebGLBase.setPreventBufferClearForInspector(true);
+            auto result = node->toDataURL("image/png"_s);
+            contextWebGLBase.setPreventBufferClearForInspector(false);
+
+            if (result.hasException()) {
+                errorString = result.releaseException().releaseMessage();
+                return;
+            }
+            *content = result.releaseReturnValue().string;
+            return;
+        }
+#endif
+    }
+
+    // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebMetal context;
+    errorString = "Unsupported canvas context type"_s;
 }
 
 void InspectorCanvasAgent::requestCSSCanvasClientNodes(ErrorString& errorString, const String& canvasId, RefPtr<JSON::ArrayOf<int>>& result)
 {
-    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
+    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     if (!inspectorCanvas)
         return;
 
@@ -219,7 +250,7 @@ static JSC::JSValue contextAsScriptValue(JSC::ExecState& state, CanvasRenderingC
 
 void InspectorCanvasAgent::resolveCanvasContext(ErrorString& errorString, const String& canvasId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
 {
-    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
+    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     if (!inspectorCanvas)
         return;
 
@@ -248,7 +279,7 @@ void InspectorCanvasAgent::setRecordingAutoCaptureFrameCount(ErrorString&, int c
 
 void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String& canvasId, const int* frameCount, const int* memoryLimit)
 {
-    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
+    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     if (!inspectorCanvas)
         return;
 
@@ -267,7 +298,7 @@ void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String
 
 void InspectorCanvasAgent::stopRecording(ErrorString& errorString, const String& canvasId)
 {
-    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
+    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     if (!inspectorCanvas)
         return;
 
@@ -282,7 +313,7 @@ void InspectorCanvasAgent::stopRecording(ErrorString& errorString, const String&
 void InspectorCanvasAgent::requestShaderSource(ErrorString& errorString, const String& programId, const String& shaderType, String* content)
 {
 #if ENABLE(WEBGL)
-    auto inspectorProgram = assertInspectorProgram(errorString, programId);
+    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     if (!inspectorProgram)
         return;
 
@@ -304,7 +335,7 @@ void InspectorCanvasAgent::requestShaderSource(ErrorString& errorString, const S
 void InspectorCanvasAgent::updateShader(ErrorString& errorString, const String& programId, const String& shaderType, const String& source)
 {
 #if ENABLE(WEBGL)
-    auto inspectorProgram = assertInspectorProgram(errorString, programId);
+    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     if (!inspectorProgram)
         return;
 
@@ -335,7 +366,7 @@ void InspectorCanvasAgent::updateShader(ErrorString& errorString, const String&
 void InspectorCanvasAgent::setShaderProgramDisabled(ErrorString& errorString, const String& programId, bool disabled)
 {
 #if ENABLE(WEBGL)
-    auto inspectorProgram = assertInspectorProgram(errorString, programId);
+    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     if (!inspectorProgram)
         return;
 
@@ -350,7 +381,7 @@ void InspectorCanvasAgent::setShaderProgramDisabled(ErrorString& errorString, co
 void InspectorCanvasAgent::setShaderProgramHighlighted(ErrorString& errorString, const String& programId, bool highlighted)
 {
 #if ENABLE(WEBGL)
-    auto inspectorProgram = assertInspectorProgram(errorString, programId);
+    auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     if (!inspectorProgram)
         return;
 
@@ -393,7 +424,7 @@ void InspectorCanvasAgent::didChangeCSSCanvasClientNodes(CanvasBase& canvasBase)
         return;
     }
 
-    auto inspectorCanvas = findInspectorCanvas(*context);
+    auto* inspectorCanvas = findInspectorCanvas(*context);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -419,7 +450,7 @@ void InspectorCanvasAgent::didCreateCanvasRenderingContext(CanvasRenderingContex
 
 void InspectorCanvasAgent::didChangeCanvasMemory(CanvasRenderingContext& context)
 {
-    auto inspectorCanvas = findInspectorCanvas(context);
+    auto* inspectorCanvas = findInspectorCanvas(context);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -432,7 +463,7 @@ void InspectorCanvasAgent::didChangeCanvasMemory(CanvasRenderingContext& context
 
 void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
 {
-    auto inspectorCanvas = findInspectorCanvas(canvasRenderingContext);
+    auto* inspectorCanvas = findInspectorCanvas(canvasRenderingContext);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -441,25 +472,11 @@ void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRend
     if (!canvasRenderingContext.callTracingActive())
         return;
 
-    // Only enqueue a microtask for the first action of each frame. Any subsequent actions will be
-    // covered by the initial microtask until the next frame.
-    if (!inspectorCanvas->currentFrameHasData()) {
-        if (auto* scriptExecutionContext = inspectorCanvas->context().canvasBase().scriptExecutionContext()) {
-            auto& queue = MicrotaskQueue::mainThreadQueue();
-            queue.append(std::make_unique<ActiveDOMCallbackMicrotask>(queue, *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
-                if (auto* canvasElement = protectedInspectorCanvas->canvasElement()) {
-                    if (canvasElement->isDescendantOf(canvasElement->document()))
-                        return;
-                }
-
-                if (protectedInspectorCanvas->context().callTracingActive())
-                    didFinishRecordingCanvasFrame(protectedInspectorCanvas->context());
-            }));
-        }
-    }
-
     inspectorCanvas->recordAction(name, WTFMove(parameters));
 
+    if (!m_canvasRecordingTimer.isActive())
+        m_canvasRecordingTimer.startOneShot(0_s);
+
     if (!inspectorCanvas->hasBufferSpace())
         didFinishRecordingCanvasFrame(inspectorCanvas->context(), true);
 }
@@ -470,8 +487,7 @@ void InspectorCanvasAgent::canvasDestroyed(CanvasBase& canvasBase)
     if (!context)
         return;
 
-    auto inspectorCanvas = findInspectorCanvas(*context);
-    ASSERT(inspectorCanvas);
+    auto* inspectorCanvas = findInspectorCanvas(*context);
     if (!inspectorCanvas)
         return;
 
@@ -488,7 +504,7 @@ void InspectorCanvasAgent::canvasDestroyed(CanvasBase& canvasBase)
 
 void InspectorCanvasAgent::didFinishRecordingCanvasFrame(CanvasRenderingContext& context, bool forceDispatch)
 {
-    auto inspectorCanvas = findInspectorCanvas(context);
+    auto* inspectorCanvas = findInspectorCanvas(context);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -499,6 +515,7 @@ void InspectorCanvasAgent::didFinishRecordingCanvasFrame(CanvasRenderingContext&
     if (!inspectorCanvas->hasRecordingData()) {
         if (forceDispatch) {
             m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), nullptr);
+
             inspectorCanvas->resetRecordingData();
         }
         return;
@@ -514,12 +531,41 @@ void InspectorCanvasAgent::didFinishRecordingCanvasFrame(CanvasRenderingContext&
     if (!forceDispatch && !inspectorCanvas->overFrameCount())
         return;
 
-    m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), inspectorCanvas->releaseObjectForRecording());
+    // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext
+
+    Inspector::Protocol::Recording::Type type;
+    if (is<CanvasRenderingContext2D>(inspectorCanvas->context()))
+        type = Inspector::Protocol::Recording::Type::Canvas2D;
+    else if (is<ImageBitmapRenderingContext>(inspectorCanvas->context()))
+        type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer;
+#if ENABLE(WEBGL)
+    else if (is<WebGLRenderingContext>(inspectorCanvas->context()))
+        type = Inspector::Protocol::Recording::Type::CanvasWebGL;
+#endif
+    else {
+        ASSERT_NOT_REACHED();
+        type = Inspector::Protocol::Recording::Type::Canvas2D;
+    }
+
+    auto recording = Inspector::Protocol::Recording::Recording::create()
+        .setVersion(Inspector::Protocol::Recording::VERSION)
+        .setType(type)
+        .setInitialState(inspectorCanvas->releaseInitialState())
+        .setData(inspectorCanvas->releaseData())
+        .release();
+
+    const String& name = inspectorCanvas->recordingName();
+    if (!name.isEmpty())
+        recording->setName(name);
+
+    m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), WTFMove(recording));
+
+    inspectorCanvas->resetRecordingData();
 }
 
 void InspectorCanvasAgent::consoleStartRecordingCanvas(CanvasRenderingContext& context, JSC::ExecState& exec, JSC::JSObject* options)
 {
-    auto inspectorCanvas = findInspectorCanvas(context);
+    auto* inspectorCanvas = findInspectorCanvas(context);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -541,7 +587,7 @@ void InspectorCanvasAgent::consoleStartRecordingCanvas(CanvasRenderingContext& c
 #if ENABLE(WEBGL)
 void InspectorCanvasAgent::didEnableExtension(WebGLRenderingContextBase& context, const String& extension)
 {
-    auto inspectorCanvas = findInspectorCanvas(context);
+    auto* inspectorCanvas = findInspectorCanvas(context);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -551,7 +597,7 @@ void InspectorCanvasAgent::didEnableExtension(WebGLRenderingContextBase& context
 
 void InspectorCanvasAgent::didCreateProgram(WebGLRenderingContextBase& context, WebGLProgram& program)
 {
-    auto inspectorCanvas = findInspectorCanvas(context);
+    auto* inspectorCanvas = findInspectorCanvas(context);
     ASSERT(inspectorCanvas);
     if (!inspectorCanvas)
         return;
@@ -564,7 +610,7 @@ void InspectorCanvasAgent::didCreateProgram(WebGLRenderingContextBase& context,
 
 void InspectorCanvasAgent::willDeleteProgram(WebGLProgram& program)
 {
-    auto inspectorProgram = findInspectorProgram(program);
+    auto* inspectorProgram = findInspectorProgram(program);
     if (!inspectorProgram)
         return;
 
@@ -574,8 +620,7 @@ void InspectorCanvasAgent::willDeleteProgram(WebGLProgram& program)
 
 bool InspectorCanvasAgent::isShaderProgramDisabled(WebGLProgram& program)
 {
-    auto inspectorProgram = findInspectorProgram(program);
-    ASSERT(inspectorProgram);
+    auto* inspectorProgram = findInspectorProgram(program);
     if (!inspectorProgram)
         return false;
 
@@ -584,8 +629,7 @@ bool InspectorCanvasAgent::isShaderProgramDisabled(WebGLProgram& program)
 
 bool InspectorCanvasAgent::isShaderProgramHighlighted(WebGLProgram& program)
 {
-    auto inspectorProgram = findInspectorProgram(program);
-    ASSERT(inspectorProgram);
+    auto* inspectorProgram = findInspectorProgram(program);
     if (!inspectorProgram)
         return false;
 
@@ -630,17 +674,30 @@ void InspectorCanvasAgent::canvasDestroyedTimerFired()
     m_removedCanvasIdentifiers.clear();
 }
 
+void InspectorCanvasAgent::canvasRecordingTimerFired()
+{
+    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
+        if (!inspectorCanvas->context().callTracingActive())
+            continue;
+
+        didFinishRecordingCanvasFrame(inspectorCanvas->context());
+    }
+}
+
 void InspectorCanvasAgent::clearCanvasData()
 {
     for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values())
         inspectorCanvas->context().canvasBase().removeObserver(*this);
 
     m_identifierToInspectorCanvas.clear();
+    m_removedCanvasIdentifiers.clear();
 #if ENABLE(WEBGL)
     m_identifierToInspectorProgram.clear();
-    m_removedCanvasIdentifiers.clear();
 #endif
 
+    if (m_canvasRecordingTimer.isActive())
+        m_canvasRecordingTimer.stop();
+
     if (m_canvasDestroyedTimer.isActive())
         m_canvasDestroyedTimer.stop();
 }
@@ -688,22 +745,22 @@ String InspectorCanvasAgent::unbindCanvas(InspectorCanvas& inspectorCanvas)
     return identifier;
 }
 
-RefPtr<InspectorCanvas> InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier)
+InspectorCanvas* InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier)
 {
-    auto inspectorCanvas = m_identifierToInspectorCanvas.get(identifier);
+    RefPtr<InspectorCanvas> inspectorCanvas = m_identifierToInspectorCanvas.get(identifier);
     if (!inspectorCanvas) {
         errorString = "No canvas for given identifier."_s;
         return nullptr;
     }
 
-    return inspectorCanvas;
+    return inspectorCanvas.get();
 }
 
-RefPtr<InspectorCanvas> InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context)
+InspectorCanvas* InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context)
 {
     for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
         if (&inspectorCanvas->context() == &context)
-            return inspectorCanvas;
+            return inspectorCanvas.get();
     }
 
     return nullptr;
@@ -718,22 +775,22 @@ String InspectorCanvasAgent::unbindProgram(InspectorShaderProgram& inspectorProg
     return identifier;
 }
 
-RefPtr<InspectorShaderProgram> InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier)
+InspectorShaderProgram* InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier)
 {
-    auto inspectorProgram = m_identifierToInspectorProgram.get(identifier);
+    RefPtr<InspectorShaderProgram> inspectorProgram = m_identifierToInspectorProgram.get(identifier);
     if (!inspectorProgram) {
         errorString = "No shader program for given identifier."_s;
         return nullptr;
     }
 
-    return inspectorProgram;
+    return inspectorProgram.get();
 }
 
-RefPtr<InspectorShaderProgram> InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program)
+InspectorShaderProgram* InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program)
 {
     for (auto& inspectorProgram : m_identifierToInspectorProgram.values()) {
         if (&inspectorProgram->program() == &program)
-            return inspectorProgram;
+            return inspectorProgram.get();
     }
 
     return nullptr;
index 7bc8d87..5b299c8 100644 (file)
@@ -112,15 +112,18 @@ private:
     void startRecording(InspectorCanvas&, Inspector::Protocol::Recording::Initiator, RecordingOptions&& = { });
 
     void canvasDestroyedTimerFired();
+    void canvasRecordingTimerFired();
     void clearCanvasData();
     InspectorCanvas& bindCanvas(CanvasRenderingContext&, bool captureBacktrace);
     String unbindCanvas(InspectorCanvas&);
-    RefPtr<InspectorCanvas> assertInspectorCanvas(ErrorString&, const String& identifier);
-    RefPtr<InspectorCanvas> findInspectorCanvas(CanvasRenderingContext&);
+    InspectorCanvas* assertInspectorCanvas(ErrorString&, const String& identifier);
+    InspectorCanvas* findInspectorCanvas(CanvasRenderingContext&);
 #if ENABLE(WEBGL)
     String unbindProgram(InspectorShaderProgram&);
-    RefPtr<InspectorShaderProgram> assertInspectorProgram(ErrorString&, const String& identifier);
-    RefPtr<InspectorShaderProgram> findInspectorProgram(WebGLProgram&);
+    InspectorShaderProgram* assertInspectorProgram(ErrorString&, const String& identifier);
+    InspectorShaderProgram* findInspectorProgram(WebGLProgram&);
+
+    HashMap<String, RefPtr<InspectorShaderProgram>> m_identifierToInspectorProgram;
 #endif
 
     std::unique_ptr<Inspector::CanvasFrontendDispatcher> m_frontendDispatcher;
@@ -130,14 +133,10 @@ private:
     Page& m_inspectedPage;
 
     HashMap<String, RefPtr<InspectorCanvas>> m_identifierToInspectorCanvas;
-#if ENABLE(WEBGL)
-    HashMap<String, RefPtr<InspectorShaderProgram>> m_identifierToInspectorProgram;
-#endif
     Vector<String> m_removedCanvasIdentifiers;
-
     Optional<size_t> m_recordingAutoCaptureFrameCount;
-
     Timer m_canvasDestroyedTimer;
+    Timer m_canvasRecordingTimer;
 };
 
 } // namespace WebCore
index 11b0e99..65d264b 100644 (file)
@@ -120,15 +120,6 @@ class GraphicsContext3DPrivate;
 
 class GraphicsContext3D : public RefCounted<GraphicsContext3D> {
 public:
-    class Client {
-    public:
-        virtual ~Client() { }
-        virtual void didComposite() = 0;
-        virtual void forceContextLost() = 0;
-        virtual void recycleContext() = 0;
-        virtual void dispatchContextChangedNotification() = 0;
-    };
-
     enum {
         // WebGL 1 constants
         DEPTH_BUFFER_BIT = 0x00000100,
@@ -773,9 +764,7 @@ public:
 #endif
 
     bool makeContextCurrent();
-
-    void addClient(Client& client) { m_clients.add(&client); }
-    void removeClient(Client& client) { m_clients.remove(&client); }
+    void setWebGLContext(WebGLRenderingContextBase* base) { m_webglContext = base; }
 
     // With multisampling on, blit from multisampleFBO to regular FBO.
     void prepareTexture();
@@ -1518,7 +1507,8 @@ private:
     std::unique_ptr<GraphicsContext3DPrivate> m_private;
 #endif
 
-    HashSet<Client*> m_clients;
+    // FIXME: Layering violation.
+    WebGLRenderingContextBase* m_webglContext { nullptr };
 
     bool m_isForWebGL2 { false };
     bool m_usingCoreProfile { false };
index c776b32..546e741 100644 (file)
@@ -2016,9 +2016,6 @@ void GraphicsContext3D::markContextChanged()
 void GraphicsContext3D::markLayerComposited()
 {
     m_layerComposited = true;
-
-    for (auto* client : m_clients)
-        client->didComposite();
 }
 
 bool GraphicsContext3D::layerComposited() const
@@ -2028,20 +2025,26 @@ bool GraphicsContext3D::layerComposited() const
 
 void GraphicsContext3D::forceContextLost()
 {
-    for (auto* client : m_clients)
-        client->forceContextLost();
+#if ENABLE(WEBGL)
+    if (m_webglContext)
+        m_webglContext->forceLostContext(WebGLRenderingContextBase::RealLostContext);
+#endif
 }
 
 void GraphicsContext3D::recycleContext()
 {
-    for (auto* client : m_clients)
-        client->recycleContext();
+#if ENABLE(WEBGL)
+    if (m_webglContext)
+        m_webglContext->recycleContext();
+#endif
 }
 
 void GraphicsContext3D::dispatchContextChangedNotification()
 {
-    for (auto* client : m_clients)
-        client->dispatchContextChangedNotification();
+#if ENABLE(WEBGL)
+    if (m_webglContext)
+        m_webglContext->dispatchContextChangedEvent();
+#endif
 }
 
 void GraphicsContext3D::texImage2DDirect(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)