Bug 273239 - [Skia] Fix corner cases involving drawing shadows
Summary: [Skia] Fix corner cases involving drawing shadows
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WPE WebKit (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Pawel Lampe
URL:
Keywords:
Depends on:
Blocks: GLibSkia
  Show dependency treegraph
 
Reported: 2024-04-25 02:46 PDT by Pawel Lampe
Modified: 2024-06-14 03:58 PDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pawel Lampe 2024-04-25 02:46:31 PDT
See LayoutTests failures such as:

imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.composite.1.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.composite.1.worker.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.composite.2.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.composite.2.worker.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.enable.blur.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.enable.blur.worker.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.enable.x.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.enable.x.worker.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.enable.y.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.enable.y.worker.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.image.alpha.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.image.basic.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.image.scale.html
imported/w3c/web-platform-tests/html/canvas/offscreen/shadows/2d.shadow.image.transparent.2.html
Comment 1 Pawel Lampe 2024-04-25 03:10:27 PDT
See more LayoutTests failures such as:

imported/w3c/web-platform-tests/html/canvas/element/shadows/2d.shadow.composite.1.html
imported/w3c/web-platform-tests/html/canvas/element/shadows/2d.shadow.composite.2.html
imported/w3c/web-platform-tests/html/canvas/element/shadows/2d.shadow.enable.blur.html
imported/w3c/web-platform-tests/html/canvas/element/shadows/2d.shadow.enable.x.html
imported/w3c/web-platform-tests/html/canvas/element/shadows/2d.shadow.enable.y.html
css3/color-filters/color-filter-text-decoration-shadow.html
fast/canvas/canvas-scale-shadowBlur.html
fast/canvas/canvas-strokePath-gradient-shadow.html
fast/canvas/canvas-strokeRect-alpha-shadow.html
fast/canvas/canvas-strokeRect-gradient-shadow.html
Comment 2 Pawel Lampe 2024-04-25 03:32:21 PDT
In general the above failures are due to 2 distict problems:

1) Skia bug when drawing an image with a shadow filter:

Currently, when we draw an image with shadow, we do this using a single call:
m_canvas.drawImageRect(image, normalizedSrcRect, normalizedDestRect, toSkSamplingOptions(m_state.imageInterpolationQuality()), &paint, { });
which uses a paint (SkPaint) with SkImageFilters::DropShadow attached using paint.setImageFilter(). While this works in most of the cases, it turns out that sometimes - when SkImageFilters::DropShadow is attached, and the <canvas> size is very close to the size of image being drawn - the above call draws no shadow (or nothing if I recall correctly). So far I've observed that it happens only when the image we're drawing is using accelerated surface, so e.g. if we uncomment the line in below demo (and comment the one above) the issue is gone:

<html>
  <head>
  </head>
  <body>
    <img id="img" src="/images/red.png" style="visibility:hidden">
    <canvas id="canvas" width="166" height="99" style="border: 1px solid #000"/>
    <script>
      var img = document.getElementById("img");
      img.onload = async () => {
          var canvas = document.getElementById("canvas");
          var ctx = canvas.getContext('2d');

          ctx.fillStyle = '#00f';
          ctx.fillRect(0, 0, 100, 50);
          ctx.shadowColor = '#0f0';
          ctx.shadowOffsetY = 50;
          var x = await createImageBitmap(img);
          // var x = img;
          ctx.drawImage(x, 0, -25);
      }
    </script>
  </body>
</html

the red.png comes from LayoutTests/imported/w3c/web-platform-tests/



2) Every time we draw something with a shadow, we do it within a single draw call with shadow filter attached.

While this approach is very clean and efficient, it makes it impossible to handle cases where the certain class of composite operators come into play. More precisely, the operators such as "destination-atop" etc. assume that drawing of e.g. rect with shadow is done in 2 steps: first draw the shadow, then the rect. In such case, having composite operation such as "destination-atop" would make the shadow to appear over the rect since shadow was on canvas before rect, and therefore it serves as a "desitnation" when rect is being drawn.
Comment 3 Pawel Lampe 2024-05-06 05:07:13 PDT
fast/canvas/canvas-scale-shadowBlur.html
fast/canvas/canvas-strokePath-gradient-shadow.html
fast/canvas/canvas-strokeRect-alpha-shadow.html
fast/canvas/canvas-strokeRect-gradient-shadow.html

tests were extracted to https://bugs.webkit.org/show_bug.cgi?id=273766
Comment 4 Pawel Lampe 2024-05-13 01:16:22 PDT
Pull request: https://github.com/WebKit/WebKit/pull/28168
Comment 5 EWS 2024-06-14 03:58:46 PDT
Committed 280008@main (120f5b1d4f90): <https://commits.webkit.org/280008@main>

Reviewed commits have been landed. Closing PR #28168 and removing active labels.