⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 243356 in webkit


Ignore:
Timestamp:
Mar 21, 2019, 7:47:35 PM (7 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Safari Canvas Inspector seems to show the canvas being rendered twice per frame.
https://bugs.webkit.org/show_bug.cgi?id=196082
<rdar://problem/49113496>

Reviewed by Dean Jackson.

Source/WebCore:

Tests: inspector/canvas/recording-2d.html

inspector/canvas/recording-bitmaprenderer.html
inspector/canvas/recording-html-2d.html
inspector/canvas/recording-webgl.html
inspector/canvas/setRecordingAutoCaptureFrameCount.html

WebGL <canvas> follow a different "rendering" path such that HTMLCanvasElement::paint
isn't called. Previously, there was a 0s timer that was started after the first action of a
frame was recorded (for the case that the <canvas> isn't attached to the DOM) that would
automatically stop the recording. It was possible that actions in two different "frame"s
were recorded as part of the same frame, because the WebGL <canvas> would instead fall
back to the timer to know when the "frame" had ended.

Now, there is additional instrumentation for the WebGL specific rendering path.
Additionally, replace the 0s timer with a microtask for more "immediate" calling.

  • html/HTMLCanvasElement.cpp:

(WebCore::HTMLCanvasElement::paint):
Ensure that the InspectorInstrumentation call is last. This matches what we expect, as
before we were instrumenting right before is it about to paint.

  • platform/graphics/GraphicsContext3D.h:

(WebCore::GraphicsContext3D::Client::~Client): Added.
(WebCore::GraphicsContext3D::addClient): Added.
(WebCore::GraphicsContext3D::removeClient): Added.
(WebCore::GraphicsContext3D::setWebGLContext): Deleted.

  • platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:

(WebCore::GraphicsContext3D::markLayerComposited):
(WebCore::GraphicsContext3D::forceContextLost):
(WebCore::GraphicsContext3D::recycleContext):
(WebCore::GraphicsContext3D::dispatchContextChangedNotification):

  • html/canvas/WebGLRenderingContextBase.h:
  • html/canvas/WebGLRenderingContextBase.cpp:

(WebCore::WebGLRenderingContextBase::WebGLRenderingContextBase):
(WebCore::WebGLRenderingContextBase::destroyGraphicsContext3D):
(WebCore::WebGLRenderingContextBase::didComposite): Added.
(WebCore::WebGLRenderingContextBase::forceContextLost):
(WebCore::WebGLRenderingContextBase::recycleContext):
(WebCore::WebGLRenderingContextBase::dispatchContextChangedNotification): Added.
(WebCore::WebGLRenderingContextBase::dispatchContextChangedEvent): Deleted.
Introduce a GraphicsContext3DClient abstract class, rather than passing the
WebGLRenderingContextBase directly to the GraphicsContext3D (layering violation).
Notify the client whenever the GraphicsContext3D composites, which will in turn notify the
InspectorCanvasAgent so that it knows that the "frame" is over.

  • inspector/agents/InspectorCanvasAgent.h:
  • inspector/agents/InspectorCanvasAgent.cpp:

(WebCore::InspectorCanvasAgent::InspectorCanvasAgent):
(WebCore::InspectorCanvasAgent::requestNode):
(WebCore::InspectorCanvasAgent::requestContent):
(WebCore::InspectorCanvasAgent::requestCSSCanvasClientNodes):
(WebCore::InspectorCanvasAgent::resolveCanvasContext):
(WebCore::InspectorCanvasAgent::startRecording):
(WebCore::InspectorCanvasAgent::stopRecording):
(WebCore::InspectorCanvasAgent::requestShaderSource):
(WebCore::InspectorCanvasAgent::updateShader):
(WebCore::InspectorCanvasAgent::setShaderProgramDisabled):
(WebCore::InspectorCanvasAgent::setShaderProgramHighlighted):
(WebCore::InspectorCanvasAgent::didChangeCSSCanvasClientNodes):
(WebCore::InspectorCanvasAgent::didChangeCanvasMemory):
(WebCore::InspectorCanvasAgent::recordCanvasAction):
(WebCore::InspectorCanvasAgent::canvasDestroyed):
(WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
(WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas):
(WebCore::InspectorCanvasAgent::didEnableExtension):
(WebCore::InspectorCanvasAgent::didCreateProgram):
(WebCore::InspectorCanvasAgent::willDeleteProgram):
(WebCore::InspectorCanvasAgent::isShaderProgramDisabled):
(WebCore::InspectorCanvasAgent::isShaderProgramHighlighted):
(WebCore::InspectorCanvasAgent::clearCanvasData):
(WebCore::InspectorCanvasAgent::assertInspectorCanvas):
(WebCore::InspectorCanvasAgent::findInspectorCanvas):
(WebCore::InspectorCanvasAgent::assertInspectorProgram):
(WebCore::InspectorCanvasAgent::findInspectorProgram):
(WebCore::InspectorCanvasAgent::canvasRecordingTimerFired): Deleted.
Replace raw pointers with RefPtrs. This is primarily used so that the microtask (instead
of a timer) that is enqueued after the first action of each frame is recorded can access a
ref-counted instance of an InspectorCanvas, ensuring that it isn't destructed.

  • inspector/InspectorCanvas.h:
  • inspector/InspectorCanvas.cpp:

(WebCore::InspectorCanvas::canvasElement):
(WebCore::InspectorCanvas::recordAction):
(WebCore::InspectorCanvas::finalizeFrame):
(WebCore::InspectorCanvas::releaseObjectForRecording): Added.
(WebCore::InspectorCanvas::getCanvasContentAsDataURL):
(WebCore::InspectorCanvas::appendActionSnapshotIfNeeded):
(WebCore::InspectorCanvas::buildInitialState):
(WebCore::InspectorCanvas::releaseInitialState): Deleted.
(WebCore::InspectorCanvas::releaseFrames): Deleted.
(WebCore::InspectorCanvas::releaseData): Deleted.
Move the recording payload construction logic to InspectorCanvas so the actual data
doesn't need to leave that class.
Drive-by: unify the logic for getting the contents of a canvas from InspectorCanvasAgent.

LayoutTests:

  • inspector/canvas/recording-2d.html:
  • inspector/canvas/recording-bitmaprenderer.html:
  • inspector/canvas/recording-html-2d.html:
  • inspector/canvas/recording-webgl.html:
  • inspector/canvas/setRecordingAutoCaptureFrameCount.html:
Location:
trunk
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243355 r243356  
     12019-03-21  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Safari Canvas Inspector seems to show the canvas being rendered twice per frame.
     4        https://bugs.webkit.org/show_bug.cgi?id=196082
     5        <rdar://problem/49113496>
     6
     7        Reviewed by Dean Jackson.
     8
     9        * inspector/canvas/recording-2d.html:
     10        * inspector/canvas/recording-bitmaprenderer.html:
     11        * inspector/canvas/recording-html-2d.html:
     12        * inspector/canvas/recording-webgl.html:
     13        * inspector/canvas/setRecordingAutoCaptureFrameCount.html:
     14
    1152019-03-21  Joseph Pecoraro  <pecoraro@apple.com>
    216
  • trunk/LayoutTests/inspector/canvas/recording-2d.html

    r237808 r243356  
    4040    bitmap = await createImageBitmap(image);
    4141
    42     document.body.appendChild(canvas);
    43 
    4442    ctx.save();
    4543    cancelActions();
     
    5452}
    5553
    56 let timeoutID = NaN;
     54let requestAnimationFrameId = NaN;
    5755let saveCount = 1;
    5856
     
    6260    ctx.restore(); // Ensures the state is reset between test cases.
    6361
    64     clearTimeout(timeoutID);
    65     timeoutID = NaN;
     62    cancelAnimationFrame(requestAnimationFrameId);
     63    requestAnimationFrameId = NaN;
    6664
    6765    ctx.save(); // Ensures the state is reset between test cases.
     
    400398        frames[index++]();
    401399        if (index < frames.length)
    402             timeoutID = setTimeout(executeFrameFunction, 0);
     400            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
    403401    };
    404402    executeFrameFunction();
  • trunk/LayoutTests/inspector/canvas/recording-bitmaprenderer.html

    r237777 r243356  
    2424    ctx = canvas.getContext("bitmaprenderer");
    2525
    26     document.body.appendChild(canvas);
     26    cancelActions();
    2727
    2828    runTest();
     
    3535}
    3636
    37 let timeoutID = NaN;
     37let requestAnimationFrameId = NaN;
    3838
    3939function cancelActions() {
    40     clearTimeout(timeoutID);
    41     timeoutID = NaN;
     40    cancelAnimationFrame(requestAnimationFrameId);
     41    requestAnimationFrameId = NaN;
    4242
    4343    createImageBitmap(transparentImage).then((transparentBitmap) => {
     
    6969        frames[index++]();
    7070        if (index < frames.length)
    71             timeoutID = setTimeout(executeFrameFunction, 0);
     71            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
    7272    };
    7373    executeFrameFunction();
  • trunk/LayoutTests/inspector/canvas/recording-html-2d.html

    r242809 r243356  
    4040    imageBitmap = await createImageBitmap(image);
    4141
    42     document.body.appendChild(canvas);
     42    cancelActions();
    4343
    4444    context.strokeStyle = "red";
     
    5757}
    5858
     59let requestAnimationFrameId = NaN;
     60
    5961function cancelActions() {
     62    cancelAnimationFrame(requestAnimationFrameId);
     63    requestAnimationFrameId = NaN;
     64
     65    context.resetTransform();
     66    context.beginPath();
     67    context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    6068}
    6169
     
    98106        frames[index++]();
    99107        if (index < frames.length)
    100             timeoutID = setTimeout(executeFrameFunction, 0);
     108            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
    101109    };
    102110    executeFrameFunction();
  • trunk/LayoutTests/inspector/canvas/recording-webgl.html

    r237777 r243356  
    5050    texture = context.createTexture();
    5151
    52     document.body.appendChild(context.canvas);
     52    cancelActions();
    5353
    5454    runTest();
     
    6161}
    6262
    63 let timeoutID = NaN;
     63let requestAnimationFrameId = NaN;
    6464
    6565function cancelActions() {
    66     clearTimeout(timeoutID);
    67     timeoutID = NaN;
     66    cancelAnimationFrame(requestAnimationFrameId);
     67    requestAnimationFrameId = NaN;
    6868
    6969    context.clearColor(0.0, 0.0, 0.0, 0.0);
     
    503503        frames[index++]();
    504504        if (index < frames.length)
    505             timeoutID = setTimeout(executeFrameFunction, 0);
     505            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
    506506    };
    507507    executeFrameFunction();
  • trunk/LayoutTests/inspector/canvas/setRecordingAutoCaptureFrameCount.html

    r237681 r243356  
    77    window.internals.settings.setWebGLErrorsToConsoleEnabled(false);
    88
    9 let timeoutID = NaN;
     9let requestAnimationFrameId = NaN;
    1010
    1111function cancelActions() {
    12     clearTimeout(timeoutID);
    13     timeoutID = NaN;
     12    cancelAnimationFrame(requestAnimationFrameId);
     13    requestAnimationFrameId = NaN;
    1414}
    1515
     
    2020
    2121        if (index < frames.length)
    22             timeoutID = setTimeout(executeFrameFunction, 0);
     22            requestAnimationFrameId = requestAnimationFrame(executeFrameFunction);
    2323        else {
    2424            setTimeout(() => {
  • trunk/Source/WebCore/ChangeLog

    r243354 r243356  
     12019-03-21  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Safari Canvas Inspector seems to show the canvas being rendered twice per frame.
     4        https://bugs.webkit.org/show_bug.cgi?id=196082
     5        <rdar://problem/49113496>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Tests: inspector/canvas/recording-2d.html
     10               inspector/canvas/recording-bitmaprenderer.html
     11               inspector/canvas/recording-html-2d.html
     12               inspector/canvas/recording-webgl.html
     13               inspector/canvas/setRecordingAutoCaptureFrameCount.html
     14
     15        WebGL `<canvas>` follow a different "rendering" path such that `HTMLCanvasElement::paint`
     16        isn't called. Previously, there was a 0s timer that was started after the first action of a
     17        frame was recorded (for the case that the `<canvas>` isn't attached to the DOM) that would
     18        automatically stop the recording. It was possible that actions in two different "frame"s
     19        were recorded as part of the same frame, because the WebGL `<canvas>` would instead fall
     20        back to the timer to know when the "frame" had ended.
     21
     22        Now, there is additional instrumentation for the WebGL specific rendering path.
     23        Additionally, replace the 0s timer with a microtask for more "immediate" calling.
     24
     25        * html/HTMLCanvasElement.cpp:
     26        (WebCore::HTMLCanvasElement::paint):
     27        Ensure that the `InspectorInstrumentation` call is last. This matches what we expect, as
     28        before we were instrumenting right before is it about to paint.
     29
     30        * platform/graphics/GraphicsContext3D.h:
     31        (WebCore::GraphicsContext3D::Client::~Client): Added.
     32        (WebCore::GraphicsContext3D::addClient): Added.
     33        (WebCore::GraphicsContext3D::removeClient): Added.
     34        (WebCore::GraphicsContext3D::setWebGLContext): Deleted.
     35        * platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
     36        (WebCore::GraphicsContext3D::markLayerComposited):
     37        (WebCore::GraphicsContext3D::forceContextLost):
     38        (WebCore::GraphicsContext3D::recycleContext):
     39        (WebCore::GraphicsContext3D::dispatchContextChangedNotification):
     40        * html/canvas/WebGLRenderingContextBase.h:
     41        * html/canvas/WebGLRenderingContextBase.cpp:
     42        (WebCore::WebGLRenderingContextBase::WebGLRenderingContextBase):
     43        (WebCore::WebGLRenderingContextBase::destroyGraphicsContext3D):
     44        (WebCore::WebGLRenderingContextBase::didComposite): Added.
     45        (WebCore::WebGLRenderingContextBase::forceContextLost):
     46        (WebCore::WebGLRenderingContextBase::recycleContext):
     47        (WebCore::WebGLRenderingContextBase::dispatchContextChangedNotification): Added.
     48        (WebCore::WebGLRenderingContextBase::dispatchContextChangedEvent): Deleted.
     49        Introduce a `GraphicsContext3DClient` abstract class, rather than passing the
     50        `WebGLRenderingContextBase` directly to the `GraphicsContext3D` (layering violation).
     51        Notify the client whenever the `GraphicsContext3D` composites, which will in turn notify the
     52        `InspectorCanvasAgent` so that it knows that the "frame" is over.
     53
     54        * inspector/agents/InspectorCanvasAgent.h:
     55        * inspector/agents/InspectorCanvasAgent.cpp:
     56        (WebCore::InspectorCanvasAgent::InspectorCanvasAgent):
     57        (WebCore::InspectorCanvasAgent::requestNode):
     58        (WebCore::InspectorCanvasAgent::requestContent):
     59        (WebCore::InspectorCanvasAgent::requestCSSCanvasClientNodes):
     60        (WebCore::InspectorCanvasAgent::resolveCanvasContext):
     61        (WebCore::InspectorCanvasAgent::startRecording):
     62        (WebCore::InspectorCanvasAgent::stopRecording):
     63        (WebCore::InspectorCanvasAgent::requestShaderSource):
     64        (WebCore::InspectorCanvasAgent::updateShader):
     65        (WebCore::InspectorCanvasAgent::setShaderProgramDisabled):
     66        (WebCore::InspectorCanvasAgent::setShaderProgramHighlighted):
     67        (WebCore::InspectorCanvasAgent::didChangeCSSCanvasClientNodes):
     68        (WebCore::InspectorCanvasAgent::didChangeCanvasMemory):
     69        (WebCore::InspectorCanvasAgent::recordCanvasAction):
     70        (WebCore::InspectorCanvasAgent::canvasDestroyed):
     71        (WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
     72        (WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas):
     73        (WebCore::InspectorCanvasAgent::didEnableExtension):
     74        (WebCore::InspectorCanvasAgent::didCreateProgram):
     75        (WebCore::InspectorCanvasAgent::willDeleteProgram):
     76        (WebCore::InspectorCanvasAgent::isShaderProgramDisabled):
     77        (WebCore::InspectorCanvasAgent::isShaderProgramHighlighted):
     78        (WebCore::InspectorCanvasAgent::clearCanvasData):
     79        (WebCore::InspectorCanvasAgent::assertInspectorCanvas):
     80        (WebCore::InspectorCanvasAgent::findInspectorCanvas):
     81        (WebCore::InspectorCanvasAgent::assertInspectorProgram):
     82        (WebCore::InspectorCanvasAgent::findInspectorProgram):
     83        (WebCore::InspectorCanvasAgent::canvasRecordingTimerFired): Deleted.
     84        Replace raw pointers with `RefPtr`s. This is primarily used so that the microtask (instead
     85        of a timer) that is enqueued after the first action of each frame  is recorded can access a
     86        ref-counted instance of an `InspectorCanvas`, ensuring that it isn't destructed.
     87
     88        * inspector/InspectorCanvas.h:
     89        * inspector/InspectorCanvas.cpp:
     90        (WebCore::InspectorCanvas::canvasElement):
     91        (WebCore::InspectorCanvas::recordAction):
     92        (WebCore::InspectorCanvas::finalizeFrame):
     93        (WebCore::InspectorCanvas::releaseObjectForRecording): Added.
     94        (WebCore::InspectorCanvas::getCanvasContentAsDataURL):
     95        (WebCore::InspectorCanvas::appendActionSnapshotIfNeeded):
     96        (WebCore::InspectorCanvas::buildInitialState):
     97        (WebCore::InspectorCanvas::releaseInitialState): Deleted.
     98        (WebCore::InspectorCanvas::releaseFrames): Deleted.
     99        (WebCore::InspectorCanvas::releaseData): Deleted.
     100        Move the recording payload construction logic to `InspectorCanvas` so the actual data
     101        doesn't need to leave that class.
     102        Drive-by: unify the logic for getting the contents of a canvas from `InspectorCanvasAgent`.
     103
    11042019-03-21  Tim Horton  <timothy_horton@apple.com>
    2105
  • trunk/Source/WebCore/html/HTMLCanvasElement.cpp

    r243163 r243356  
    669669void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r)
    670670{
     671    // Clear the dirty rect
     672    m_dirtyRect = FloatRect();
     673
     674    if (!context.paintingDisabled()) {
     675        bool shouldPaint = true;
     676
     677        if (m_context) {
     678            shouldPaint = paintsIntoCanvasBuffer() || document().printing();
     679            if (shouldPaint)
     680                m_context->paintRenderingResultsToCanvas();
     681        }
     682
     683        if (shouldPaint) {
     684            if (hasCreatedImageBuffer()) {
     685                ImageBuffer* imageBuffer = buffer();
     686                if (imageBuffer) {
     687                    if (m_presentedImage) {
     688                        ImageOrientationDescription orientationDescription;
     689#if ENABLE(CSS_IMAGE_ORIENTATION)
     690                        orientationDescription.setImageOrientationEnum(renderer()->style().imageOrientation());
     691#endif
     692                        context.drawImage(*m_presentedImage, snappedIntRect(r), ImagePaintingOptions(orientationDescription));
     693                    } else
     694                        context.drawImageBuffer(*imageBuffer, snappedIntRect(r));
     695                }
     696            }
     697
     698            if (isGPUBased())
     699                downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited();
     700        }
     701    }
     702
    671703    if (UNLIKELY(m_context && m_context->callTracingActive()))
    672704        InspectorInstrumentation::didFinishRecordingCanvasFrame(*m_context);
    673 
    674     // Clear the dirty rect
    675     m_dirtyRect = FloatRect();
    676 
    677     if (context.paintingDisabled())
    678         return;
    679    
    680     if (m_context) {
    681         if (!paintsIntoCanvasBuffer() && !document().printing())
    682             return;
    683 
    684         m_context->paintRenderingResultsToCanvas();
    685     }
    686 
    687     if (hasCreatedImageBuffer()) {
    688         ImageBuffer* imageBuffer = buffer();
    689         if (imageBuffer) {
    690             if (m_presentedImage) {
    691                 ImageOrientationDescription orientationDescription;
    692 #if ENABLE(CSS_IMAGE_ORIENTATION)
    693                 orientationDescription.setImageOrientationEnum(renderer()->style().imageOrientation());
    694 #endif
    695                 context.drawImage(*m_presentedImage, snappedIntRect(r), ImagePaintingOptions(orientationDescription));
    696             } else
    697                 context.drawImageBuffer(*imageBuffer, snappedIntRect(r));
    698         }
    699     }
    700 
    701     if (isGPUBased())
    702         downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited();
    703705}
    704706
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp

    r243163 r243356  
    662662    m_contextGroup->addContext(*this);
    663663   
    664     m_context->setWebGLContext(this);
     664    m_context->addClient(*this);
    665665
    666666    m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
     
    915915
    916916    if (m_context) {
     917        m_context->removeClient(*this);
    917918        m_context->setContextLostCallback(nullptr);
    918919        m_context->setErrorMessageCallback(nullptr);
     
    50435044}
    50445045
    5045 void WebGLRenderingContextBase::recycleContext()
    5046 {
    5047     printToConsole(MessageLevel::Error, "There are too many active WebGL contexts on this page, the oldest context will be lost.");
    5048     // Using SyntheticLostContext means the developer won't be able to force the restoration
    5049     // of the context by calling preventDefault() in a "webglcontextlost" event handler.
    5050     forceLostContext(SyntheticLostContext);
    5051     destroyGraphicsContext3D();
    5052 }
    5053 
    50545046void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode)
    50555047{
     
    62266218}
    62276219
    6228 void WebGLRenderingContextBase::dispatchContextChangedEvent()
    6229 {
    6230     auto* canvas = htmlCanvas();
    6231     if (!canvas)
    6232         return;
    6233 
    6234     canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));
    6235 }
    6236 
    62376220void WebGLRenderingContextBase::simulateContextChanged()
    62386221{
     
    65146497}
    65156498
     6499void WebGLRenderingContextBase::didComposite()
     6500{
     6501    if (UNLIKELY(callTracingActive()))
     6502        InspectorInstrumentation::didFinishRecordingCanvasFrame(*this);
     6503}
     6504
     6505void WebGLRenderingContextBase::forceContextLost()
     6506{
     6507    forceLostContext(WebGLRenderingContextBase::RealLostContext);
     6508}
     6509
     6510void WebGLRenderingContextBase::recycleContext()
     6511{
     6512    printToConsole(MessageLevel::Error, "There are too many active WebGL contexts on this page, the oldest context will be lost.");
     6513    // Using SyntheticLostContext means the developer won't be able to force the restoration
     6514    // of the context by calling preventDefault() in a "webglcontextlost" event handler.
     6515    forceLostContext(SyntheticLostContext);
     6516    destroyGraphicsContext3D();
     6517}
     6518
     6519void WebGLRenderingContextBase::dispatchContextChangedNotification()
     6520{
     6521    auto* canvas = htmlCanvas();
     6522    if (!canvas)
     6523        return;
     6524
     6525    canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));
     6526}
     6527
     6528
    65166529} // namespace WebCore
    65176530
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h

    r239427 r243356  
    9595using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>, RefPtr<OffscreenCanvas>>;
    9696
    97 class WebGLRenderingContextBase : public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
     97class WebGLRenderingContextBase : public GraphicsContext3D::Client, public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
    9898public:
    9999    static std::unique_ptr<WebGLRenderingContextBase> create(CanvasBase&, WebGLContextAttributes&, const String&);
     
    331331    };
    332332    void forceLostContext(LostContextMode);
    333     void recycleContext();
    334333    void forceRestoreContext();
    335334    void loseContextImpl(LostContextMode);
    336     void dispatchContextChangedEvent();
    337335    WEBCORE_EXPORT void simulateContextChanged();
    338336
     
    359357    // Used for testing only, from Internals.
    360358    WEBCORE_EXPORT void setFailNextGPUStatusCheck();
     359
     360    // GraphicsContext3D::Client
     361    void didComposite() override;
     362    void forceContextLost() override;
     363    void recycleContext() override;
     364    void dispatchContextChangedNotification() override;
    361365
    362366protected:
  • trunk/Source/WebCore/inspector/InspectorCanvas.cpp

    r242759 r243356  
    9090HTMLCanvasElement* InspectorCanvas::canvasElement()
    9191{
    92     auto* canvasBase = &m_context.canvasBase();
    93     if (is<HTMLCanvasElement>(canvasBase))
    94         return downcast<HTMLCanvasElement>(canvasBase);
     92    if (is<HTMLCanvasElement>(m_context.canvasBase()))
     93        return &downcast<HTMLCanvasElement>(m_context.canvasBase());
    9594    return nullptr;
    9695}
     
    138137{
    139138    if (!m_initialState) {
     139        // We should only construct the initial state for the first action of the recording.
     140        ASSERT(!m_frames && !m_currentActions);
     141
    140142        m_initialState = buildInitialState();
    141143        m_bufferUsed += m_initialState->memoryCost();
     
    172174}
    173175
    174 RefPtr<Inspector::Protocol::Recording::InitialState>&& InspectorCanvas::releaseInitialState()
    175 {
    176     return WTFMove(m_initialState);
    177 }
    178 
    179 RefPtr<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>>&& InspectorCanvas::releaseFrames()
     176void InspectorCanvas::finalizeFrame()
    180177{
    181178    appendActionSnapshotIfNeeded();
    182179
    183     return WTFMove(m_frames);
    184 }
    185 
    186 RefPtr<JSON::ArrayOf<JSON::Value>>&& InspectorCanvas::releaseData()
    187 {
    188     m_indexedDuplicateData.clear();
    189     return WTFMove(m_serializedDuplicateData);
    190 }
    191 
    192 void InspectorCanvas::finalizeFrame()
    193 {
    194180    if (m_frames && m_frames->length() && !std::isnan(m_currentFrameStartTime)) {
    195181        auto currentFrame = static_cast<Inspector::Protocol::Recording::Frame*>(m_frames->get(m_frames->length() - 1).get());
     
    312298}
    313299
     300Ref<Inspector::Protocol::Recording::Recording> InspectorCanvas::releaseObjectForRecording()
     301{
     302    ASSERT(!m_currentActions);
     303    ASSERT(!m_actionNeedingSnapshot);
     304    ASSERT(!m_frames);
     305
     306    // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext
     307
     308    Inspector::Protocol::Recording::Type type;
     309    if (is<CanvasRenderingContext2D>(m_context))
     310        type = Inspector::Protocol::Recording::Type::Canvas2D;
     311    else if (is<ImageBitmapRenderingContext>(m_context))
     312        type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer;
     313#if ENABLE(WEBGL)
     314    else if (is<WebGLRenderingContext>(m_context))
     315        type = Inspector::Protocol::Recording::Type::CanvasWebGL;
     316#endif
     317    else {
     318        ASSERT_NOT_REACHED();
     319        type = Inspector::Protocol::Recording::Type::Canvas2D;
     320    }
     321
     322    auto recording = Inspector::Protocol::Recording::Recording::create()
     323        .setVersion(Inspector::Protocol::Recording::VERSION)
     324        .setType(type)
     325        .setInitialState(m_initialState.releaseNonNull())
     326        .setData(m_serializedDuplicateData.releaseNonNull())
     327        .release();
     328
     329    if (!m_recordingName.isEmpty())
     330        recording->setName(m_recordingName);
     331
     332    resetRecordingData();
     333
     334    return recording;
     335}
     336
     337String InspectorCanvas::getCanvasContentAsDataURL(ErrorString& errorString)
     338{
     339    // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebMetal context;
     340    if (!is<CanvasRenderingContext2D>(m_context)
     341#if ENABLE(WEBGL)
     342        && !is<WebGLRenderingContextBase>(m_context)
     343#endif
     344        && !is<ImageBitmapRenderingContext>(m_context)) {
     345        errorString = "Unsupported canvas context type"_s;
     346        return emptyString();
     347    }
     348
     349    // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations
     350    auto* node = canvasElement();
     351    if (!node) {
     352        errorString = "Context isn't related to an HTMLCanvasElement"_s;
     353        return emptyString();
     354    }
     355
     356#if ENABLE(WEBGL)
     357    if (is<WebGLRenderingContextBase>(m_context))
     358        downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(true);
     359#endif
     360
     361    ExceptionOr<UncachedString> result = node->toDataURL("image/png"_s);
     362
     363#if ENABLE(WEBGL)
     364    if (is<WebGLRenderingContextBase>(m_context))
     365        downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(false);
     366#endif
     367
     368    if (result.hasException()) {
     369        errorString = result.releaseException().releaseMessage();
     370        return emptyString();
     371    }
     372
     373    return result.releaseReturnValue().string;
     374}
     375
    314376void InspectorCanvas::appendActionSnapshotIfNeeded()
    315377{
     
    317379        return;
    318380
    319     m_actionNeedingSnapshot->addItem(indexForData(getCanvasContentAsDataURL()));
     381    m_bufferUsed -= m_actionNeedingSnapshot->memoryCost();
     382
     383    ErrorString ignored;
     384    m_actionNeedingSnapshot->addItem(indexForData(getCanvasContentAsDataURL(ignored)));
     385
     386    m_bufferUsed += m_actionNeedingSnapshot->memoryCost();
     387
    320388    m_actionNeedingSnapshot = nullptr;
    321 }
    322 
    323 String InspectorCanvas::getCanvasContentAsDataURL()
    324 {
    325     // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations
    326 
    327     auto* node = canvasElement();
    328     if (!node)
    329         return String();
    330 
    331 #if ENABLE(WEBGL)
    332     if (is<WebGLRenderingContextBase>(m_context))
    333         downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(true);
    334 #endif
    335 
    336     ExceptionOr<UncachedString> result = node->toDataURL("image/png"_s);
    337 
    338 #if ENABLE(WEBGL)
    339     if (is<WebGLRenderingContextBase>(m_context))
    340         downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(false);
    341 #endif
    342 
    343     if (result.hasException())
    344         return String();
    345 
    346     return result.releaseReturnValue().string;
    347389}
    348390
     
    562604        initialStatePayload->setParameters(WTFMove(parametersPayload));
    563605
    564     initialStatePayload->setContent(getCanvasContentAsDataURL());
     606    ErrorString ignored;
     607    initialStatePayload->setContent(getCanvasContentAsDataURL(ignored));
    565608
    566609    return initialStatePayload;
  • trunk/Source/WebCore/inspector/InspectorCanvas.h

    r239427 r243356  
    4545class ImageData;
    4646
     47typedef String ErrorString;
     48
    4749class InspectorCanvas final : public RefCounted<InspectorCanvas> {
    4850public:
     
    5961    void recordAction(const String&, Vector<RecordCanvasActionVariant>&& = { });
    6062
    61     RefPtr<Inspector::Protocol::Recording::InitialState>&& releaseInitialState();
    62     RefPtr<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>>&& releaseFrames();
    63     RefPtr<JSON::ArrayOf<JSON::Value>>&& releaseData();
     63    Ref<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>> releaseFrames() { return m_frames.releaseNonNull(); }
    6464
    6565    void finalizeFrame();
    6666    void markCurrentFrameIncomplete();
    6767
    68     const String& recordingName() const { return m_recordingName; }
    6968    void setRecordingName(const String& name) { m_recordingName = name; }
    7069
     
    7776
    7877    Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(bool captureBacktrace);
     78    Ref<Inspector::Protocol::Recording::Recording> releaseObjectForRecording();
     79
     80    String getCanvasContentAsDataURL(ErrorString&);
    7981
    8082private:
    8183    InspectorCanvas(CanvasRenderingContext&);
    8284    void appendActionSnapshotIfNeeded();
    83     String getCanvasContentAsDataURL();
    8485
    8586    using DuplicateDataVariant = Variant<
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp

    r243303 r243356  
    2727#include "InspectorCanvasAgent.h"
    2828
     29#include "ActiveDOMCallbackMicrotask.h"
    2930#include "CanvasRenderingContext.h"
    3031#include "CanvasRenderingContext2D.h"
     
    3839#include "JSExecState.h"
    3940#include "JSImageBitmapRenderingContext.h"
     41#include "Microtasks.h"
    4042#include "OffscreenCanvas.h"
    4143#include "ScriptState.h"
     
    7981    , m_inspectedPage(context.inspectedPage)
    8082    , m_canvasDestroyedTimer(*this, &InspectorCanvasAgent::canvasDestroyedTimerFired)
    81     , m_canvasRecordingTimer(*this, &InspectorCanvasAgent::canvasRecordingTimerFired)
    8283{
    8384}
     
    148149void InspectorCanvasAgent::requestNode(ErrorString& errorString, const String& canvasId, int* nodeId)
    149150{
    150     auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     151    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    151152    if (!inspectorCanvas)
    152153        return;
     
    169170void InspectorCanvasAgent::requestContent(ErrorString& errorString, const String& canvasId, String* content)
    170171{
    171     auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    172     if (!inspectorCanvas)
    173         return;
    174 
    175     // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations
    176 
    177     if (auto* node = inspectorCanvas->canvasElement()) {
    178         if (is<CanvasRenderingContext2D>(inspectorCanvas->context()) || is<ImageBitmapRenderingContext>(inspectorCanvas->context())) {
    179             auto result = node->toDataURL("image/png"_s);
    180             if (result.hasException()) {
    181                 errorString = result.releaseException().releaseMessage();
    182                 return;
    183             }
    184             *content = result.releaseReturnValue().string;
    185             return;
    186         }
    187 
    188 #if ENABLE(WEBGL)
    189         if (is<WebGLRenderingContextBase>(inspectorCanvas->context())) {
    190             WebGLRenderingContextBase& contextWebGLBase = downcast<WebGLRenderingContextBase>(inspectorCanvas->context());
    191 
    192             contextWebGLBase.setPreventBufferClearForInspector(true);
    193             auto result = node->toDataURL("image/png"_s);
    194             contextWebGLBase.setPreventBufferClearForInspector(false);
    195 
    196             if (result.hasException()) {
    197                 errorString = result.releaseException().releaseMessage();
    198                 return;
    199             }
    200             *content = result.releaseReturnValue().string;
    201             return;
    202         }
    203 #endif
    204     }
    205 
    206     // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebMetal context;
    207     errorString = "Unsupported canvas context type"_s;
     172    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     173    if (!inspectorCanvas)
     174        return;
     175
     176    *content = inspectorCanvas->getCanvasContentAsDataURL(errorString);
    208177}
    209178
    210179void InspectorCanvasAgent::requestCSSCanvasClientNodes(ErrorString& errorString, const String& canvasId, RefPtr<JSON::ArrayOf<int>>& result)
    211180{
    212     auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     181    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    213182    if (!inspectorCanvas)
    214183        return;
     
    251220void InspectorCanvasAgent::resolveCanvasContext(ErrorString& errorString, const String& canvasId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
    252221{
    253     auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     222    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    254223    if (!inspectorCanvas)
    255224        return;
     
    280249void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String& canvasId, const int* frameCount, const int* memoryLimit)
    281250{
    282     auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     251    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    283252    if (!inspectorCanvas)
    284253        return;
     
    299268void InspectorCanvasAgent::stopRecording(ErrorString& errorString, const String& canvasId)
    300269{
    301     auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     270    auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
    302271    if (!inspectorCanvas)
    303272        return;
     
    314283{
    315284#if ENABLE(WEBGL)
    316     auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     285    auto inspectorProgram = assertInspectorProgram(errorString, programId);
    317286    if (!inspectorProgram)
    318287        return;
     
    336305{
    337306#if ENABLE(WEBGL)
    338     auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     307    auto inspectorProgram = assertInspectorProgram(errorString, programId);
    339308    if (!inspectorProgram)
    340309        return;
     
    367336{
    368337#if ENABLE(WEBGL)
    369     auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     338    auto inspectorProgram = assertInspectorProgram(errorString, programId);
    370339    if (!inspectorProgram)
    371340        return;
     
    382351{
    383352#if ENABLE(WEBGL)
    384     auto* inspectorProgram = assertInspectorProgram(errorString, programId);
     353    auto inspectorProgram = assertInspectorProgram(errorString, programId);
    385354    if (!inspectorProgram)
    386355        return;
     
    425394    }
    426395
    427     auto* inspectorCanvas = findInspectorCanvas(*context);
     396    auto inspectorCanvas = findInspectorCanvas(*context);
    428397    ASSERT(inspectorCanvas);
    429398    if (!inspectorCanvas)
     
    451420void InspectorCanvasAgent::didChangeCanvasMemory(CanvasRenderingContext& context)
    452421{
    453     auto* inspectorCanvas = findInspectorCanvas(context);
     422    auto inspectorCanvas = findInspectorCanvas(context);
    454423    ASSERT(inspectorCanvas);
    455424    if (!inspectorCanvas)
     
    464433void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters)
    465434{
    466     auto* inspectorCanvas = findInspectorCanvas(canvasRenderingContext);
     435    auto inspectorCanvas = findInspectorCanvas(canvasRenderingContext);
    467436    ASSERT(inspectorCanvas);
    468437    if (!inspectorCanvas)
     
    473442        return;
    474443
     444    // Only enqueue a microtask for the first action of each frame. Any subsequent actions will be
     445    // covered by the initial microtask until the next frame.
     446    if (!inspectorCanvas->currentFrameHasData()) {
     447        if (auto* scriptExecutionContext = inspectorCanvas->context().canvasBase().scriptExecutionContext()) {
     448            auto& queue = MicrotaskQueue::mainThreadQueue();
     449            queue.append(std::make_unique<ActiveDOMCallbackMicrotask>(queue, *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
     450                if (auto* canvasElement = protectedInspectorCanvas->canvasElement()) {
     451                    if (canvasElement->isDescendantOf(canvasElement->document()))
     452                        return;
     453                }
     454
     455                if (protectedInspectorCanvas->context().callTracingActive())
     456                    didFinishRecordingCanvasFrame(protectedInspectorCanvas->context());
     457            }));
     458        }
     459    }
     460
    475461    inspectorCanvas->recordAction(name, WTFMove(parameters));
    476 
    477     if (!m_canvasRecordingTimer.isActive())
    478         m_canvasRecordingTimer.startOneShot(0_s);
    479462
    480463    if (!inspectorCanvas->hasBufferSpace())
     
    488471        return;
    489472
    490     auto* inspectorCanvas = findInspectorCanvas(*context);
     473    auto inspectorCanvas = findInspectorCanvas(*context);
     474    ASSERT(inspectorCanvas);
    491475    if (!inspectorCanvas)
    492476        return;
     
    505489void InspectorCanvasAgent::didFinishRecordingCanvasFrame(CanvasRenderingContext& context, bool forceDispatch)
    506490{
    507     auto* inspectorCanvas = findInspectorCanvas(context);
     491    auto inspectorCanvas = findInspectorCanvas(context);
    508492    ASSERT(inspectorCanvas);
    509493    if (!inspectorCanvas)
     
    516500        if (forceDispatch) {
    517501            m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), nullptr);
    518 
    519502            inspectorCanvas->resetRecordingData();
    520503        }
     
    532515        return;
    533516
    534     // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext
    535 
    536     Inspector::Protocol::Recording::Type type;
    537     if (is<CanvasRenderingContext2D>(inspectorCanvas->context()))
    538         type = Inspector::Protocol::Recording::Type::Canvas2D;
    539     else if (is<ImageBitmapRenderingContext>(inspectorCanvas->context()))
    540         type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer;
    541 #if ENABLE(WEBGL)
    542     else if (is<WebGLRenderingContext>(inspectorCanvas->context()))
    543         type = Inspector::Protocol::Recording::Type::CanvasWebGL;
    544 #endif
    545     else {
    546         ASSERT_NOT_REACHED();
    547         type = Inspector::Protocol::Recording::Type::Canvas2D;
    548     }
    549 
    550     auto recording = Inspector::Protocol::Recording::Recording::create()
    551         .setVersion(Inspector::Protocol::Recording::VERSION)
    552         .setType(type)
    553         .setInitialState(inspectorCanvas->releaseInitialState())
    554         .setData(inspectorCanvas->releaseData())
    555         .release();
    556 
    557     const String& name = inspectorCanvas->recordingName();
    558     if (!name.isEmpty())
    559         recording->setName(name);
    560 
    561     m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), WTFMove(recording));
    562 
    563     inspectorCanvas->resetRecordingData();
     517    m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), inspectorCanvas->releaseObjectForRecording());
    564518}
    565519
    566520void InspectorCanvasAgent::consoleStartRecordingCanvas(CanvasRenderingContext& context, JSC::ExecState& exec, JSC::JSObject* options)
    567521{
    568     auto* inspectorCanvas = findInspectorCanvas(context);
     522    auto inspectorCanvas = findInspectorCanvas(context);
    569523    ASSERT(inspectorCanvas);
    570524    if (!inspectorCanvas)
     
    588542void InspectorCanvasAgent::didEnableExtension(WebGLRenderingContextBase& context, const String& extension)
    589543{
    590     auto* inspectorCanvas = findInspectorCanvas(context);
     544    auto inspectorCanvas = findInspectorCanvas(context);
    591545    ASSERT(inspectorCanvas);
    592546    if (!inspectorCanvas)
     
    598552void InspectorCanvasAgent::didCreateProgram(WebGLRenderingContextBase& context, WebGLProgram& program)
    599553{
    600     auto* inspectorCanvas = findInspectorCanvas(context);
     554    auto inspectorCanvas = findInspectorCanvas(context);
    601555    ASSERT(inspectorCanvas);
    602556    if (!inspectorCanvas)
     
    611565void InspectorCanvasAgent::willDeleteProgram(WebGLProgram& program)
    612566{
    613     auto* inspectorProgram = findInspectorProgram(program);
     567    auto inspectorProgram = findInspectorProgram(program);
    614568    if (!inspectorProgram)
    615569        return;
     
    621575bool InspectorCanvasAgent::isShaderProgramDisabled(WebGLProgram& program)
    622576{
    623     auto* inspectorProgram = findInspectorProgram(program);
     577    auto inspectorProgram = findInspectorProgram(program);
     578    ASSERT(inspectorProgram);
    624579    if (!inspectorProgram)
    625580        return false;
     
    630585bool InspectorCanvasAgent::isShaderProgramHighlighted(WebGLProgram& program)
    631586{
    632     auto* inspectorProgram = findInspectorProgram(program);
     587    auto inspectorProgram = findInspectorProgram(program);
     588    ASSERT(inspectorProgram);
    633589    if (!inspectorProgram)
    634590        return false;
     
    675631}
    676632
    677 void InspectorCanvasAgent::canvasRecordingTimerFired()
    678 {
    679     for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
    680         if (!inspectorCanvas->context().callTracingActive())
    681             continue;
    682 
    683         didFinishRecordingCanvasFrame(inspectorCanvas->context());
    684     }
    685 }
    686 
    687633void InspectorCanvasAgent::clearCanvasData()
    688634{
     
    691637
    692638    m_identifierToInspectorCanvas.clear();
     639#if ENABLE(WEBGL)
     640    m_identifierToInspectorProgram.clear();
    693641    m_removedCanvasIdentifiers.clear();
    694 #if ENABLE(WEBGL)
    695     m_identifierToInspectorProgram.clear();
    696 #endif
    697 
    698     if (m_canvasRecordingTimer.isActive())
    699         m_canvasRecordingTimer.stop();
     642#endif
    700643
    701644    if (m_canvasDestroyedTimer.isActive())
     
    746689}
    747690
    748 InspectorCanvas* InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier)
    749 {
    750     RefPtr<InspectorCanvas> inspectorCanvas = m_identifierToInspectorCanvas.get(identifier);
     691RefPtr<InspectorCanvas> InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier)
     692{
     693    auto inspectorCanvas = m_identifierToInspectorCanvas.get(identifier);
    751694    if (!inspectorCanvas) {
    752695        errorString = "No canvas for given identifier."_s;
     
    754697    }
    755698
    756     return inspectorCanvas.get();
    757 }
    758 
    759 InspectorCanvas* InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context)
     699    return inspectorCanvas;
     700}
     701
     702RefPtr<InspectorCanvas> InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context)
    760703{
    761704    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {
    762705        if (&inspectorCanvas->context() == &context)
    763             return inspectorCanvas.get();
     706            return inspectorCanvas;
    764707    }
    765708
     
    776719}
    777720
    778 InspectorShaderProgram* InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier)
    779 {
    780     RefPtr<InspectorShaderProgram> inspectorProgram = m_identifierToInspectorProgram.get(identifier);
     721RefPtr<InspectorShaderProgram> InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier)
     722{
     723    auto inspectorProgram = m_identifierToInspectorProgram.get(identifier);
    781724    if (!inspectorProgram) {
    782725        errorString = "No shader program for given identifier."_s;
     
    784727    }
    785728
    786     return inspectorProgram.get();
    787 }
    788 
    789 InspectorShaderProgram* InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program)
     729    return inspectorProgram;
     730}
     731
     732RefPtr<InspectorShaderProgram> InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program)
    790733{
    791734    for (auto& inspectorProgram : m_identifierToInspectorProgram.values()) {
    792735        if (&inspectorProgram->program() == &program)
    793             return inspectorProgram.get();
     736            return inspectorProgram;
    794737    }
    795738
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.h

    r243303 r243356  
    113113
    114114    void canvasDestroyedTimerFired();
    115     void canvasRecordingTimerFired();
    116115    void clearCanvasData();
    117116    InspectorCanvas& bindCanvas(CanvasRenderingContext&, bool captureBacktrace);
    118117    String unbindCanvas(InspectorCanvas&);
    119     InspectorCanvas* assertInspectorCanvas(ErrorString&, const String& identifier);
    120     InspectorCanvas* findInspectorCanvas(CanvasRenderingContext&);
     118    RefPtr<InspectorCanvas> assertInspectorCanvas(ErrorString&, const String& identifier);
     119    RefPtr<InspectorCanvas> findInspectorCanvas(CanvasRenderingContext&);
    121120#if ENABLE(WEBGL)
    122121    String unbindProgram(InspectorShaderProgram&);
    123     InspectorShaderProgram* assertInspectorProgram(ErrorString&, const String& identifier);
    124     InspectorShaderProgram* findInspectorProgram(WebGLProgram&);
    125 
    126     HashMap<String, RefPtr<InspectorShaderProgram>> m_identifierToInspectorProgram;
     122    RefPtr<InspectorShaderProgram> assertInspectorProgram(ErrorString&, const String& identifier);
     123    RefPtr<InspectorShaderProgram> findInspectorProgram(WebGLProgram&);
    127124#endif
    128125
     
    134131
    135132    HashMap<String, RefPtr<InspectorCanvas>> m_identifierToInspectorCanvas;
     133#if ENABLE(WEBGL)
     134    HashMap<String, RefPtr<InspectorShaderProgram>> m_identifierToInspectorProgram;
     135#endif
    136136    Vector<String> m_removedCanvasIdentifiers;
     137
    137138    Optional<size_t> m_recordingAutoCaptureFrameCount;
     139
    138140    Timer m_canvasDestroyedTimer;
    139     Timer m_canvasRecordingTimer;
    140141};
    141142
  • trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h

    r242205 r243356  
    121121class GraphicsContext3D : public RefCounted<GraphicsContext3D> {
    122122public:
     123    class Client {
     124    public:
     125        virtual ~Client() { }
     126        virtual void didComposite() = 0;
     127        virtual void forceContextLost() = 0;
     128        virtual void recycleContext() = 0;
     129        virtual void dispatchContextChangedNotification() = 0;
     130    };
     131
    123132    enum {
    124133        // WebGL 1 constants
     
    765774
    766775    bool makeContextCurrent();
    767     void setWebGLContext(WebGLRenderingContextBase* base) { m_webglContext = base; }
     776
     777    void addClient(Client& client) { m_clients.add(&client); }
     778    void removeClient(Client& client) { m_clients.remove(&client); }
    768779
    769780    // With multisampling on, blit from multisampleFBO to regular FBO.
     
    15081519#endif
    15091520
    1510     // FIXME: Layering violation.
    1511     WebGLRenderingContextBase* m_webglContext { nullptr };
     1521    HashSet<Client*> m_clients;
    15121522
    15131523    bool m_isForWebGL2 { false };
  • trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp

    r242205 r243356  
    20172017{
    20182018    m_layerComposited = true;
     2019
     2020    for (auto* client : m_clients)
     2021        client->didComposite();
    20192022}
    20202023
     
    20262029void GraphicsContext3D::forceContextLost()
    20272030{
    2028 #if ENABLE(WEBGL)
    2029     if (m_webglContext)
    2030         m_webglContext->forceLostContext(WebGLRenderingContextBase::RealLostContext);
    2031 #endif
     2031    for (auto* client : m_clients)
     2032        client->forceContextLost();
    20322033}
    20332034
    20342035void GraphicsContext3D::recycleContext()
    20352036{
    2036 #if ENABLE(WEBGL)
    2037     if (m_webglContext)
    2038         m_webglContext->recycleContext();
    2039 #endif
     2037    for (auto* client : m_clients)
     2038        client->recycleContext();
    20402039}
    20412040
    20422041void GraphicsContext3D::dispatchContextChangedNotification()
    20432042{
    2044 #if ENABLE(WEBGL)
    2045     if (m_webglContext)
    2046         m_webglContext->dispatchContextChangedEvent();
    2047 #endif
     2043    for (auto* client : m_clients)
     2044        client->dispatchContextChangedNotification();
    20482045}
    20492046
Note: See TracChangeset for help on using the changeset viewer.