Changeset 251651 in webkit
- Timestamp:
- Oct 28, 2019 3:12:43 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r251650 r251651 1 2019-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 1 41 2019-10-28 Carlos Garcia Campos <cgarcia@igalia.com> 2 42 -
trunk/Source/WebCore/platform/graphics/ImageBackingStore.h
r222841 r251651 60 60 return false; 61 61 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()) 66 65 return false; 67 66 68 buffer.grow(bufferSize);69 m_pixels = SharedBuffer::create(WTFMove(buffer));70 m_pixelsPtr = reinterpret_cast<RGBA32*>(const_cast<char*>(m_pixels->data()));71 67 m_size = size; 72 68 m_frameRect = IntRect(IntPoint(), m_size); … … 87 83 void clear() 88 84 { 89 m emset(m_pixelsPtr, 0, (m_size.area() * sizeof(RGBA32)).unsafeGet());85 m_pixels->zeroPixelData(); 90 86 } 91 87 … … 134 130 { 135 131 ASSERT(inBounds(IntPoint(x, y))); 136 return m_pixels Ptr + y * m_size.width() + x;132 return m_pixels->pixelAt(x, y); 137 133 } 138 134 … … 190 186 191 187 private: 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 192 209 ImageBackingStore(const IntSize& size, bool premultiplyAlpha = true) 193 210 : m_premultiplyAlpha(premultiplyAlpha) … … 202 219 { 203 220 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()));206 221 } 207 222 … … 227 242 } 228 243 229 RefPtr< SharedBuffer> m_pixels;230 RGBA32* m_pixelsPtr { nullptr }; 244 RefPtr<RGBAPixelBufferThreadSafeRefCounted> m_pixels; 245 231 246 IntSize m_size; 232 247 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 35 35 m_pixels->ref(); 36 36 RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data( 37 reinterpret_cast<unsigned char*>(const_cast<uint32_t*>(m_pixels Ptr)),37 reinterpret_cast<unsigned char*>(const_cast<uint32_t*>(m_pixels->data())), 38 38 CAIRO_FORMAT_ARGB32, size().width(), size().height(), size().width() * sizeof(uint32_t))); 39 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(); });40 cairo_surface_set_user_data(surface.get(), &s_surfaceDataKey, m_pixels.get(), [](void* data) { static_cast<RGBAPixelBufferThreadSafeRefCounted*>(data)->deref(); }); 41 41 42 42 return surface;
Note: See TracChangeset
for help on using the changeset viewer.