Title: [288977] trunk
Revision
288977
Author
[email protected]
Date
2022-02-02 12:06:00 -0800 (Wed, 02 Feb 2022)

Log Message

REGRESSION(r288865): SourceImage should never sink its ImageBuffer to a NativeImage
https://bugs.webkit.org/show_bug.cgi?id=236005

Reviewed by Simon Fraser.

Source/WebCore:

The r288865 changes SourceImage::nativeImage() such that if the image
variant has an ImageBuffer, it will sink this ImageBuffer into a NativeImage
and return this NativeImage to the caller. This was incorrect change
because this would invalidate the ImageBufferBackend of the SourceImage.

The fix is to copy the ImageBuffer to a NativeImage (DontCopyBackingStore)
and store it into another image variant. This will keep the ImageBuffer
valid and will prevent subsequent conversion if this function is called
multiple times.

Similar changes should be applied to SourceImage::imageBuffer().

Test: svg/custom/pattern-multiple-referencing.html

* platform/graphics/SourceImage.cpp:
(WebCore::nativeImageOf):
(WebCore::SourceImage::nativeImageIfExists const):
(WebCore::SourceImage::nativeImage const):
(WebCore::imageBufferOf):
(WebCore::SourceImage::imageBufferIfExists const):
(WebCore::SourceImage::imageBuffer const):
* platform/graphics/SourceImage.h:

LayoutTests:

* svg/custom/pattern-multiple-referencing-expected.txt: Added.
* svg/custom/pattern-multiple-referencing.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (288976 => 288977)


--- trunk/LayoutTests/ChangeLog	2022-02-02 19:58:13 UTC (rev 288976)
+++ trunk/LayoutTests/ChangeLog	2022-02-02 20:06:00 UTC (rev 288977)
@@ -1,3 +1,13 @@
+2022-02-02  Said Abou-Hallawa  <[email protected]>
+
+        REGRESSION(r288865): SourceImage should never sink its ImageBuffer to a NativeImage
+        https://bugs.webkit.org/show_bug.cgi?id=236005
+
+        Reviewed by Simon Fraser.
+
+        * svg/custom/pattern-multiple-referencing-expected.txt: Added.
+        * svg/custom/pattern-multiple-referencing.html: Added.
+
 2022-02-02  Patrick Griffis  <[email protected]>
 
         WPT: Import WebAssembly CSP tests

Added: trunk/LayoutTests/svg/custom/pattern-multiple-referencing-expected.txt (0 => 288977)


--- trunk/LayoutTests/svg/custom/pattern-multiple-referencing-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/custom/pattern-multiple-referencing-expected.txt	2022-02-02 20:06:00 UTC (rev 288977)
@@ -0,0 +1,3 @@
+This test passes if it doesn't crash.
+
+

Added: trunk/LayoutTests/svg/custom/pattern-multiple-referencing.html (0 => 288977)


--- trunk/LayoutTests/svg/custom/pattern-multiple-referencing.html	                        (rev 0)
+++ trunk/LayoutTests/svg/custom/pattern-multiple-referencing.html	2022-02-02 20:06:00 UTC (rev 288977)
@@ -0,0 +1,17 @@
+<body>
+    <p>This test passes if it doesn't crash.</p>
+    <svg width="200" height="200">
+        <defs>
+            <pattern id="pattern" x="0" y="0" width="1" height="1">
+                <rect x="0" y="0" width="50" height="100" fill="green"/>
+                <rect x="50" y="0" width="50" height="100" fill="blue"/>
+            </pattern>
+        </defs>
+        <rect width="100" height="100" fill="url(#pattern)" stroke="black"/>
+        <rect x="100" y="100" width="100" height="100" fill="url(#pattern)" stroke="black"/>
+    </svg>
+    <script>
+        if (window.testRunner)
+            testRunner.dumpAsText()
+    </script>
+</body>

Modified: trunk/Source/WebCore/ChangeLog (288976 => 288977)


--- trunk/Source/WebCore/ChangeLog	2022-02-02 19:58:13 UTC (rev 288976)
+++ trunk/Source/WebCore/ChangeLog	2022-02-02 20:06:00 UTC (rev 288977)
@@ -1,3 +1,33 @@
+2022-02-02  Said Abou-Hallawa  <[email protected]>
+
+        REGRESSION(r288865): SourceImage should never sink its ImageBuffer to a NativeImage
+        https://bugs.webkit.org/show_bug.cgi?id=236005
+
+        Reviewed by Simon Fraser.
+
+        The r288865 changes SourceImage::nativeImage() such that if the image
+        variant has an ImageBuffer, it will sink this ImageBuffer into a NativeImage
+        and return this NativeImage to the caller. This was incorrect change 
+        because this would invalidate the ImageBufferBackend of the SourceImage.
+
+        The fix is to copy the ImageBuffer to a NativeImage (DontCopyBackingStore) 
+        and store it into another image variant. This will keep the ImageBuffer
+        valid and will prevent subsequent conversion if this function is called
+        multiple times.
+
+        Similar changes should be applied to SourceImage::imageBuffer().
+
+        Test: svg/custom/pattern-multiple-referencing.html
+
+        * platform/graphics/SourceImage.cpp:
+        (WebCore::nativeImageOf):
+        (WebCore::SourceImage::nativeImageIfExists const):
+        (WebCore::SourceImage::nativeImage const):
+        (WebCore::imageBufferOf):
+        (WebCore::SourceImage::imageBufferIfExists const):
+        (WebCore::SourceImage::imageBuffer const):
+        * platform/graphics/SourceImage.h:
+
 2022-02-02  Chris Dumez  <[email protected]>
 
         Move SharedWorkerThread & SharedWorkerProxy to workers/shared/context/

Modified: trunk/Source/WebCore/platform/graphics/SourceImage.cpp (288976 => 288977)


--- trunk/Source/WebCore/platform/graphics/SourceImage.cpp	2022-02-02 19:58:13 UTC (rev 288976)
+++ trunk/Source/WebCore/platform/graphics/SourceImage.cpp	2022-02-02 20:06:00 UTC (rev 288977)
@@ -35,48 +35,68 @@
 {
 }
 
-NativeImage* SourceImage::nativeImageIfExists() const
+static inline NativeImage* nativeImageOf(const SourceImage::ImageVariant& imageVariant)
 {
-    if (auto* nativeImage = std::get_if<Ref<NativeImage>>(&m_imageVariant))
+    if (auto* nativeImage = std::get_if<Ref<NativeImage>>(&imageVariant))
         return nativeImage->ptr();
     return nullptr;
 }
 
-RefPtr<NativeImage> SourceImage::nativeImage() const
+NativeImage* SourceImage::nativeImageIfExists() const
 {
+    return nativeImageOf(m_imageVariant);
+}
+
+NativeImage* SourceImage::nativeImage() const
+{
     if (!std::holds_alternative<Ref<ImageBuffer>>(m_imageVariant))
         return nativeImageIfExists();
 
-    auto imageBuffer = std::get<Ref<ImageBuffer>>(m_imageVariant);
-    auto nativeImage = ImageBuffer::sinkIntoNativeImage(WTFMove(imageBuffer));
-    if (!nativeImage)
-        return nullptr;
+    if (!m_transformedImageVariant) {
+        auto imageBuffer = std::get<Ref<ImageBuffer>>(m_imageVariant);
 
-    return nativeImage;
+        auto nativeImage = imageBuffer->copyNativeImage(DontCopyBackingStore);
+        if (!nativeImage)
+            return nullptr;
+
+        m_transformedImageVariant = { nativeImage.releaseNonNull() };
+    }
+
+    ASSERT(m_transformedImageVariant);
+    return nativeImageOf(*m_transformedImageVariant);
 }
 
-ImageBuffer* SourceImage::imageBufferIfExists() const
+static inline ImageBuffer* imageBufferOf(const SourceImage::ImageVariant& imageVariant)
 {
-    if (auto* imageBuffer = std::get_if<Ref<ImageBuffer>>(&m_imageVariant))
+    if (auto* imageBuffer = std::get_if<Ref<ImageBuffer>>(&imageVariant))
         return imageBuffer->ptr();
     return nullptr;
 }
 
-RefPtr<ImageBuffer> SourceImage::imageBuffer() const
+ImageBuffer* SourceImage::imageBufferIfExists() const
 {
+    return imageBufferOf(m_imageVariant);
+}
+
+ImageBuffer* SourceImage::imageBuffer() const
+{
     if (!std::holds_alternative<Ref<NativeImage>>(m_imageVariant))
         return imageBufferIfExists();
 
-    auto nativeImage = std::get<Ref<NativeImage>>(m_imageVariant);
-    auto rect = FloatRect { { }, nativeImage->size() };
+    if (!m_transformedImageVariant) {
+        auto nativeImage = std::get<Ref<NativeImage>>(m_imageVariant);
 
-    auto imageBuffer = ImageBuffer::create(nativeImage->size(), RenderingMode::Unaccelerated, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8);
-    if (!imageBuffer)
-        return nullptr;
+        auto rect = FloatRect { { }, nativeImage->size() };
+        auto imageBuffer = ImageBuffer::create(nativeImage->size(), RenderingMode::Unaccelerated, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8);
+        if (!imageBuffer)
+            return nullptr;
 
-    imageBuffer->context().drawNativeImage(nativeImage, rect.size(), rect, rect);
+        imageBuffer->context().drawNativeImage(nativeImage, rect.size(), rect, rect);
+        m_transformedImageVariant = { imageBuffer.releaseNonNull() };
+    }
 
-    return imageBuffer;
+    ASSERT(m_transformedImageVariant);
+    return imageBufferOf(*m_transformedImageVariant);
 }
 
 RenderingResourceIdentifier SourceImage::imageIdentifier() const

Modified: trunk/Source/WebCore/platform/graphics/SourceImage.h (288976 => 288977)


--- trunk/Source/WebCore/platform/graphics/SourceImage.h	2022-02-02 19:58:13 UTC (rev 288976)
+++ trunk/Source/WebCore/platform/graphics/SourceImage.h	2022-02-02 20:06:00 UTC (rev 288977)
@@ -42,10 +42,10 @@
     SourceImage(ImageVariant&&);
 
     NativeImage* nativeImageIfExists() const;
-    RefPtr<NativeImage> nativeImage() const;
+    NativeImage* nativeImage() const;
 
     ImageBuffer* imageBufferIfExists() const;
-    RefPtr<ImageBuffer> imageBuffer() const;
+    ImageBuffer* imageBuffer() const;
 
     RenderingResourceIdentifier imageIdentifier() const;
     IntSize size() const;
@@ -55,6 +55,7 @@
 
 private:
     ImageVariant m_imageVariant;
+    mutable std::optional<ImageVariant> m_transformedImageVariant;
 };
 
 template<class Encoder>
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to