Add support for wide gamut for ShareableBitmap for image popovers
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Oct 2016 00:50:53 +0000 (00:50 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Oct 2016 00:50:53 +0000 (00:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164001

Patch by Megan Gardner <megan_gardner@apple.com> on 2016-10-27
Reviewed by Simon Fraser.

Source/WebCore:

Add a function to return a CGColorSpaceRef for extended sRGB.

This is currently untestable, so no tests added.

* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::extendedSRGBColorSpaceRef):

Source/WebKit2:

Added suppport for wide gamut in ShareableBitmap. SharableBitmaps now know the size of their pixels,
and that data is passed back and forth between the processes. The callers of SharedBitmap will determine
if their image should support wide gamut, but ShareableBitmap will override a set flag on a device that
is incapbable of supporting a wide gamut image.
This makes it possible to show wide gamut images in image popovers on iOS.
This is currently untestable, so no tests added.

* Platform/IPC/Decoder.cpp:
(IPC::Decoder::decode):
* Platform/IPC/Decoder.h:
* Platform/IPC/Encoder.cpp:
(IPC::Encoder::encode):
* Platform/IPC/Encoder.h:
* Shared/ShareableBitmap.cpp:
(WebKit::bytesPerPixel):
(WebKit::ShareableBitmap::Handle::encode):
(WebKit::ShareableBitmap::Handle::decode):
(WebKit::ShareableBitmap::Handle::clear):
(WebKit::ShareableBitmap::create):
(WebKit::ShareableBitmap::createShareable):
(WebKit::ShareableBitmap::createHandle):
(WebKit::ShareableBitmap::ShareableBitmap):
* Shared/ShareableBitmap.h:
(WebKit::ShareableBitmap::numBytesForSize):
(WebKit::ShareableBitmap::sizeInBytes):
* Shared/cg/ShareableBitmapCG.cpp:
(WebKit::bitmapInfo):
(WebKit::ShareableBitmap::createGraphicsContext):
(WebKit::ShareableBitmap::createCGImage):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPositionInformation):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208020 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
Source/WebCore/platform/graphics/cg/GraphicsContextCG.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/ShareableBitmap.cpp
Source/WebKit2/Shared/ShareableBitmap.h
Source/WebKit2/Shared/cg/ShareableBitmapCG.cpp
Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

index 7df5b06..482f63f 100644 (file)
@@ -1,3 +1,17 @@
+2016-10-27  Megan Gardner  <megan_gardner@apple.com>
+
+        Add support for wide gamut for ShareableBitmap for image popovers
+        https://bugs.webkit.org/show_bug.cgi?id=164001
+
+        Reviewed by Simon Fraser.
+
+        Add a function to return a CGColorSpaceRef for extended sRGB.
+
+        This is currently untestable, so no tests added.
+
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::extendedSRGBColorSpaceRef):
+
 2016-10-25  Brent Fulgham  <bfulgham@apple.com>
 
         [Win][Direct2D] Create a RAII Helper Class for the Render Target
index 58012dd..e06f45d 100644 (file)
@@ -93,6 +93,18 @@ CGColorSpaceRef sRGBColorSpaceRef()
 #endif // PLATFORM(WIN)
     return sRGBSpace;
 }
+    
+CGColorSpaceRef extendedSRGBColorSpaceRef()
+{
+    static CGColorSpaceRef extendedSRGBSpace;
+#if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 101200)
+    extendedSRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB);
+#endif
+    // If there is no support for exteneded sRGB, fall back to sRGB.
+    if (!extendedSRGBSpace)
+        extendedSRGBSpace = sRGBColorSpaceRef();
+    return extendedSRGBSpace;
+}
 
 CGColorSpaceRef displayP3ColorSpaceRef()
 {
index e6f1526..e6d31af 100644 (file)
@@ -34,6 +34,7 @@ namespace WebCore {
 
 CGColorSpaceRef deviceRGBColorSpaceRef();
 WEBCORE_EXPORT CGColorSpaceRef sRGBColorSpaceRef();
+WEBCORE_EXPORT CGColorSpaceRef extendedSRGBColorSpaceRef();
 WEBCORE_EXPORT CGColorSpaceRef displayP3ColorSpaceRef();
 CGColorSpaceRef linearRGBColorSpaceRef();
 
index aaef8c4..4bb10d0 100644 (file)
@@ -1,3 +1,42 @@
+2016-10-27  Megan Gardner  <megan_gardner@apple.com>
+
+        Add support for wide gamut for ShareableBitmap for image popovers
+        https://bugs.webkit.org/show_bug.cgi?id=164001
+
+        Reviewed by Simon Fraser.
+
+        Added suppport for wide gamut in ShareableBitmap. SharableBitmaps now know the size of their pixels,
+        and that data is passed back and forth between the processes. The callers of SharedBitmap will determine
+        if their image should support wide gamut, but ShareableBitmap will override a set flag on a device that
+        is incapbable of supporting a wide gamut image.
+        This makes it possible to show wide gamut images in image popovers on iOS.
+        This is currently untestable, so no tests added.
+
+        * Platform/IPC/Decoder.cpp:
+        (IPC::Decoder::decode):
+        * Platform/IPC/Decoder.h:
+        * Platform/IPC/Encoder.cpp:
+        (IPC::Encoder::encode):
+        * Platform/IPC/Encoder.h:
+        * Shared/ShareableBitmap.cpp:
+        (WebKit::bytesPerPixel):
+        (WebKit::ShareableBitmap::Handle::encode):
+        (WebKit::ShareableBitmap::Handle::decode):
+        (WebKit::ShareableBitmap::Handle::clear):
+        (WebKit::ShareableBitmap::create):
+        (WebKit::ShareableBitmap::createShareable):
+        (WebKit::ShareableBitmap::createHandle):
+        (WebKit::ShareableBitmap::ShareableBitmap):
+        * Shared/ShareableBitmap.h:
+        (WebKit::ShareableBitmap::numBytesForSize):
+        (WebKit::ShareableBitmap::sizeInBytes):
+        * Shared/cg/ShareableBitmapCG.cpp:
+        (WebKit::bitmapInfo):
+        (WebKit::ShareableBitmap::createGraphicsContext):
+        (WebKit::ShareableBitmap::createCGImage):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getPositionInformation):
+
 2016-10-27  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
index 8db0411..bb912ea 100644 (file)
 using namespace WebCore;
 
 namespace WebKit {
+    
+static unsigned calculateBytesPerPixel(ShareableBitmap::Flags flags)
+{
+    if (flags & ShareableBitmap::SupportsExtendedColor)
+        return 8; // for extended color, we are using half-float representations
+    return 4;
+}
 
 ShareableBitmap::Handle::Handle()
     : m_flags(0)
@@ -54,6 +61,7 @@ bool ShareableBitmap::Handle::decode(IPC::Decoder& decoder, Handle& handle)
         return false;
     if (!decoder.decode(handle.m_flags))
         return false;
+    handle.m_bytesPerPixel = calculateBytesPerPixel(handle.m_flags);
     return true;
 }
 
@@ -62,11 +70,13 @@ void ShareableBitmap::Handle::clear()
     m_handle.clear();
     m_size = IntSize();
     m_flags = Flag::NoFlags;
+    m_bytesPerPixel = calculateBytesPerPixel(m_flags);
 }
 
 RefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags)
 {
-    auto numBytes = numBytesForSize(size);
+    unsigned bytesPerPixel = calculateBytesPerPixel(flags);
+    auto numBytes = numBytesForSize(size, bytesPerPixel);
     if (numBytes.hasOverflowed())
         return nullptr;
 
@@ -79,7 +89,8 @@ RefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags
 
 RefPtr<ShareableBitmap> ShareableBitmap::createShareable(const IntSize& size, Flags flags)
 {
-    auto numBytes = numBytesForSize(size);
+    unsigned bytesPerPixel = calculateBytesPerPixel(flags);
+    auto numBytes = numBytesForSize(size, bytesPerPixel);
     if (numBytes.hasOverflowed())
         return nullptr;
 
@@ -94,14 +105,15 @@ RefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags
 {
     ASSERT(sharedMemory);
 
-    auto numBytes = numBytesForSize(size);
+    unsigned bytesPerPixel = calculateBytesPerPixel(flags);
+    auto numBytes = numBytesForSize(size, bytesPerPixel);
     if (numBytes.hasOverflowed())
         return nullptr;
     if (sharedMemory->size() < numBytes.unsafeGet()) {
         ASSERT_NOT_REACHED();
         return nullptr;
     }
-
+    
     return adoptRef(new ShareableBitmap(size, flags, sharedMemory));
 }
 
@@ -123,6 +135,7 @@ bool ShareableBitmap::createHandle(Handle& handle, SharedMemory::Protection prot
         return false;
     handle.m_size = m_size;
     handle.m_flags = m_flags;
+    handle.m_bytesPerPixel = m_bytesPerPixel;
     return true;
 }
 
@@ -131,6 +144,7 @@ ShareableBitmap::ShareableBitmap(const IntSize& size, Flags flags, void* data)
     , m_flags(flags)
     , m_data(data)
 {
+    m_bytesPerPixel = calculateBytesPerPixel(flags);
 }
 
 ShareableBitmap::ShareableBitmap(const IntSize& size, Flags flags, RefPtr<SharedMemory> sharedMemory)
@@ -139,6 +153,7 @@ ShareableBitmap::ShareableBitmap(const IntSize& size, Flags flags, RefPtr<Shared
     , m_sharedMemory(sharedMemory)
     , m_data(0)
 {
+    m_bytesPerPixel = calculateBytesPerPixel(flags);
 }
 
 ShareableBitmap::~ShareableBitmap()
index 923aa1f..5b1d433 100644 (file)
@@ -51,6 +51,7 @@ public:
     enum Flag {
         NoFlags = 0,
         SupportsAlpha = 1 << 0,
+        SupportsExtendedColor = 1 << 1,
     };
     typedef unsigned Flags;
 
@@ -72,6 +73,7 @@ public:
         mutable SharedMemory::Handle m_handle;
         WebCore::IntSize m_size;
         Flags m_flags;
+        unsigned m_bytesPerPixel;
     };
 
     // Create a shareable bitmap that uses malloced memory.
@@ -126,8 +128,9 @@ private:
 
 #if USE(CAIRO)
     static Checked<unsigned, RecordOverflow> numBytesForSize(const WebCore::IntSize&);
+    static Checked<unsigned, RecordOverflow> numBytesForSize(const WebCore::IntSize& size, unsigned bytesPerPixel) { return numBytesForSize(size); }
 #else
-    static Checked<unsigned, RecordOverflow> numBytesForSize(const WebCore::IntSize& size) { return size.area<RecordOverflow>() * 4; }
+    static Checked<unsigned, RecordOverflow> numBytesForSize(const WebCore::IntSize& size, unsigned bytesPerPixel) { return size.area<RecordOverflow>() * bytesPerPixel; }
 #endif
 
 #if USE(CG)
@@ -141,10 +144,15 @@ private:
 #endif
 
     void* data() const;
+#if USE(CAIRO)
     size_t sizeInBytes() const { return numBytesForSize(m_size).unsafeGet(); }
-
+#else
+    size_t sizeInBytes() const { return numBytesForSize(m_size, m_bytesPerPixel).unsafeGet(); }
+#endif
+    
     WebCore::IntSize m_size;
     Flags m_flags;
+    unsigned m_bytesPerPixel;
 
     // If the shareable bitmap is backed by shared memory, this points to the shared memory object.
     RefPtr<SharedMemory> m_sharedMemory;
index 8e3cca4..74624b2 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <WebCore/BitmapImage.h>
 #include <WebCore/GraphicsContextCG.h>
+#include <WebCore/PlatformScreen.h>
 #include <wtf/RetainPtr.h>
 #include "CGUtilities.h"
 
@@ -37,21 +38,40 @@ namespace WebKit {
 
 static CGBitmapInfo bitmapInfo(ShareableBitmap::Flags flags)
 {
-    CGBitmapInfo info = kCGBitmapByteOrder32Host;
-    if (flags & ShareableBitmap::SupportsAlpha)
-        info |= kCGImageAlphaPremultipliedFirst;
-    else
-        info |= kCGImageAlphaNoneSkipFirst;
-
+    CGBitmapInfo info = 0;
+    if ((flags & ShareableBitmap::SupportsExtendedColor) && screenSupportsExtendedColor()) {
+        info |= kCGBitmapFloatComponents | kCGBitmapByteOrder16Host;
+        
+        if (flags & ShareableBitmap::SupportsAlpha)
+            info |= kCGImageAlphaPremultipliedLast;
+        else
+            info |= kCGImageAlphaNoneSkipLast;
+        
+    } else {
+        info |= kCGBitmapByteOrder32Host;
+        
+        if (flags & ShareableBitmap::SupportsAlpha)
+            info |= kCGImageAlphaPremultipliedFirst;
+        else
+            info |= kCGImageAlphaNoneSkipFirst;
+    }
+    
     return info;
 }
 
 std::unique_ptr<GraphicsContext> ShareableBitmap::createGraphicsContext()
 {
     ref(); // Balanced by deref in releaseBitmapContextData.
-    RetainPtr<CGContextRef> bitmapContext = adoptCF(CGBitmapContextCreateWithData(data(),
-        m_size.width(), m_size.height(), 8, m_size.width() * 4, sRGBColorSpaceRef(),
-        bitmapInfo(m_flags), releaseBitmapContextData, this));
+    
+    CGColorSpaceRef colorSpace;
+    if (m_flags & ShareableBitmap::SupportsExtendedColor)
+        colorSpace = extendedSRGBColorSpaceRef();
+    else
+        colorSpace = sRGBColorSpaceRef();
+    
+    RetainPtr<CGContextRef> bitmapContext = adoptCF(CGBitmapContextCreateWithData(data(), m_size.width(), m_size.height(), m_bytesPerPixel * 8 / 4, m_size.width() * m_bytesPerPixel, colorSpace, bitmapInfo(m_flags), releaseBitmapContextData, this));
+    
+    ASSERT(bitmapContext.get());
 
     // We want the origin to be in the top left corner so we flip the backing store context.
     CGContextTranslateCTM(bitmapContext.get(), 0, m_size.height());
@@ -87,7 +107,7 @@ RetainPtr<CGImageRef> ShareableBitmap::makeCGImage()
 RetainPtr<CGImageRef> ShareableBitmap::createCGImage(CGDataProviderRef dataProvider) const
 {
     ASSERT_ARG(dataProvider, dataProvider);
-
+    // FIXME: Make this use extended color, etc.
     RetainPtr<CGImageRef> image = adoptCF(CGImageCreate(m_size.width(), m_size.height(), 8, 32, m_size.width() * 4, sRGBColorSpaceRef(), bitmapInfo(m_flags), dataProvider, 0, false, kCGRenderingIntentDefault));
     return image;
 }
index fe3bf8d..c41c9be 100644 (file)
@@ -2357,7 +2357,10 @@ void WebPage::getPositionInformation(const IntPoint& point, InteractionInformati
                                 screenSizeInPixels.scale(corePage()->deviceScaleFactor());
                                 FloatSize scaledSize = largestRectWithAspectRatioInsideRect(image->size().width() / image->size().height(), FloatRect(0, 0, screenSizeInPixels.width(), screenSizeInPixels.height())).size();
                                 FloatSize bitmapSize = scaledSize.width() < image->size().width() ? scaledSize : image->size();
-                                if (RefPtr<ShareableBitmap> sharedBitmap = ShareableBitmap::createShareable(IntSize(bitmapSize), ShareableBitmap::SupportsAlpha)) {
+                                // FIXME: Only select ExtendedColor on images known to need wide gamut
+                                ShareableBitmap::Flags flags = ShareableBitmap::SupportsAlpha;
+                                flags |= screenSupportsExtendedColor() ? ShareableBitmap::SupportsExtendedColor : 0;
+                                if (RefPtr<ShareableBitmap> sharedBitmap = ShareableBitmap::createShareable(IntSize(bitmapSize), flags)) {
                                     auto graphicsContext = sharedBitmap->createGraphicsContext();
                                     graphicsContext->drawImage(*image, FloatRect(0, 0, bitmapSize.width(), bitmapSize.height()));
                                     info.image = sharedBitmap;