Skip to content

Commit

Permalink
Add NativeImageBackend to support GPUP NativeImage
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=266216
rdar://119489321

Reviewed by Matt Woodrow.

Add NativeImageBackend interface that future work can use to implement
NativeImage that exists in GPUP.

NativeImage instances are held as members of objects. Thus the interface
cannot be based on NativeImage itself, because this would mean that
transitioning from local to remote would need the held objects replaced.
Instead, make the polymorphic extension point the "backend", similar to
current ImageBuffer.

* Source/WebCore/platform/graphics/NativeImage.cpp:
(WebCore::PlatformImageNativeImageBackend::platformImage const):
(WebCore::PlatformImageNativeImageBackend::PlatformImageNativeImageBackend):
(WebCore::NativeImage::create):
(WebCore::NativeImage::NativeImage):
(WebCore::NativeImage::platformImage const):
(WebCore::NativeImage::replaceContents):
(WebCore::NativeImage::setPlatformImage): Deleted.
* Source/WebCore/platform/graphics/NativeImage.h:
* Source/WebCore/platform/graphics/cg/NativeImageCG.cpp:
(WebCore::NativeImage::create):
(WebCore::NativeImage::size const):
(WebCore::NativeImage::hasAlpha const):
(WebCore::NativeImage::singlePixelSolidColor const):
(WebCore::NativeImage::colorSpace const):
(WebCore::NativeImage::clearSubimages):
* Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp:
(WebKit::createShareableBitmapFromNativeImage):

Canonical link: https://commits.webkit.org/272103@main
  • Loading branch information
kkinnunen-apple committed Dec 15, 2023
1 parent 273f225 commit aaab202
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 46 deletions.
50 changes: 42 additions & 8 deletions Source/WebCore/platform/graphics/NativeImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,27 @@

namespace WebCore {

NativeImageBackend::~NativeImageBackend() = default;

PlatformImageNativeImageBackend::~PlatformImageNativeImageBackend() = default;

const PlatformImagePtr& PlatformImageNativeImageBackend::platformImage() const
{
return m_platformImage;
}

PlatformImageNativeImageBackend::PlatformImageNativeImageBackend(PlatformImagePtr platformImage)
: m_platformImage(WTFMove(platformImage))
{
}

#if !USE(CG)
RefPtr<NativeImage> NativeImage::create(PlatformImagePtr&& platformImage, RenderingResourceIdentifier renderingResourceIdentifier)
RefPtr<NativeImage> NativeImage::create(PlatformImagePtr&& platformImage, RenderingResourceIdentifier identifier)
{
if (!platformImage)
return nullptr;
return adoptRef(*new NativeImage(WTFMove(platformImage), renderingResourceIdentifier));
UniqueRef<PlatformImageNativeImageBackend> backend { *new PlatformImageNativeImageBackend(WTFMove(platformImage)) };
return adoptRef(*new NativeImage(WTFMove(backend), identifier));
}

RefPtr<NativeImage> NativeImage::createTransient(PlatformImagePtr&& image, RenderingResourceIdentifier identifier)
Expand All @@ -42,17 +57,36 @@ RefPtr<NativeImage> NativeImage::createTransient(PlatformImagePtr&& image, Rende
}
#endif

NativeImage::NativeImage(PlatformImagePtr&& platformImage, RenderingResourceIdentifier renderingResourceIdentifier)
NativeImage::NativeImage(UniqueRef<NativeImageBackend> backend, RenderingResourceIdentifier renderingResourceIdentifier)
: RenderingResource(renderingResourceIdentifier)
, m_platformImage(WTFMove(platformImage))
, m_backend(WTFMove(backend))
{
}

const PlatformImagePtr& NativeImage::platformImage() const
{
return m_backend->platformImage();
}

IntSize NativeImage::size() const
{
return m_backend->size();
}

bool NativeImage::hasAlpha() const
{
return m_backend->hasAlpha();
}

DestinationColorSpace NativeImage::colorSpace() const
{
ASSERT(m_platformImage);
return m_backend->colorSpace();
}

void NativeImage::setPlatformImage(PlatformImagePtr&& platformImage)
void NativeImage::replaceContents(PlatformImagePtr platformImage)
{
ASSERT(platformImage);
m_platformImage = WTFMove(platformImage);
UniqueRef<PlatformImageNativeImageBackend> backend { *new PlatformImageNativeImageBackend(WTFMove(platformImage)) };
m_backend = WTFMove(backend);
}

} // namespace WebCore
33 changes: 29 additions & 4 deletions Source/WebCore/platform/graphics/NativeImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,22 @@
#include "IntSize.h"
#include "PlatformImage.h"
#include "RenderingResource.h"
#include <wtf/UniqueRef.h>

namespace WebCore {

class GraphicsContext;

class NativeImageBackend;

class NativeImage final : public RenderingResource {
WTF_MAKE_FAST_ALLOCATED;
public:
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());

WEBCORE_EXPORT void setPlatformImage(PlatformImagePtr&&);
const PlatformImagePtr& platformImage() const { return m_platformImage; }
WEBCORE_EXPORT const PlatformImagePtr& platformImage() const;

WEBCORE_EXPORT IntSize size() const;
bool hasAlpha() const;
Expand All @@ -55,12 +57,35 @@ class NativeImage final : public RenderingResource {
void draw(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect, ImagePaintingOptions);
void clearSubimages();

private:
NativeImage(PlatformImagePtr&&, RenderingResourceIdentifier);
WEBCORE_EXPORT void replaceContents(PlatformImagePtr);
protected:
NativeImage(UniqueRef<NativeImageBackend>, RenderingResourceIdentifier);

bool isNativeImage() const final { return true; }

UniqueRef<NativeImageBackend> m_backend;
};

class NativeImageBackend {
public:
WEBCORE_EXPORT virtual ~NativeImageBackend();
virtual const PlatformImagePtr& platformImage() const = 0;
virtual IntSize size() const = 0;
virtual bool hasAlpha() const = 0;
virtual DestinationColorSpace colorSpace() const = 0;
};

class PlatformImageNativeImageBackend final : public NativeImageBackend {
public:
WEBCORE_EXPORT ~PlatformImageNativeImageBackend() final;
WEBCORE_EXPORT const PlatformImagePtr& platformImage() const final;
WEBCORE_EXPORT IntSize size() const final;
WEBCORE_EXPORT bool hasAlpha() const final;
WEBCORE_EXPORT DestinationColorSpace colorSpace() const final;
private:
PlatformImageNativeImageBackend(PlatformImagePtr);
PlatformImagePtr m_platformImage;
friend class NativeImage;
};

} // namespace WebCore
Expand Down
21 changes: 11 additions & 10 deletions Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,35 @@

namespace WebCore {

IntSize NativeImage::size() const
IntSize PlatformImageNativeImageBackend::size() const
{
return cairoSurfaceSize(m_platformImage.get());
}

bool NativeImage::hasAlpha() const
bool PlatformImageNativeImageBackend::hasAlpha() const
{
return cairo_surface_get_content(m_platformImage.get()) != CAIRO_CONTENT_COLOR;
}

DestinationColorSpace PlatformImageNativeImageBackend::colorSpace() const
{
notImplemented();
return DestinationColorSpace::SRGB();
}

Color NativeImage::singlePixelSolidColor() const
{
if (size() != IntSize(1, 1))
return Color();

if (cairo_surface_get_type(m_platformImage.get()) != CAIRO_SURFACE_TYPE_IMAGE)
auto platformImage = this->platformImage().get();
if (cairo_surface_get_type(platformImage) != CAIRO_SURFACE_TYPE_IMAGE)
return Color();

unsigned* pixel = reinterpret_cast_ptr<unsigned*>(cairo_image_surface_get_data(m_platformImage.get()));
unsigned* pixel = reinterpret_cast_ptr<unsigned*>(cairo_image_surface_get_data(platformImage));
return unpremultiplied(asSRGBA(PackedColor::ARGB { *pixel }));
}

DestinationColorSpace NativeImage::colorSpace() const
{
notImplemented();
return DestinationColorSpace::SRGB();
}

void NativeImage::draw(GraphicsContext& context, const FloatRect& destinationRect, const FloatRect& sourceRect, ImagePaintingOptions options)
{
context.drawNativeImageInternal(*this, destinationRect, sourceRect, options);
Expand Down
39 changes: 20 additions & 19 deletions Source/WebCore/platform/graphics/cg/NativeImageCG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,30 @@

namespace WebCore {

IntSize PlatformImageNativeImageBackend::size() const
{
return IntSize(CGImageGetWidth(m_platformImage.get()), CGImageGetHeight(m_platformImage.get()));
}

bool PlatformImageNativeImageBackend::hasAlpha() const
{
CGImageAlphaInfo info = CGImageGetAlphaInfo(m_platformImage.get());
return (info >= kCGImageAlphaPremultipliedLast) && (info <= kCGImageAlphaFirst);
}

DestinationColorSpace PlatformImageNativeImageBackend::colorSpace() const
{
return DestinationColorSpace(CGImageGetColorSpace(m_platformImage.get()));
}

RefPtr<NativeImage> NativeImage::create(PlatformImagePtr&& image, RenderingResourceIdentifier renderingResourceIdentifier)
{
if (!image)
return nullptr;
if (CGImageGetWidth(image.get()) > std::numeric_limits<int>::max() || CGImageGetHeight(image.get()) > std::numeric_limits<int>::max())
return nullptr;
return adoptRef(*new NativeImage(WTFMove(image), renderingResourceIdentifier));
UniqueRef<PlatformImageNativeImageBackend> backend { *new PlatformImageNativeImageBackend(WTFMove(image)) };
return adoptRef(*new NativeImage(WTFMove(backend), renderingResourceIdentifier));
}

RefPtr<NativeImage> NativeImage::createTransient(PlatformImagePtr&& image, RenderingResourceIdentifier identifier)
Expand All @@ -60,17 +77,6 @@ RefPtr<NativeImage> NativeImage::createTransient(PlatformImagePtr&& image, Rende
return create(WTFMove(transientImage), identifier);
}

IntSize NativeImage::size() const
{
return IntSize(CGImageGetWidth(m_platformImage.get()), CGImageGetHeight(m_platformImage.get()));
}

bool NativeImage::hasAlpha() const
{
CGImageAlphaInfo info = CGImageGetAlphaInfo(m_platformImage.get());
return (info >= kCGImageAlphaPremultipliedLast) && (info <= kCGImageAlphaFirst);
}

Color NativeImage::singlePixelSolidColor() const
{
if (size() != IntSize(1, 1))
Expand All @@ -83,19 +89,14 @@ Color NativeImage::singlePixelSolidColor() const
return Color();

CGContextSetBlendMode(bitmapContext.get(), kCGBlendModeCopy);
CGContextDrawImage(bitmapContext.get(), CGRectMake(0, 0, 1, 1), m_platformImage.get());
CGContextDrawImage(bitmapContext.get(), CGRectMake(0, 0, 1, 1), platformImage().get());

if (!pixel[3])
return Color::transparentBlack;

return makeFromComponentsClampingExceptAlpha<SRGBA<uint8_t>>(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
}

DestinationColorSpace NativeImage::colorSpace() const
{
return DestinationColorSpace(CGImageGetColorSpace(m_platformImage.get()));
}

void NativeImage::draw(GraphicsContext& context, const FloatRect& destinationRect, const FloatRect& sourceRect, ImagePaintingOptions options)
{
auto isHDRColorSpace = [](CGColorSpaceRef colorSpace) -> bool {
Expand Down Expand Up @@ -159,7 +160,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
void NativeImage::clearSubimages()
{
#if CACHE_SUBIMAGES
CGSubimageCacheWithTimer::clearImage(m_platformImage.get());
CGSubimageCacheWithTimer::clearImage(platformImage().get());
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ inline static std::optional<ShareableBitmap::Handle> createShareableBitmapFromNa
#endif

// If we failed to create ShareableBitmap or PlatformImage, fall back to image-draw method.
if (!platformImage)
if (!platformImage) {
bitmap = ShareableBitmap::createFromImageDraw(image);

if (!platformImage && bitmap)
platformImage = bitmap->createPlatformImage(DontCopyBackingStore, ShouldInterpolate::Yes);
if (bitmap)
platformImage = bitmap->createPlatformImage(DontCopyBackingStore, ShouldInterpolate::Yes);
}

if (!platformImage)
return std::nullopt;
Expand All @@ -124,7 +124,7 @@ inline static std::optional<ShareableBitmap::Handle> createShareableBitmapFromNa
handle->takeOwnershipOfMemory(MemoryLedger::Graphics);

// Replace the PlatformImage of the input NativeImage with the shared one.
image.setPlatformImage(WTFMove(platformImage));
image.replaceContents(WTFMove(platformImage));
return handle;
}

Expand Down

0 comments on commit aaab202

Please sign in to comment.