Skip to content

Commit

Permalink
[cairo] When creating a native image from pixel buffer the buffer sho…
Browse files Browse the repository at this point in the history
…uld be owned by the cairo surface

https://bugs.webkit.org/show_bug.cgi?id=263440

Reviewed by Alejandro G. Castro.

It's currently owned by the NativeImage container, but the surface can
be alive after the container destruction. This patch reverts 262575@main
and uses cairo_surface_set_user_data() instead.

* Source/WebCore/platform/graphics/NativeImage.h:
* Source/WebCore/platform/graphics/cairo/GraphicsContextGLCairo.cpp:
(WebCore::GraphicsContextGL::createNativeImageFromPixelBuffer):
* Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp:
(WebCore::NativeImage::create): Deleted.
(WebCore::NativeImage::NativeImage): Deleted.

Canonical link: https://commits.webkit.org/269618@main
  • Loading branch information
carlosgcampos committed Oct 21, 2023
1 parent c954b58 commit 504426c
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 46 deletions.
13 changes: 0 additions & 13 deletions Source/WebCore/platform/graphics/NativeImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
#include "PlatformImage.h"
#include "RenderingResource.h"

#if USE(CAIRO)
#include "PixelBuffer.h"
#endif

namespace WebCore {

class GraphicsContext;
Expand All @@ -47,9 +43,6 @@ class NativeImage final : public RenderingResource {
static WEBCORE_EXPORT RefPtr<NativeImage> create(PlatformImagePtr&&, RenderingResourceIdentifier = RenderingResourceIdentifier::generate());
// Creates a NativeImage that is intended to be drawn once or only few times. Signals the platform to avoid generating any caches for the image.
static WEBCORE_EXPORT RefPtr<NativeImage> createTransient(PlatformImagePtr&&, RenderingResourceIdentifier = RenderingResourceIdentifier::generate());
#if USE(CAIRO)
static RefPtr<NativeImage> create(Ref<PixelBuffer>&&, bool premultipliedAlpha);
#endif

WEBCORE_EXPORT void setPlatformImage(PlatformImagePtr&&);
const PlatformImagePtr& platformImage() const { return m_platformImage; }
Expand All @@ -64,16 +57,10 @@ class NativeImage final : public RenderingResource {

private:
NativeImage(PlatformImagePtr&&, RenderingResourceIdentifier);
#if USE(CAIRO)
NativeImage(PlatformImagePtr&&, RenderingResourceIdentifier, Ref<PixelBuffer>&&);
#endif

bool isNativeImage() const final { return true; }

PlatformImagePtr m_platformImage;
#if USE(CAIRO)
RefPtr<PixelBuffer> m_pixelBuffer;
#endif
};

} // namespace WebCore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,31 @@ bool GraphicsContextGLImageExtractor::extractImage(bool premultiplyAlpha, bool i

RefPtr<NativeImage> GraphicsContextGL::createNativeImageFromPixelBuffer(const GraphicsContextGLAttributes& sourceContextAttributes, Ref<PixelBuffer>&& pixelBuffer)
{
return NativeImage::create(WTFMove(pixelBuffer), sourceContextAttributes.premultipliedAlpha);
ASSERT(!pixelBuffer->size().isEmpty());

// Convert RGBA to BGRA. BGRA is CAIRO_FORMAT_ARGB32 on little-endian architectures.
Ref protectedPixelBuffer = pixelBuffer;
size_t totalBytes = pixelBuffer->sizeInBytes();
uint8_t* pixels = pixelBuffer->bytes();
for (size_t i = 0; i < totalBytes; i += 4)
std::swap(pixels[i], pixels[i + 2]);

if (!sourceContextAttributes.premultipliedAlpha) {
for (size_t i = 0; i < totalBytes; i += 4) {
pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
}
}

auto imageSize = pixelBuffer->size();
RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
pixelBuffer->bytes(), CAIRO_FORMAT_ARGB32, imageSize.width(), imageSize.height(), imageSize.width() * 4));
static cairo_user_data_key_t dataKey;
cairo_surface_set_user_data(imageSurface.get(), &dataKey, &protectedPixelBuffer.leakRef(), [](void* buffer) {
static_cast<PixelBuffer*>(buffer)->deref();
});
return NativeImage::create(WTFMove(imageSurface));
}

} // namespace WebCore
Expand Down
32 changes: 0 additions & 32 deletions Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,38 +35,6 @@

namespace WebCore {

RefPtr<NativeImage> NativeImage::create(Ref<PixelBuffer>&& pixelBuffer, bool premultipliedAlpha)
{
ASSERT(!pixelBuffer->size().isEmpty());

// Convert RGBA to BGRA. BGRA is CAIRO_FORMAT_ARGB32 on little-endian architectures.
size_t totalBytes = pixelBuffer->sizeInBytes();
uint8_t* pixels = pixelBuffer->bytes();
for (size_t i = 0; i < totalBytes; i += 4)
std::swap(pixels[i], pixels[i + 2]);

if (!premultipliedAlpha) {
for (size_t i = 0; i < totalBytes; i += 4) {
pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
}
}

auto imageSize = pixelBuffer->size();
RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
pixelBuffer->bytes(), CAIRO_FORMAT_ARGB32, imageSize.width(), imageSize.height(), imageSize.width() * 4));

return adoptRef(*new NativeImage(WTFMove(imageSurface), RenderingResourceIdentifier::generate(), WTFMove(pixelBuffer)));
}

NativeImage::NativeImage(PlatformImagePtr&& platformImage, RenderingResourceIdentifier renderingResourceIdentifier, Ref<PixelBuffer>&& pixelBuffer)
: RenderingResource(renderingResourceIdentifier)
, m_platformImage(WTFMove(platformImage))
, m_pixelBuffer(WTFMove(pixelBuffer))
{
}

IntSize NativeImage::size() const
{
return cairoSurfaceSize(m_platformImage.get());
Expand Down

0 comments on commit 504426c

Please sign in to comment.