Changeset 239067 in webkit


Ignore:
Timestamp:
Dec 10, 2018 7:55:49 PM (5 years ago)
Author:
Justin Michaud
Message:

CS Painting API should support multiple worklets.
https://bugs.webkit.org/show_bug.cgi?id=192335

Reviewed by Dean Jackson.

Source/WebCore:

Adds a new map to support separate paint worklet global scopes (one for each worklet). Also
adds some tests and a fix for a repaint bug that this oncovered, where changing a custom property required
for paint would not trigger a repaint if there had not been a valid value set before.

Test: fast/css-custom-paint/multiple-worklets.html

  • css/CSSPaintImageValue.cpp:

(WebCore::CSSPaintImageValue::image):

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::applyProperty):

  • dom/Document.cpp:

(WebCore::Document::prepareForDestruction):
(WebCore::Document::paintWorkletGlobalScope):
(WebCore::Document::setPaintWorkletGlobalScope):

  • dom/Document.h:

(WebCore::Document::paintWorkletGlobalScope): Deleted.

  • rendering/style/RenderStyle.cpp:

(WebCore::changedCustomPaintWatchedProperty):

  • worklets/Worklet.cpp:

(WebCore::Worklet::addModule):

  • worklets/WorkletGlobalScope.cpp:

(WebCore::WorkletGlobalScope::prepareForDestruction):

LayoutTests:

  • fast/css-custom-paint/animate-repaint-expected.txt:
  • fast/css-custom-paint/animate-repaint.html:
  • fast/css-custom-paint/delay-expected.html: Added.
  • fast/css-custom-paint/delay-repaint-expected.txt: Copied from LayoutTests/fast/css-custom-paint/animate-repaint-expected.txt.
  • fast/css-custom-paint/delay-repaint.html: Copied from LayoutTests/fast/css-custom-paint/animate-repaint.html.
  • fast/css-custom-paint/delay.html: Copied from LayoutTests/fast/css-custom-paint/animate-repaint.html.
  • fast/css-custom-paint/multiple-worklets-expected.html: Added.
  • fast/css-custom-paint/multiple-worklets.html: Added.
Location:
trunk
Files:
5 added
11 edited
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r239064 r239067  
     12018-12-10  Justin Michaud  <justin_michaud@apple.com>
     2
     3        CS Painting API should support multiple worklets.
     4        https://bugs.webkit.org/show_bug.cgi?id=192335
     5
     6        Reviewed by Dean Jackson.
     7
     8        * fast/css-custom-paint/animate-repaint-expected.txt:
     9        * fast/css-custom-paint/animate-repaint.html:
     10        * fast/css-custom-paint/delay-expected.html: Added.
     11        * fast/css-custom-paint/delay-repaint-expected.txt: Copied from LayoutTests/fast/css-custom-paint/animate-repaint-expected.txt.
     12        * fast/css-custom-paint/delay-repaint.html: Copied from LayoutTests/fast/css-custom-paint/animate-repaint.html.
     13        * fast/css-custom-paint/delay.html: Copied from LayoutTests/fast/css-custom-paint/animate-repaint.html.
     14        * fast/css-custom-paint/multiple-worklets-expected.html: Added.
     15        * fast/css-custom-paint/multiple-worklets.html: Added.
     16
    1172018-12-10  Youenn Fablet  <youenn@apple.com>
    218
  • trunk/LayoutTests/fast/css-custom-paint/animate-repaint-expected.txt

    r238686 r239067  
    11(repaint rects
    2   (rect 0 0 800 600)
    3   (rect 0 0 150 150)
    4   (rect 8 8 784 150)
    5   (rect 0 0 800 166)
    62  (rect 0 0 800 600)
    73  (rect 8 8 150 150)
  • trunk/LayoutTests/fast/css-custom-paint/animate-repaint.html

    r238686 r239067  
    2323
    2424<script type="text/javascript">
    25   if (window.testRunner && window.internals) {
    26     window.testRunner.dumpAsText(false);
    27     window.internals.startTrackingRepaints();
     25  function onload() {
     26    if (window.testRunner && window.internals) {
     27      window.testRunner.dumpAsText(false);
     28      window.internals.startTrackingRepaints();
     29    }
     30    importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
     31
     32    // FIXME: Once importWorklet returns a promise, these setTimeouts should go away.
     33    setTimeout(function() {
     34      document.getElementById('paint').style.setProperty('--my-prop', 'goodbye');
     35    }, 500);
     36
     37    setTimeout(function() {
     38      var repaintRects = "No test runner";
     39      if (window.testRunner && window.internals) {
     40        // force a style recalc.
     41        var dummy = document.body.offsetTop;
     42        repaintRects = window.internals.repaintRectsAsText();
     43        window.internals.stopTrackingRepaints();
     44      }
     45
     46      var pre = document.createElement('pre');
     47      document.body.appendChild(pre);
     48      pre.innerHTML = repaintRects;
     49    }, 1000);
    2850  }
    29   importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
    30 
    31   // FIXME: Once importWorklet returns a promise, these setTimeouts should go away.
    32   setTimeout(function() {
    33     document.getElementById('paint').style.setProperty('--my-prop', 'goodbye');
    34   }, 500);
    35 
    36   setTimeout(function() {
    37     var repaintRects = "No test runner";
    38     if (window.testRunner && window.internals) {
    39       window.internals.startTrackingRepaints();
    40 
    41       // force a style recalc.
    42       var dummy = document.body.offsetTop;
    43 
    44       repaintRects = window.internals.repaintRectsAsText();
    45 
    46       window.internals.stopTrackingRepaints();
    47     }
    48 
    49     var pre = document.createElement('pre');
    50     document.body.appendChild(pre);
    51     pre.innerHTML = repaintRects;
    52   }, 1000);
    5351</script>
    5452
     
    6260</style>
    6361
    64 <body>
     62<body onload="onload()">
    6563  <div id="paint"></div>
    6664</body>
  • trunk/LayoutTests/fast/css-custom-paint/delay-repaint-expected.txt

    r239066 r239067  
    11(repaint rects
    2   (rect 0 0 800 600)
    3   (rect 0 0 150 150)
    4   (rect 8 8 784 150)
    5   (rect 0 0 800 166)
    62  (rect 0 0 800 600)
    73  (rect 8 8 150 150)
  • trunk/LayoutTests/fast/css-custom-paint/delay-repaint.html

    r239066 r239067  
    11<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
    22<meta name="author" title="Justin Michaud" href="mailto:justin_michaud@webkit.org">
    3 <meta name="assert" content="Test that paint worklets repaint when properties change">
     3<meta name="assert" content="Test that paint worklets repaint when modules are added, and correctly watch properties">
    44<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
    55<script src="resources/testharness.js"></script>
     
    1010
    1111    paint(ctx, geom, properties) {
    12       if (properties.get('--my-prop').toString() != "goodbye") {
     12      if (properties.get('--my-prop') == 5) {
     13        ctx.fillStyle = "green";
     14      } else {
    1315        ctx.fillStyle = "red";
    14       } else {
    15         ctx.fillStyle = "green";
    1616      }
    17 
    1817      ctx.fillRect(0, 0, geom.width, geom.height);
    1918    }
     
    2322
    2423<script type="text/javascript">
     24function onload() {
    2525  if (window.testRunner && window.internals) {
    2626    window.testRunner.dumpAsText(false);
    2727    window.internals.startTrackingRepaints();
    2828  }
    29   importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
    3029
    3130  // FIXME: Once importWorklet returns a promise, these setTimeouts should go away.
    3231  setTimeout(function() {
    33     document.getElementById('paint').style.setProperty('--my-prop', 'goodbye');
     32    importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
    3433  }, 500);
     34
     35  setTimeout(function() {
     36    paint.style.setProperty('--my-prop', 5);
     37  }, 2000);
    3538
    3639  setTimeout(function() {
    3740    var repaintRects = "No test runner";
    3841    if (window.testRunner && window.internals) {
    39       window.internals.startTrackingRepaints();
    40 
    4142      // force a style recalc.
    4243      var dummy = document.body.offsetTop;
    43 
    4444      repaintRects = window.internals.repaintRectsAsText();
    45 
    4645      window.internals.stopTrackingRepaints();
    4746    }
     
    5049    document.body.appendChild(pre);
    5150    pre.innerHTML = repaintRects;
    52   }, 1000);
     51  }, 2500);
     52}
    5353</script>
    5454
     
    5656  #paint {
    5757    background-image: paint(my-paint);
    58     --my-prop: hello;
    5958    width: 150px;
    6059    height: 150px;
     
    6261</style>
    6362
    64 <body>
     63<body onload="onload()">
    6564  <div id="paint"></div>
    6665</body>
  • trunk/LayoutTests/fast/css-custom-paint/delay.html

    r239066 r239067  
    11<!DOCTYPE html><!-- webkit-test-runner [ experimental:CSSPaintingAPIEnabled=true ] -->
    22<meta name="author" title="Justin Michaud" href="mailto:justin_michaud@webkit.org">
    3 <meta name="assert" content="Test that paint worklets repaint when properties change">
     3<meta name="assert" content="Test that paint worklets repaint when modules are added, and correctly watch properties">
    44<link rel="help" content="https://drafts.css-houdini.org/css-paint-api-1/">
    55<script src="resources/testharness.js"></script>
     
    1010
    1111    paint(ctx, geom, properties) {
    12       if (properties.get('--my-prop').toString() != "goodbye") {
     12      if (properties.get('--my-prop') == 5) {
     13        ctx.fillStyle = "green";
     14      } else {
    1315        ctx.fillStyle = "red";
    14       } else {
    15         ctx.fillStyle = "green";
    1616      }
    17 
    1817      ctx.fillRect(0, 0, geom.width, geom.height);
    1918    }
     
    2322
    2423<script type="text/javascript">
    25   if (window.testRunner && window.internals) {
    26     window.testRunner.dumpAsText(false);
    27     window.internals.startTrackingRepaints();
    28   }
    29   importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
    30 
    31   // FIXME: Once importWorklet returns a promise, these setTimeouts should go away.
    3224  setTimeout(function() {
    33     document.getElementById('paint').style.setProperty('--my-prop', 'goodbye');
     25    importWorklet(CSS.paintWorklet, document.getElementById('code').textContent);
    3426  }, 500);
    35 
     27  // FIXME: This should use a promise once addModule supports it.
    3628  setTimeout(function() {
    37     var repaintRects = "No test runner";
    38     if (window.testRunner && window.internals) {
    39       window.internals.startTrackingRepaints();
    40 
    41       // force a style recalc.
    42       var dummy = document.body.offsetTop;
    43 
    44       repaintRects = window.internals.repaintRectsAsText();
    45 
    46       window.internals.stopTrackingRepaints();
    47     }
    48 
    49     var pre = document.createElement('pre');
    50     document.body.appendChild(pre);
    51     pre.innerHTML = repaintRects;
    52   }, 1000);
     29    paint.style.setProperty('--my-prop', 5);
     30  }, 2000);
    5331</script>
    5432
     
    5634  #paint {
    5735    background-image: paint(my-paint);
    58     --my-prop: hello;
    5936    width: 150px;
    6037    height: 150px;
  • trunk/Source/WebCore/ChangeLog

    r239065 r239067  
     12018-12-10  Justin Michaud  <justin_michaud@apple.com>
     2
     3        CS Painting API should support multiple worklets.
     4        https://bugs.webkit.org/show_bug.cgi?id=192335
     5
     6        Reviewed by Dean Jackson.
     7
     8        Adds a new map to support separate paint worklet global scopes (one for each worklet). Also
     9        adds some tests and a fix for a repaint bug that this oncovered, where changing a custom property required
     10        for paint would not trigger a repaint if there had not been a valid value set before.
     11
     12        Test: fast/css-custom-paint/multiple-worklets.html
     13
     14        * css/CSSPaintImageValue.cpp:
     15        (WebCore::CSSPaintImageValue::image):
     16        * css/StyleResolver.cpp:
     17        (WebCore::StyleResolver::applyProperty):
     18        * dom/Document.cpp:
     19        (WebCore::Document::prepareForDestruction):
     20        (WebCore::Document::paintWorkletGlobalScope):
     21        (WebCore::Document::setPaintWorkletGlobalScope):
     22        * dom/Document.h:
     23        (WebCore::Document::paintWorkletGlobalScope): Deleted.
     24        * rendering/style/RenderStyle.cpp:
     25        (WebCore::changedCustomPaintWatchedProperty):
     26        * worklets/Worklet.cpp:
     27        (WebCore::Worklet::addModule):
     28        * worklets/WorkletGlobalScope.cpp:
     29        (WebCore::WorkletGlobalScope::prepareForDestruction):
     30
    1312018-12-10  Youenn Fablet  <youenn@apple.com>
    232
  • trunk/Source/WebCore/css/CSSPaintImageValue.cpp

    r238872 r239067  
    5252    if (size.isEmpty())
    5353        return nullptr;
    54     auto* selectedGlobalScope = renderElement.document().paintWorkletGlobalScope();
     54    auto* selectedGlobalScope = renderElement.document().paintWorkletGlobalScopeForName(m_name);
    5555    if (!selectedGlobalScope)
    5656        return nullptr;
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r238686 r239067  
    17211721
    17221722#if ENABLE(CSS_PAINTING_API)
    1723     if (is<CSSPaintImageValue>(*valueToApply) && document().paintWorkletGlobalScope()) {
    1724         // FIXME: This should use the "document paint registration map" from the spec, once it is implemented.
    1725         auto& paintWorklet = *document().paintWorkletGlobalScope();
    1726         auto locker = holdLock(paintWorklet.paintDefinitionLock());
    1727         if (auto* registration = paintWorklet.paintDefinitionMap().get(downcast<CSSPaintImageValue>(*valueToApply).name())) {
    1728             for (auto& property : registration->inputProperties)
    1729                 state.style()->addCustomPaintWatchProperty(property);
     1723    if (is<CSSPaintImageValue>(*valueToApply)) {
     1724        auto& name = downcast<CSSPaintImageValue>(*valueToApply).name();
     1725        if (auto* paintWorklet = document().paintWorkletGlobalScopeForName(name)) {
     1726            auto locker = holdLock(paintWorklet->paintDefinitionLock());
     1727            if (auto* registration = paintWorklet->paintDefinitionMap().get(name)) {
     1728                for (auto& property : registration->inputProperties)
     1729                    state.style()->addCustomPaintWatchProperty(property);
     1730            }
    17301731        }
    17311732    }
  • trunk/Source/WebCore/dom/Document.cpp

    r239057 r239067  
    25632563
    25642564#if ENABLE(CSS_PAINTING_API)
    2565     if (m_paintWorkletGlobalScope) {
    2566         m_paintWorkletGlobalScope->prepareForDestruction();
    2567         m_paintWorkletGlobalScope = nullptr;
    2568     }
     2565    for (auto& scope : m_paintWorkletGlobalScopes.values())
     2566        scope->prepareForDestruction();
     2567    m_paintWorkletGlobalScopes.clear();
    25692568#endif
    25702569
     
    85188517}
    85198518
    8520 void Document::setPaintWorkletGlobalScope(Ref<PaintWorkletGlobalScope>&& scope)
    8521 {
    8522     m_paintWorkletGlobalScope = WTFMove(scope);
     8519PaintWorkletGlobalScope* Document::paintWorkletGlobalScopeForName(const String& name)
     8520{
     8521    return m_paintWorkletGlobalScopes.get(name);
     8522}
     8523
     8524void Document::setPaintWorkletGlobalScopeForName(const String& name, Ref<PaintWorkletGlobalScope>&& scope)
     8525{
     8526    auto addResult = m_paintWorkletGlobalScopes.add(name, WTFMove(scope));
     8527    ASSERT_UNUSED(addResult, addResult);
    85238528}
    85248529#endif
  • trunk/Source/WebCore/dom/Document.h

    r239057 r239067  
    15231523#if ENABLE(CSS_PAINTING_API)
    15241524    Worklet& ensurePaintWorklet();
    1525     PaintWorkletGlobalScope* paintWorkletGlobalScope() { return m_paintWorkletGlobalScope.get(); }
    1526     void setPaintWorkletGlobalScope(Ref<PaintWorkletGlobalScope>&&);
     1525    PaintWorkletGlobalScope* paintWorkletGlobalScopeForName(const String& name);
     1526    void setPaintWorkletGlobalScopeForName(const String& name, Ref<PaintWorkletGlobalScope>&&);
    15271527#endif
    15281528
     
    20732073#if ENABLE(CSS_PAINTING_API)
    20742074    RefPtr<Worklet> m_paintWorklet;
    2075     RefPtr<PaintWorkletGlobalScope> m_paintWorkletGlobalScope;
     2075    HashMap<String, Ref<PaintWorkletGlobalScope>> m_paintWorkletGlobalScopes;
    20762076#endif
    20772077
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r238968 r239067  
    990990                RefPtr<CSSValue> valueA;
    991991                RefPtr<CSSValue> valueB;
    992                 if (isCustomPropertyName(name) && a.getCustomProperty(name) && b.getCustomProperty(name)) {
    993                     valueA = CSSCustomPropertyValue::create(*a.getCustomProperty(name));
    994                     valueB = CSSCustomPropertyValue::create(*b.getCustomProperty(name));
     992                if (isCustomPropertyName(name)) {
     993                    if (a.getCustomProperty(name))
     994                        valueA = CSSCustomPropertyValue::create(*a.getCustomProperty(name));
     995                    if (b.getCustomProperty(name))
     996                        valueB = CSSCustomPropertyValue::create(*b.getCustomProperty(name));
    995997                } else {
    996998                    CSSPropertyID propertyID = cssPropertyID(name);
  • trunk/Source/WebCore/worklets/Worklet.cpp

    r237766 r239067  
    5050    auto context = PaintWorkletGlobalScope::create(document, ScriptSourceCode(moduleURL));
    5151    context->evaluate();
    52     // FIXME: We should store multiple global scopes and choose between them
    53     // This will not function correctly if multiple modules are added.
    54     document.setPaintWorkletGlobalScope(WTFMove(context));
     52
     53    auto locker = holdLock(context->paintDefinitionLock());
     54    for (auto& name : context->paintDefinitionMap().keys())
     55        document.setPaintWorkletGlobalScopeForName(name, makeRef(context.get()));
    5556}
    5657
  • trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp

    r238686 r239067  
    7575void WorkletGlobalScope::prepareForDestruction()
    7676{
    77     ASSERT(m_script);
     77    if (!m_script)
     78        return;
    7879    stopActiveDOMObjects();
    7980    removeRejectedPromiseTracker();
Note: See TracChangeset for help on using the changeset viewer.