Changeset 251651 in webkit


Ignore:
Timestamp:
Oct 28, 2019 3:12:43 AM (5 years ago)
Author:
cturner@igalia.com
Message:

ImageDecoders: use a thread safe data buffer for Cairo backing store
https://bugs.webkit.org/show_bug.cgi?id=201727

Reviewed by Carlos Garcia Campos.

When an image resource gets cached and replaces an existing image,
CachedImage::didReplaceSharedBufferContents is called, which
destroys the decoder in the BitmapImage class. This decoder can be
initialized from any thread via
ImageSource::ensureDecoderAvailable. On GTK/WPE, this dispatches
to a ScalableImageDecoder, which contains a vector of
ScalableImageDecoderFrame's, which contain ImageBackingStore's,
which for reasons related to Cairo, contain a RefCounted
SharedBuffer of pixel data.

The problem is that the CachedImage's decoders can be
created/destroyed on different threads, so a thread-safe buffer
class is required to hold these data, and pass them safely into
cairo_image_surface_create_for_data rather than a SharedBuffer
which must be created/destroyed on the main-thread.

Covered by existing tests.

  • platform/graphics/ImageBackingStore.h: Create a small

thread-safe utility class to hold the RGBA pixel data.
(WebCore::ImageBackingStore::setSize):
(WebCore::ImageBackingStore::clear):
(WebCore::ImageBackingStore::pixelAt const):
(WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::create):
(WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::zeroPixelData):
(WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::pixelAt const):
(WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::data const):
(WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::isValid const):
(WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::RGBAPixelBufferThreadSafeRefCounted):
(WebCore::ImageBackingStore::ImageBackingStore):

  • platform/image-decoders/cairo/ImageBackingStoreCairo.cpp:

(WebCore::ImageBackingStore::image const):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r251650 r251651  
     12019-10-28  Charlie Turner  <cturner@igalia.com>
     2
     3        ImageDecoders: use a thread safe data buffer for Cairo backing store
     4        https://bugs.webkit.org/show_bug.cgi?id=201727
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        When an image resource gets cached and replaces an existing image,
     9        CachedImage::didReplaceSharedBufferContents is called, which
     10        destroys the decoder in the BitmapImage class. This decoder can be
     11        initialized from any thread via
     12        ImageSource::ensureDecoderAvailable. On GTK/WPE, this dispatches
     13        to a ScalableImageDecoder, which contains a vector of
     14        ScalableImageDecoderFrame's, which contain ImageBackingStore's,
     15        which for reasons related to Cairo, contain a RefCounted
     16        SharedBuffer of pixel data.
     17
     18        The problem is that the CachedImage's decoders can be
     19        created/destroyed on different threads, so a thread-safe buffer
     20        class is required to hold these data, and pass them safely into
     21        cairo_image_surface_create_for_data rather than a SharedBuffer
     22        which must be created/destroyed on the main-thread.
     23
     24        Covered by existing tests.
     25
     26        * platform/graphics/ImageBackingStore.h: Create a small
     27        thread-safe utility class to hold the RGBA pixel data.
     28        (WebCore::ImageBackingStore::setSize):
     29        (WebCore::ImageBackingStore::clear):
     30        (WebCore::ImageBackingStore::pixelAt const):
     31        (WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::create):
     32        (WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::zeroPixelData):
     33        (WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::pixelAt const):
     34        (WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::data const):
     35        (WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::isValid const):
     36        (WebCore::ImageBackingStore::ThreadSafeRGBAPixelBuffer::RGBAPixelBufferThreadSafeRefCounted):
     37        (WebCore::ImageBackingStore::ImageBackingStore):
     38        * platform/image-decoders/cairo/ImageBackingStoreCairo.cpp:
     39        (WebCore::ImageBackingStore::image const):
     40
    1412019-10-28  Carlos Garcia Campos  <cgarcia@igalia.com>
    242
  • trunk/Source/WebCore/platform/graphics/ImageBackingStore.h

    r222841 r251651  
    6060            return false;
    6161
    62         Vector<char> buffer;
    63         size_t bufferSize = size.area().unsafeGet() * sizeof(RGBA32);
    64 
    65         if (!buffer.tryReserveCapacity(bufferSize))
     62        m_pixels = RGBAPixelBufferThreadSafeRefCounted::create(size);
     63
     64        if (!m_pixels->isValid())
    6665            return false;
    6766
    68         buffer.grow(bufferSize);
    69         m_pixels = SharedBuffer::create(WTFMove(buffer));
    70         m_pixelsPtr = reinterpret_cast<RGBA32*>(const_cast<char*>(m_pixels->data()));
    7167        m_size = size;
    7268        m_frameRect = IntRect(IntPoint(), m_size);
     
    8783    void clear()
    8884    {
    89         memset(m_pixelsPtr, 0, (m_size.area() * sizeof(RGBA32)).unsafeGet());
     85        m_pixels->zeroPixelData();
    9086    }
    9187
     
    134130    {
    135131        ASSERT(inBounds(IntPoint(x, y)));
    136         return m_pixelsPtr + y * m_size.width() + x;
     132        return m_pixels->pixelAt(x, y);
    137133    }
    138134
     
    190186
    191187private:
     188    class RGBAPixelBufferThreadSafeRefCounted : public ThreadSafeRefCounted<RGBAPixelBufferThreadSafeRefCounted> {
     189    public:
     190        static Ref<RGBAPixelBufferThreadSafeRefCounted> create(const IntSize& initialSize) { return adoptRef(*new RGBAPixelBufferThreadSafeRefCounted(initialSize)); }
     191        void zeroPixelData() { m_pixels.fill(0); }
     192        RGBA32* pixelAt(int x, int y) const { return const_cast<unsigned*>(&m_pixels.data()[y * m_size.width() + x]); }
     193        const RGBA32* data() const { return m_pixels.data(); }
     194        bool isValid() const { return m_isValid; }
     195    private:
     196        RGBAPixelBufferThreadSafeRefCounted(const IntSize& initialSize)
     197            : m_size(initialSize)
     198        {
     199            unsigned bufferSize = initialSize.area().unsafeGet();
     200            m_isValid = m_pixels.tryReserveCapacity(bufferSize);
     201            if (m_isValid)
     202                m_pixels.resize(bufferSize);
     203        }
     204        IntSize m_size;
     205        Vector<RGBA32> m_pixels;
     206        bool m_isValid { false };
     207    };
     208
    192209    ImageBackingStore(const IntSize& size, bool premultiplyAlpha = true)
    193210        : m_premultiplyAlpha(premultiplyAlpha)
     
    202219    {
    203220        ASSERT(!m_size.isEmpty() && !isOverSize(m_size));
    204         m_pixels = SharedBuffer::create(other.m_pixels->data(), other.m_pixels->size());
    205         m_pixelsPtr = reinterpret_cast<RGBA32*>(const_cast<char*>(m_pixels->data()));
    206221    }
    207222
     
    227242    }
    228243
    229     RefPtr<SharedBuffer> m_pixels;
    230     RGBA32* m_pixelsPtr { nullptr };
     244    RefPtr<RGBAPixelBufferThreadSafeRefCounted> m_pixels;
     245
    231246    IntSize m_size;
    232247    IntRect m_frameRect; // This will always just be the entire buffer except for GIF and PNG frames
  • trunk/Source/WebCore/platform/image-decoders/cairo/ImageBackingStoreCairo.cpp

    r228974 r251651  
    3535    m_pixels->ref();
    3636    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(
    37         reinterpret_cast<unsigned char*>(const_cast<uint32_t*>(m_pixelsPtr)),
     37        reinterpret_cast<unsigned char*>(const_cast<uint32_t*>(m_pixels->data())),
    3838        CAIRO_FORMAT_ARGB32, size().width(), size().height(), size().width() * sizeof(uint32_t)));
    3939    static cairo_user_data_key_t s_surfaceDataKey;
    40     cairo_surface_set_user_data(surface.get(), &s_surfaceDataKey, m_pixels.get(), [](void* data) { static_cast<SharedBuffer*>(data)->deref(); });
     40    cairo_surface_set_user_data(surface.get(), &s_surfaceDataKey, m_pixels.get(), [](void* data) { static_cast<RGBAPixelBufferThreadSafeRefCounted*>(data)->deref(); });
    4141
    4242    return surface;
Note: See TracChangeset for help on using the changeset viewer.