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

Changeset 295343 in webkit


Ignore:
Timestamp:
Jun 7, 2022, 6:43:49 AM (4 years ago)
Author:
commit-queue@webkit.org
Message:

ImageBuffer::copyImage consumes GPUP memory and is redundant
​https://bugs.webkit.org/show_bug.cgi?id=241127

Patch by Kimmo Kinnunen <​kkinnunen@apple.com> on 2022-06-07
ImageBuffer::copyImage overrides:

  • Always ends up returning BitmapImage
  • Always ends up constructing BitmapImage from copyNativeImage
  • Is implemented erroneously in many backends, ignoring the preserve resolution scale flag
  • Is implemented correctly in ImageBufferCGBackend, but will allocate the destination buffer when trying to honor the PreserveResolution::No. This will cause a large unattributed allocation in GPUP.

Instead, implement ImageBuffer::copyImage for all the backends and overrides
with ImageBuffer::copyNativeImage().

Implement the scaling conversion, PreserveResolution::No, as a normal WebCore GraphicsContext
operation.

Reviewed by Said Abou-Hallawa.

  • Source/WebCore/platform/graphics/ConcreteImageBuffer.h:
  • Source/WebCore/platform/graphics/ImageBuffer.cpp:

(WebCore::ImageBuffer::copyImage const):
(WebCore::ImageBuffer::sinkIntoImage):

  • Source/WebCore/platform/graphics/ImageBuffer.h:
  • Source/WebCore/platform/graphics/ImageBufferBackend.cpp:

(WebCore::ImageBufferBackend::sinkIntoImage): Deleted.

  • Source/WebCore/platform/graphics/ImageBufferBackend.h:
  • Source/WebCore/platform/graphics/cairo/ImageBufferCairoBackend.cpp:

(WebCore::ImageBufferCairoBackend::copyImage const): Deleted.

  • Source/WebCore/platform/graphics/cairo/ImageBufferCairoBackend.h:
  • Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp:

(WebCore::createBitmapImageAfterScalingIfNeeded): Deleted.
(WebCore::ImageBufferCGBackend::copyImage const): Deleted.
(WebCore::ImageBufferCGBackend::sinkIntoImage): Deleted.

  • Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.h:
  • Source/WebKit/WebProcess/GPU/graphics/ImageBufferShareableBitmapBackend.cpp:

(WebKit::ImageBufferShareableBitmapBackend::copyImage const): Deleted.

  • Source/WebKit/WebProcess/GPU/graphics/ImageBufferShareableBitmapBackend.h:
  • Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h:
  • Source/WebKit/WebProcess/GPU/graphics/cocoa/ImageBufferRemoteIOSurfaceBackend.cpp:

(WebKit::ImageBufferRemoteIOSurfaceBackend::copyImage const): Deleted.

  • Source/WebKit/WebProcess/GPU/graphics/cocoa/ImageBufferRemoteIOSurfaceBackend.h:

Canonical link: ​https://commits.webkit.org/251359@main

Location:
trunk/Source
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/platform/graphics/ConcreteImageBuffer.h

    r295149 r295343  
    141141    }
    142142
    143     RefPtr<Image> copyImage(BackingStoreCopy copyBehavior = CopyBackingStore, PreserveResolution preserveResolution = PreserveResolution::No) const override
    144     {
    145         if (auto* backend = ensureBackendCreated()) {
    146             const_cast<ConcreteImageBuffer&>(*this).flushDrawingContext();
    147             return backend->copyImage(copyBehavior, preserveResolution);
    148         }
    149         return nullptr;
    150     }
    151 
    152143    RefPtr<Image> filteredImage(Filter& filter) override
    153144    {
    … …  
    198189            flushDrawingContext();
    199190            return backend->sinkIntoNativeImage();
    200         }
    201         return nullptr;
    202     }
    203 
    204     RefPtr<Image> sinkIntoImage(PreserveResolution preserveResolution = PreserveResolution::No) override
    205     {
    206         if (auto* backend = ensureBackendCreated()) {
    207             flushDrawingContext();
    208             return backend->sinkIntoImage(preserveResolution);
    209191        }
    210192        return nullptr;
  • trunk/Source/WebCore/platform/graphics/ImageBuffer.cpp

    r292557 r295343  
    2929#include "ImageBuffer.h"
    3030
     31#include "BitmapImage.h"
    3132#include "GraphicsContext.h"
    3233#include "HostWindow.h"
    … …  
    122123}
    123124
    124 RefPtr<NativeImage> ImageBuffer::sinkIntoNativeImage(RefPtr<ImageBuffer> imageBuffer)
     125RefPtr<NativeImage> ImageBuffer::sinkIntoNativeImage(RefPtr<ImageBuffer> source)
    125126{
    126     return imageBuffer->sinkIntoNativeImage();
     127    if (!source)
     128        return nullptr;
     129    return source->sinkIntoNativeImage();
    127130}
    128131
    129 RefPtr<Image> ImageBuffer::sinkIntoImage(RefPtr<ImageBuffer> imageBuffer, PreserveResolution preserveResolution)
     132RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, PreserveResolution preserveResolution) const
    130133{
    131     return imageBuffer->sinkIntoImage(preserveResolution);
     134    RefPtr<NativeImage> image;
     135    if (resolutionScale() == 1 || preserveResolution == PreserveResolution::Yes)
     136        image = copyNativeImage(copyBehavior);
     137    else {
     138        auto copyBuffer = context().createImageBuffer(logicalSize(), 1.f, colorSpace());
     139        if (!copyBuffer)
     140            return nullptr;
     141        copyBuffer->context().drawImageBuffer(const_cast<ImageBuffer&>(*this), FloatPoint { }, CompositeOperator::Copy);
     142        image = ImageBuffer::sinkIntoNativeImage(WTFMove(copyBuffer));
     143    }
     144    if (!image)
     145        return nullptr;
     146    return BitmapImage::create(image.releaseNonNull());
     147}
     148
     149RefPtr<Image> ImageBuffer::sinkIntoImage(RefPtr<ImageBuffer> source, PreserveResolution preserveResolution)
     150{
     151    if (!source)
     152        return nullptr;
     153    RefPtr<NativeImage> image;
     154    if (source->resolutionScale() == 1 || preserveResolution == PreserveResolution::Yes)
     155        image = sinkIntoNativeImage(WTFMove(source));
     156    else {
     157        auto copySize = source->logicalSize();
     158        auto copyBuffer = source->context().createImageBuffer(copySize, 1.f, source->colorSpace());
     159        if (!copyBuffer)
     160            return nullptr;
     161        drawConsuming(WTFMove(source), copyBuffer->context(), FloatRect { { }, copySize }, FloatRect { 0, 0, -1, -1 }, CompositeOperator::Copy);
     162        image = ImageBuffer::sinkIntoNativeImage(WTFMove(copyBuffer));
     163    }
     164    if (!image)
     165        return nullptr;
     166    return BitmapImage::create(image.releaseNonNull());
    132167}
    133168
  • trunk/Source/WebCore/platform/graphics/ImageBuffer.h

    r295149 r295343  
    128128
    129129    virtual RefPtr<NativeImage> copyNativeImage(BackingStoreCopy = CopyBackingStore) const = 0;
    130     virtual RefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore, PreserveResolution = PreserveResolution::No) const = 0;
     130    WEBCORE_EXPORT RefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore, PreserveResolution = PreserveResolution::No) const;
    131131    virtual RefPtr<Image> filteredImage(Filter&) = 0;
    132132
    … …  
    163163
    164164    virtual RefPtr<NativeImage> sinkIntoNativeImage() = 0;
    165     virtual RefPtr<Image> sinkIntoImage(PreserveResolution = PreserveResolution::No) = 0;
    166165    virtual void drawConsuming(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions&) = 0;
    167166};
  • trunk/Source/WebCore/platform/graphics/ImageBufferBackend.cpp

    r295227 r295343  
    5959{
    6060    return copyNativeImage(DontCopyBackingStore);
    61 }
    62 
    63 RefPtr<Image> ImageBufferBackend::sinkIntoImage(PreserveResolution preserveResolution)
    64 {
    65     return copyImage(DontCopyBackingStore, preserveResolution);
    6661}
    6762
  • trunk/Source/WebCore/platform/graphics/ImageBufferBackend.h

    r295149 r295343  
    112112    virtual void finalizeDrawIntoContext(GraphicsContext&) { }
    113113    virtual RefPtr<NativeImage> copyNativeImage(BackingStoreCopy) const = 0;
    114     virtual RefPtr<Image> copyImage(BackingStoreCopy, PreserveResolution) const = 0;
    115114
    116115    WEBCORE_EXPORT virtual RefPtr<NativeImage> sinkIntoNativeImage();
    117     WEBCORE_EXPORT virtual RefPtr<Image> sinkIntoImage(PreserveResolution);
    118116
    119117    virtual void clipToMask(GraphicsContext&, const FloatRect&) { }
  • trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairoBackend.cpp

    r295216 r295343  
    4545
    4646namespace WebCore {
    47 
    48 RefPtr<Image> ImageBufferCairoBackend::copyImage(BackingStoreCopy copyBehavior, PreserveResolution) const
    49 {
    50     // BitmapImage will release the passed in surface on destruction
    51     return BitmapImage::create(copyNativeImage(copyBehavior));
    52 }
    5347
    5448void ImageBufferCairoBackend::clipToMask(GraphicsContext& destContext, const FloatRect& destRect)
  • trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairoBackend.h

    r294536 r295343  
    3838class ImageBufferCairoBackend : public ImageBufferBackend {
    3939public:
    40     RefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore, PreserveResolution = PreserveResolution::No) const override;
    41 
    4240    void clipToMask(GraphicsContext&, const FloatRect& destRect) override;
    4341
  • trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp

    r295227 r295343  
    9191        return sRGBColorSpaceRef();
    9292    return imageBufferColorSpace.platformColorSpace();
    93 }
    94 
    95 static RefPtr<Image> createBitmapImageAfterScalingIfNeeded(RefPtr<NativeImage>&& image, const IntSize& logicalSize, const IntSize& backendSize, float resolutionScale, PreserveResolution preserveResolution)
    96 {
    97     if (!image)
    98         return nullptr;
    99 
    100     if (resolutionScale == 1 || preserveResolution == PreserveResolution::Yes)
    101         image = NativeImage::create(createCroppedImageIfNecessary(image->platformImage().get(), backendSize));
    102     else {
    103         auto context = adoptCF(CGBitmapContextCreate(0, logicalSize.width(), logicalSize.height(), 8, 4 * logicalSize.width(), colorSpaceForBitmap(image->colorSpace()), static_cast<uint32_t>(kCGImageAlphaPremultipliedFirst) | static_cast<uint32_t>(kCGBitmapByteOrder32Host)));
    104         CGContextSetBlendMode(context.get(), kCGBlendModeCopy);
    105         CGContextClipToRect(context.get(), FloatRect(FloatPoint::zero(), logicalSize));
    106         FloatSize imageSizeInUserSpace = logicalSize;
    107         CGContextDrawImage(context.get(), FloatRect(FloatPoint::zero(), imageSizeInUserSpace), image->platformImage().get());
    108         image = NativeImage::create(adoptCF(CGBitmapContextCreateImage(context.get())));
    109     }
    110 
    111     if (!image)
    112         return nullptr;
    113 
    114     return BitmapImage::create(WTFMove(image));
    115 }
    116 
    117 RefPtr<Image> ImageBufferCGBackend::copyImage(BackingStoreCopy copyBehavior, PreserveResolution preserveResolution) const
    118 {
    119     RefPtr<NativeImage> image;
    120     if (resolutionScale() == 1 || preserveResolution == PreserveResolution::Yes)
    121         image = copyNativeImage(copyBehavior);
    122     else
    123         image = copyNativeImage(DontCopyBackingStore);
    124     return createBitmapImageAfterScalingIfNeeded(WTFMove(image), logicalSize(), backendSize(), resolutionScale(), preserveResolution);
    125 }
    126 
    127 RefPtr<Image> ImageBufferCGBackend::sinkIntoImage(PreserveResolution preserveResolution)
    128 {
    129     // Get the backend size before sinking the it into a NativeImage. sinkIntoNativeImage() sets the IOSurface to null if it's an accelerated backend.
    130     auto backendSize = this->backendSize();
    131     return createBitmapImageAfterScalingIfNeeded(sinkIntoNativeImage(), logicalSize(), backendSize, resolutionScale(), preserveResolution);
    13293}
    13394
  • trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.h

    r294536 r295343  
    4444    using ImageBufferBackend::ImageBufferBackend;
    4545
    46     RefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore, PreserveResolution = PreserveResolution::No) const override;
    47     RefPtr<Image> sinkIntoImage(PreserveResolution) override;
    48 
    4946    void clipToMask(GraphicsContext&, const FloatRect& destRect) override;
    5047
  • trunk/Source/WebKit/WebProcess/GPU/graphics/ImageBufferShareableBitmapBackend.cpp

    r295149 r295343  
    154154}
    155155
    156 RefPtr<Image> ImageBufferShareableBitmapBackend::copyImage(BackingStoreCopy, PreserveResolution) const
    157 {
    158     return m_bitmap->createImage();
    159 }
    160 
    161156RefPtr<PixelBuffer> ImageBufferShareableBitmapBackend::getPixelBuffer(const PixelBufferFormat& outputFormat, const IntRect& srcRect, const ImageBufferAllocator& allocator) const
    162157{
  • trunk/Source/WebKit/WebProcess/GPU/graphics/ImageBufferShareableBitmapBackend.h

    r295149 r295343  
    6464
    6565    RefPtr<WebCore::NativeImage> copyNativeImage(WebCore::BackingStoreCopy = WebCore::CopyBackingStore) const final;
    66     RefPtr<WebCore::Image> copyImage(WebCore::BackingStoreCopy = WebCore::CopyBackingStore, WebCore::PreserveResolution = WebCore::PreserveResolution::No) const final;
    6766
    6867    RefPtr<WebCore::PixelBuffer> getPixelBuffer(const WebCore::PixelBufferFormat& outputFormat, const WebCore::IntRect&, const WebCore::ImageBufferAllocator&) const final;
  • trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h

    r295227 r295343  
    196196    }
    197197
    198     RefPtr<WebCore::Image> copyImage(WebCore::BackingStoreCopy copyBehavior = WebCore::CopyBackingStore, WebCore::PreserveResolution preserveResolution = WebCore::PreserveResolution::No) const final
    199     {
    200         if (UNLIKELY(!m_remoteRenderingBackendProxy))
    201             return { };
    202 
    203         if (canMapBackingStore())
    204             return BaseConcreteImageBuffer::copyImage(copyBehavior, preserveResolution);
    205 
    206         const_cast<RemoteImageBufferProxy*>(this)->flushDrawingContext();
    207         auto bitmap = m_remoteRenderingBackendProxy->getShareableBitmap(m_renderingResourceIdentifier, preserveResolution);
    208         if (!bitmap)
    209             return { };
    210         return bitmap->createImage();
    211     }
    212 
    213198    void drawConsuming(WebCore::GraphicsContext& destContext, const WebCore::FloatRect& destRect, const WebCore::FloatRect& srcRect, const WebCore::ImagePaintingOptions& options) final
    214199    {
    … …  
    220205    {
    221206        return copyNativeImage();
    222     }
    223 
    224     RefPtr<WebCore::Image> sinkIntoImage(WebCore::PreserveResolution preserveResolution = WebCore::PreserveResolution::No) final
    225     {
    226         return copyImage(WebCore::BackingStoreCopy::CopyBackingStore, preserveResolution);
    227207    }
    228208
  • trunk/Source/WebKit/WebProcess/GPU/graphics/cocoa/ImageBufferRemoteIOSurfaceBackend.cpp

    r295149 r295343  
    113113}
    114114
    115 RefPtr<Image> ImageBufferRemoteIOSurfaceBackend::copyImage(BackingStoreCopy, PreserveResolution) const
    116 {
    117     RELEASE_ASSERT_NOT_REACHED();
    118     return { };
    119 }
    120 
    121115String ImageBufferRemoteIOSurfaceBackend::toDataURL(const String&, std::optional<double>, PreserveResolution) const
    122116{
  • trunk/Source/WebKit/WebProcess/GPU/graphics/cocoa/ImageBufferRemoteIOSurfaceBackend.h

    r295149 r295343  
    6161    WebCore::IntSize backendSize() const final;
    6262    RefPtr<WebCore::NativeImage> copyNativeImage(WebCore::BackingStoreCopy) const final;
    63     RefPtr<WebCore::Image> copyImage(WebCore::BackingStoreCopy, WebCore::PreserveResolution) const final;
    6463    String toDataURL(const String& mimeType, std::optional<double> quality, WebCore::PreserveResolution) const final;
    6564    Vector<uint8_t> toData(const String& mimeType, std::optional<double> quality) const final;
Note: See TracChangeset for help on using the changeset viewer.