Changeset 218253 in webkit


Ignore:
Timestamp:
Jun 14, 2017 4:23:25 AM (7 years ago)
Author:
magomez@igalia.com
Message:

REGRESSION(r216901): ImageDecoders: rendering of large images is broken since r216901
https://bugs.webkit.org/show_bug.cgi?id=172502

Reviewed by Carlos Garcia Campos.

When using GTK and WPE image decoders, the decoded frames are stored inside a Vector of
ImageFrames inside the decoders. These ImageFrames have and ImageBackingStore with the
pixels. When a NativeImagePtr is requested, a cairo surface is created from the data
in those ImageBackingStores, but the data keeps being owned by the backing stores. Due
to this, if the decoder that created the image gets destroyed, the backing stores for
the decoded frames get destroyed as well, causing the cairo surfaces that were using
that data to contain garbage (and potentially cause a crash).

To fix this, we change ImageBackingStore so the pixels are stored in a SharedBuffer. The
buffer will be reffed everytime a cairo surface is created with it, and the cairo surfaces
will unref the buffer when they are destroyed. This way, the pixel data won't be freed
while there are cairo surfaces using it.

No new tests, no behaviour change.

  • platform/graphics/ImageBackingStore.h:

(WebCore::ImageBackingStore::setSize):
(WebCore::ImageBackingStore::ImageBackingStore):

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

(WebCore::ImageBackingStore::image):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r218248 r218253  
     12017-06-14  Miguel Gomez  <magomez@igalia.com>
     2
     3        REGRESSION(r216901): ImageDecoders: rendering of large images is broken since r216901
     4        https://bugs.webkit.org/show_bug.cgi?id=172502
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        When using GTK and WPE image decoders, the decoded frames are stored inside a Vector of
     9        ImageFrames inside the decoders. These ImageFrames have and ImageBackingStore with the
     10        pixels. When a NativeImagePtr is requested, a cairo surface is created from the data
     11        in those ImageBackingStores, but the data keeps being owned by the backing stores. Due
     12        to this, if the decoder that created the image gets destroyed, the backing stores for
     13        the decoded frames get destroyed as well, causing the cairo surfaces that were using
     14        that data to contain garbage (and potentially cause a crash).
     15
     16        To fix this, we change ImageBackingStore so the pixels are stored in a SharedBuffer. The
     17        buffer will be reffed everytime a cairo surface is created with it, and the cairo surfaces
     18        will unref the buffer when they are destroyed. This way, the pixel data won't be freed
     19        while there are cairo surfaces using it.
     20
     21        No new tests, no behaviour change.
     22
     23        * platform/graphics/ImageBackingStore.h:
     24        (WebCore::ImageBackingStore::setSize):
     25        (WebCore::ImageBackingStore::ImageBackingStore):
     26        * platform/image-decoders/cairo/ImageBackingStoreCairo.cpp:
     27        (WebCore::ImageBackingStore::image):
     28
    1292017-06-14  Zan Dobersek  <zdobersek@igalia.com>
    230
  • trunk/Source/WebCore/platform/graphics/ImageBackingStore.h

    r215172 r218253  
    3030#include "IntSize.h"
    3131#include "NativeImage.h"
    32 
    33 #include <wtf/Vector.h>
     32#include "SharedBuffer.h"
    3433
    3534namespace WebCore {
     
    5554            return false;
    5655
    57         unsigned area = size.area().unsafeGet();
    58         if (!m_pixels.tryReserveCapacity(area))
     56        Vector<char> buffer;
     57        size_t bufferSize = size.area().unsafeGet() * sizeof(RGBA32);
     58
     59        if (!buffer.tryReserveCapacity(bufferSize))
    5960            return false;
    6061
    61         m_pixels.resize(area);
    62         m_pixelsPtr = m_pixels.data();
     62        buffer.resize(bufferSize);
     63        m_pixels = SharedBuffer::create(WTFMove(buffer));
     64        m_pixelsPtr = reinterpret_cast<RGBA32*>(const_cast<char*>(m_pixels->data()));
    6365        m_size = size;
    6466        m_frameRect = IntRect(IntPoint(), m_size);
     
    184186
    185187    ImageBackingStore(const ImageBackingStore& other)
    186         : m_pixels(other.m_pixels)
    187         , m_size(other.m_size)
     188        : m_size(other.m_size)
    188189        , m_premultiplyAlpha(other.m_premultiplyAlpha)
    189190    {
    190191        ASSERT(!m_size.isEmpty() && !isOverSize(m_size));
    191         m_pixelsPtr = m_pixels.data();
     192        m_pixels = other.m_pixels->copy();
     193        m_pixelsPtr = reinterpret_cast<RGBA32*>(const_cast<char*>(m_pixels->data()));
    192194    }
    193195
     
    213215    }
    214216
    215     Vector<RGBA32> m_pixels;
     217    RefPtr<SharedBuffer> m_pixels;
    216218    RGBA32* m_pixelsPtr { nullptr };
    217219    IntSize m_size;
  • trunk/Source/WebCore/platform/image-decoders/cairo/ImageBackingStoreCairo.cpp

    r205841 r218253  
    3333NativeImagePtr ImageBackingStore::image() const
    3434{
    35     return adoptRef(cairo_image_surface_create_for_data(
     35    m_pixels->ref();
     36    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(
    3637        reinterpret_cast<unsigned char*>(const_cast<RGBA32*>(m_pixelsPtr)),
    3738        CAIRO_FORMAT_ARGB32, size().width(), size().height(), size().width() * sizeof(RGBA32)));
     39    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(); });
     41
     42    return surface;
    3843}
    3944
Note: See TracChangeset for help on using the changeset viewer.