Title: [269809] trunk
Revision
269809
Author
[email protected]
Date
2020-11-13 18:11:30 -0800 (Fri, 13 Nov 2020)

Log Message

[GPUProcess] Add basic GPUProcess crash handling for canvas
https://bugs.webkit.org/show_bug.cgi?id=218924

Reviewed by Simon Fraser.

Source/WebKit:

Update RemoteRenderingBackendProxy to be a GPUProcessConnection::Client so that it
gets notified when the IPC connection to the GPUProcess gets severed. When this
happens, RemoteRenderingBackendProxy clears all its SharedMemory handles and
sends IPC messages to the GPU process to recreate all the ImageBuffers we had.

* WebProcess/GPU/graphics/RemoteImageBufferProxy.h:
(WebKit::RemoteImageBufferProxy::create):
(WebKit::RemoteImageBufferProxy::clearBackend):
(WebKit::RemoteImageBufferProxy::size const):
(WebKit::RemoteImageBufferProxy::renderingMode const):
(WebKit::RemoteImageBufferProxy::colorSpace const):
(WebKit::RemoteImageBufferProxy::pixelFormat const):
(WebKit::RemoteImageBufferProxy::RemoteImageBufferProxy):
* WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
(WebKit::RemoteRenderingBackendProxy::RemoteRenderingBackendProxy):
(WebKit::RemoteRenderingBackendProxy::connectToGPUProcess):
(WebKit::recreateImage):
(WebKit::RemoteRenderingBackendProxy::gpuProcessConnectionDidClose):
(WebKit::RemoteRenderingBackendProxy::createImageBuffer):
* WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:
* WebProcess/GPU/graphics/RemoteResourceCacheProxy.h:
(WebKit::RemoteResourceCacheProxy::imageBuffers const):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
(convertToCGImage):
(getPixelIndex):
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (269808 => 269809)


--- trunk/Source/WebKit/ChangeLog	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Source/WebKit/ChangeLog	2020-11-14 02:11:30 UTC (rev 269809)
@@ -1,5 +1,35 @@
 2020-11-13  Chris Dumez  <[email protected]>
 
+        [GPUProcess] Add basic GPUProcess crash handling for canvas
+        https://bugs.webkit.org/show_bug.cgi?id=218924
+
+        Reviewed by Simon Fraser.
+
+        Update RemoteRenderingBackendProxy to be a GPUProcessConnection::Client so that it
+        gets notified when the IPC connection to the GPUProcess gets severed. When this
+        happens, RemoteRenderingBackendProxy clears all its SharedMemory handles and
+        sends IPC messages to the GPU process to recreate all the ImageBuffers we had.
+
+        * WebProcess/GPU/graphics/RemoteImageBufferProxy.h:
+        (WebKit::RemoteImageBufferProxy::create):
+        (WebKit::RemoteImageBufferProxy::clearBackend):
+        (WebKit::RemoteImageBufferProxy::size const):
+        (WebKit::RemoteImageBufferProxy::renderingMode const):
+        (WebKit::RemoteImageBufferProxy::colorSpace const):
+        (WebKit::RemoteImageBufferProxy::pixelFormat const):
+        (WebKit::RemoteImageBufferProxy::RemoteImageBufferProxy):
+        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
+        (WebKit::RemoteRenderingBackendProxy::RemoteRenderingBackendProxy):
+        (WebKit::RemoteRenderingBackendProxy::connectToGPUProcess):
+        (WebKit::recreateImage):
+        (WebKit::RemoteRenderingBackendProxy::gpuProcessConnectionDidClose):
+        (WebKit::RemoteRenderingBackendProxy::createImageBuffer):
+        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:
+        * WebProcess/GPU/graphics/RemoteResourceCacheProxy.h:
+        (WebKit::RemoteResourceCacheProxy::imageBuffers const):
+
+2020-11-13  Chris Dumez  <[email protected]>
+
         [GPUProcess] Add basic low memory handling in the GPUProcess
         https://bugs.webkit.org/show_bug.cgi?id=218926
         <rdar://problem/70300888>

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h (269808 => 269809)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h	2020-11-14 02:11:30 UTC (rev 269809)
@@ -48,12 +48,12 @@
     using BaseDisplayListImageBuffer::m_renderingResourceIdentifier;
 
 public:
-    static RefPtr<RemoteImageBufferProxy> create(const WebCore::FloatSize& size, float resolutionScale, RemoteRenderingBackendProxy& remoteRenderingBackendProxy)
+    static RefPtr<RemoteImageBufferProxy> create(const WebCore::FloatSize& size, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::ColorSpace colorSpace, WebCore::PixelFormat pixelFormat, RemoteRenderingBackendProxy& remoteRenderingBackendProxy)
     {
         if (BackendType::calculateBackendSize(size, resolutionScale).isEmpty())
             return nullptr;
 
-        return adoptRef(new RemoteImageBufferProxy(size, remoteRenderingBackendProxy));
+        return adoptRef(new RemoteImageBufferProxy(size, renderingMode, resolutionScale, colorSpace, pixelFormat, remoteRenderingBackendProxy));
     }
 
     ~RemoteImageBufferProxy()
@@ -65,6 +65,8 @@
         m_remoteRenderingBackendProxy->releaseRemoteResource(m_renderingResourceIdentifier);
     }
 
+    void clearBackend() { m_backend = nullptr; }
+
     void createBackend(const WebCore::FloatSize& logicalSize, const WebCore::IntSize& backendSize, float resolutionScale, WebCore::ColorSpace colorSpace, WebCore::PixelFormat pixelFormat, ImageBufferBackendHandle handle)
     {
         ASSERT(!m_backend);
@@ -76,10 +78,21 @@
         m_receivedFlushIdentifier = flushIdentifier;
     }
 
+    const WebCore::FloatSize& size() const { return m_size; }
+    WebCore::RenderingMode renderingMode() const { return m_renderingMode; }
+    float resolutionScale() const final { return m_resolutionScale; }
+    WebCore::ColorSpace colorSpace() const { return m_colorSpace; }
+    WebCore::PixelFormat pixelFormat() const { return m_pixelFormat; }
+
 protected:
-    RemoteImageBufferProxy(const WebCore::FloatSize& size, RemoteRenderingBackendProxy& remoteRenderingBackendProxy)
+    RemoteImageBufferProxy(const WebCore::FloatSize& size, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::ColorSpace colorSpace, WebCore::PixelFormat pixelFormat, RemoteRenderingBackendProxy& remoteRenderingBackendProxy)
         : BaseDisplayListImageBuffer(size, this)
         , m_remoteRenderingBackendProxy(makeWeakPtr(remoteRenderingBackendProxy))
+        , m_size(size)
+        , m_renderingMode(renderingMode)
+        , m_resolutionScale(resolutionScale)
+        , m_colorSpace(colorSpace)
+        , m_pixelFormat(pixelFormat)
     {
         ASSERT(m_remoteRenderingBackendProxy);
         m_remoteRenderingBackendProxy->remoteResourceCacheProxy().cacheImageBuffer(*this);
@@ -303,6 +316,11 @@
     WebCore::DisplayList::FlushIdentifier m_receivedFlushIdentifier;
     WeakPtr<RemoteRenderingBackendProxy> m_remoteRenderingBackendProxy;
     size_t m_itemCountInCurrentDisplayList { 0 };
+    WebCore::FloatSize m_size;
+    WebCore::RenderingMode m_renderingMode;
+    float m_resolutionScale;
+    WebCore::ColorSpace m_colorSpace;
+    WebCore::PixelFormat m_pixelFormat;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp (269808 => 269809)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp	2020-11-14 02:11:30 UTC (rev 269809)
@@ -30,7 +30,6 @@
 
 #include "DisplayListWriterHandle.h"
 #include "GPUConnectionToWebProcess.h"
-#include "GPUProcessConnection.h"
 #include "ImageDataReference.h"
 #include "PlatformRemoteImageBufferProxy.h"
 #include "RemoteRenderingBackendMessages.h"
@@ -49,12 +48,7 @@
 
 RemoteRenderingBackendProxy::RemoteRenderingBackendProxy()
 {
-    // Register itself as a MessageReceiver in the GPUProcessConnection.
-    IPC::MessageReceiverMap& messageReceiverMap = WebProcess::singleton().ensureGPUProcessConnection().messageReceiverMap();
-    messageReceiverMap.addMessageReceiver(Messages::RemoteRenderingBackendProxy::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this);
-
-    // Create the RemoteRenderingBackend
-    send(Messages::GPUConnectionToWebProcess::CreateRenderingBackend(m_renderingBackendIdentifier), 0);
+    connectToGPUProcess();
 }
 
 RemoteRenderingBackendProxy::~RemoteRenderingBackendProxy()
@@ -67,6 +61,47 @@
     send(Messages::GPUConnectionToWebProcess::ReleaseRenderingBackend(m_renderingBackendIdentifier), 0);
 }
 
+void RemoteRenderingBackendProxy::connectToGPUProcess()
+{
+    auto& connection = WebProcess::singleton().ensureGPUProcessConnection();
+    connection.addClient(*this);
+    connection.messageReceiverMap().addMessageReceiver(Messages::RemoteRenderingBackendProxy::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this);
+
+    send(Messages::GPUConnectionToWebProcess::CreateRenderingBackend(m_renderingBackendIdentifier), 0);
+}
+
+template<typename T>
+static void recreateImageBuffer(RemoteRenderingBackendProxy& proxy, T& imageBuffer, RenderingResourceIdentifier resourceIdentifier, RenderingBackendIdentifier renderingBackendIdentifier)
+{
+    imageBuffer.clearBackend();
+    proxy.send(Messages::RemoteRenderingBackend::CreateImageBuffer(imageBuffer.size(), imageBuffer.renderingMode(), imageBuffer.resolutionScale(), imageBuffer.colorSpace(), imageBuffer.pixelFormat(), resourceIdentifier), renderingBackendIdentifier);
+}
+
+void RemoteRenderingBackendProxy::reestablishGPUProcessConnection()
+{
+    connectToGPUProcess();
+
+    for (auto& pair : m_remoteResourceCacheProxy.imageBuffers()) {
+        if (auto& baseImageBuffer = pair.value) {
+            if (is<AcceleratedRemoteImageBufferProxy>(*baseImageBuffer))
+                recreateImageBuffer(*this, downcast<AcceleratedRemoteImageBufferProxy>(*baseImageBuffer), pair.key, m_renderingBackendIdentifier);
+            else
+                recreateImageBuffer(*this, downcast<UnacceleratedRemoteImageBufferProxy>(*baseImageBuffer), pair.key, m_renderingBackendIdentifier);
+        }
+    }
+}
+
+void RemoteRenderingBackendProxy::gpuProcessConnectionDidClose(GPUProcessConnection& previousConnection)
+{
+    previousConnection.removeClient(*this);
+
+    m_identifiersOfReusableHandles.clear();
+    m_identifiersOfHandlesAvailableForWriting.clear();
+    m_sharedDisplayListHandles.clear();
+
+    reestablishGPUProcessConnection();
+}
+
 IPC::Connection* RemoteRenderingBackendProxy::messageSenderConnection() const
 {
     return &WebProcess::singleton().ensureGPUProcessConnection().connection();
@@ -94,10 +129,10 @@
     RefPtr<ImageBuffer> imageBuffer;
 
     if (renderingMode == RenderingMode::Accelerated)
-        imageBuffer = AcceleratedRemoteImageBufferProxy::create(size, resolutionScale, *this);
+        imageBuffer = AcceleratedRemoteImageBufferProxy::create(size, renderingMode, resolutionScale, colorSpace, pixelFormat, *this);
 
     if (!imageBuffer)
-        imageBuffer = UnacceleratedRemoteImageBufferProxy::create(size, resolutionScale, *this);
+        imageBuffer = UnacceleratedRemoteImageBufferProxy::create(size, renderingMode, resolutionScale, colorSpace, pixelFormat, *this);
 
     if (imageBuffer) {
         send(Messages::RemoteRenderingBackend::CreateImageBuffer(size, renderingMode, resolutionScale, colorSpace, pixelFormat, imageBuffer->renderingResourceIdentifier()), m_renderingBackendIdentifier);

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h (269808 => 269809)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h	2020-11-14 02:11:30 UTC (rev 269809)
@@ -27,6 +27,7 @@
 
 #if ENABLE(GPU_PROCESS)
 
+#include "GPUProcessConnection.h"
 #include "ImageBufferBackendHandle.h"
 #include "MessageReceiver.h"
 #include "MessageSender.h"
@@ -56,7 +57,7 @@
 class RemoteRenderingBackendProxy
     : public IPC::MessageSender
     , private IPC::MessageReceiver
-    , public CanMakeWeakPtr<RemoteRenderingBackendProxy> {
+    , public GPUProcessConnection::Client {
 public:
     static std::unique_ptr<RemoteRenderingBackendProxy> create();
 
@@ -86,6 +87,11 @@
 private:
     RemoteRenderingBackendProxy();
 
+    // GPUProcessConnection::Client
+    void gpuProcessConnectionDidClose(GPUProcessConnection&) final;
+
+    void connectToGPUProcess();
+    void reestablishGPUProcessConnection();
     void updateReusableHandles();
 
     // Messages to be received.

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h (269808 => 269809)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h	2020-11-14 02:11:30 UTC (rev 269809)
@@ -49,8 +49,10 @@
 
     void cacheNativeImage(WebCore::NativeImage&);
 
+    using ImageBufferHashMap = HashMap<WebCore::RenderingResourceIdentifier, WeakPtr<WebCore::ImageBuffer>>;
+    const ImageBufferHashMap& imageBuffers() const { return m_imageBuffers; }
+
 private:
-    using ImageBufferHashMap = HashMap<WebCore::RenderingResourceIdentifier, WeakPtr<WebCore::ImageBuffer>>;
     using NativeImageHashMap = HashMap<WebCore::RenderingResourceIdentifier, WeakPtr<WebCore::NativeImage>>;
     
     void releaseNativeImage(WebCore::RenderingResourceIdentifier) override;

Modified: trunk/Tools/ChangeLog (269808 => 269809)


--- trunk/Tools/ChangeLog	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Tools/ChangeLog	2020-11-14 02:11:30 UTC (rev 269809)
@@ -1,3 +1,17 @@
+2020-11-13  Chris Dumez  <[email protected]>
+
+        [GPUProcess] Add basic GPUProcess crash handling for canvas
+        https://bugs.webkit.org/show_bug.cgi?id=218924
+
+        Reviewed by Simon Fraser.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
+        (convertToCGImage):
+        (getPixelIndex):
+        (TEST):
+
 2020-11-13  Aakash Jain  <[email protected]>
 
         [build.webkit.org] Update CompileWebKit step for new buildbot

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (269808 => 269809)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2020-11-14 01:09:38 UTC (rev 269808)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2020-11-14 02:11:30 UTC (rev 269809)
@@ -35,6 +35,30 @@
 #import <WebKit/_WKInternalDebugFeature.h>
 #import <wtf/RetainPtr.h>
 
+#if PLATFORM(MAC)
+typedef NSImage *PlatformImage;
+typedef NSWindow *PlatformWindow;
+
+static RetainPtr<CGImageRef> convertToCGImage(NSImage *image)
+{
+    return [image CGImageForProposedRect:nil context:nil hints:nil];
+}
+
+#else
+typedef UIImage *PlatformImage;
+typedef UIWindow *PlatformWindow;
+
+static RetainPtr<CGImageRef> convertToCGImage(UIImage *image)
+{
+    return image.CGImage;
+}
+#endif
+
+static NSInteger getPixelIndex(NSInteger x, NSInteger y, NSInteger width)
+{
+    return (y * width + x) * 4;
+}
+
 TEST(GPUProcess, RelaunchOnCrash)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
@@ -260,3 +284,151 @@
     EXPECT_EQ(gpuProcessPID, [processPool _gpuProcessIdentifier]);
     EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]);
 }
+
+static NSString *testCanvasPage = @"<body> \n"
+    "<canvas id='myCanvas' width='400px' height='400px'>\n"
+    "<script> \n"
+    "var context = document.getElementById('myCanvas').getContext('2d'); \n"
+    "</script> \n"
+    "</body>";
+
+TEST(GPUProcess, CanvasBasicCrashHandling)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
+        if ([feature.key isEqualToString:@"UseGPUProcessForCanvasRenderingEnabled"]) {
+            [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature];
+            break;
+        }
+    }
+
+    NSInteger viewWidth = 400;
+    NSInteger viewHeight = 400;
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, viewWidth, viewHeight) configuration:configuration.get() addToWindow:NO]);
+
+    RetainPtr<PlatformWindow> window;
+    CGFloat backingScaleFactor;
+
+#if PLATFORM(MAC)
+    window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
+    [[window contentView] addSubview:webView.get()];
+    backingScaleFactor = [window backingScaleFactor];
+#elif PLATFORM(IOS_FAMILY)
+    window = adoptNS([[UIWindow alloc] initWithFrame:[webView frame]]);
+    [window addSubview:webView.get()];
+    backingScaleFactor = [[window screen] scale];
+#endif
+
+    [webView synchronouslyLoadHTMLString:testCanvasPage];
+
+    auto webViewPID = [webView _webProcessIdentifier];
+
+    // Try painting the canvas red.
+    __block bool done = false;
+    [webView evaluateJavaScript:@"context.fillStyle = '#FF0000'; context.fillRect(0, 0, 400, 400);" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    [webView waitForNextPresentationUpdate];
+
+    // The GPU process should have been launched.
+    auto* processPool = configuration.get().processPool;
+    unsigned timeout = 0;
+    while (![processPool _gpuProcessIdentifier] && timeout++ < 100)
+        TestWebKitAPI::Util::sleep(0.1);
+    auto gpuProcessPID = [processPool _gpuProcessIdentifier];
+    EXPECT_NE(0, gpuProcessPID);
+
+    auto snapshotConfiguration = adoptNS([[WKSnapshotConfiguration alloc] init]);
+    [snapshotConfiguration setRect:NSMakeRect(0, 0, 150, 150)];
+    [snapshotConfiguration setSnapshotWidth:@(150)];
+    [snapshotConfiguration setAfterScreenUpdates:YES];
+
+    // Make sure a red square is painted.
+    done = false;
+    [webView takeSnapshotWithConfiguration:snapshotConfiguration.get() completionHandler:^(PlatformImage snapshotImage, NSError *error) {
+        EXPECT_TRUE(!error);
+
+        RetainPtr<CGImageRef> cgImage = convertToCGImage(snapshotImage);
+        RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
+
+        NSInteger viewWidthInPixels = viewWidth * backingScaleFactor;
+        NSInteger viewHeightInPixels = viewHeight * backingScaleFactor;
+
+        uint8_t *rgba = (unsigned char *)calloc(viewWidthInPixels * viewHeightInPixels * 4, sizeof(unsigned char));
+        RetainPtr<CGContextRef> context = CGBitmapContextCreate(rgba, viewWidthInPixels, viewHeightInPixels, 8, 4 * viewWidthInPixels, colorSpace.get(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
+        CGContextDrawImage(context.get(), CGRectMake(0, 0, viewWidthInPixels, viewHeightInPixels), cgImage.get());
+
+        NSInteger pixelIndex = getPixelIndex(50, 50, viewWidthInPixels);
+        EXPECT_EQ(255, rgba[pixelIndex]);
+        EXPECT_EQ(0, rgba[pixelIndex + 1]);
+        EXPECT_EQ(0, rgba[pixelIndex + 2]);
+
+        pixelIndex = getPixelIndex(100, 100, viewWidthInPixels);
+        EXPECT_EQ(255, rgba[pixelIndex]);
+        EXPECT_EQ(0, rgba[pixelIndex + 1]);
+        EXPECT_EQ(0, rgba[pixelIndex + 2]);
+
+        free(rgba);
+
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    // Kill the GPUProcess.
+    kill(gpuProcessPID, 9);
+
+    // GPU Process should get relaunched.
+    timeout = 0;
+    while ((![processPool _gpuProcessIdentifier] || [processPool _gpuProcessIdentifier] == gpuProcessPID) && timeout++ < 100)
+        TestWebKitAPI::Util::sleep(0.1);
+    EXPECT_NE([processPool _gpuProcessIdentifier], 0);
+    EXPECT_NE([processPool _gpuProcessIdentifier], gpuProcessPID);
+    gpuProcessPID = [processPool _gpuProcessIdentifier];
+
+    // WebProcess should not have crashed.
+    EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]);
+
+    // Try painting the canvas green.
+    done = false;
+    [webView evaluateJavaScript:@"context.fillStyle = '#00FF00'; context.fillRect(0, 0, 400, 400);" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    [webView waitForNextPresentationUpdate];
+
+    // Make sure a green square is painted.
+    done = false;
+    [webView takeSnapshotWithConfiguration:snapshotConfiguration.get() completionHandler:^(PlatformImage snapshotImage, NSError *error) {
+        EXPECT_TRUE(!error);
+
+        RetainPtr<CGImageRef> cgImage = convertToCGImage(snapshotImage);
+        RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
+
+        NSInteger viewWidthInPixels = viewWidth * backingScaleFactor;
+        NSInteger viewHeightInPixels = viewHeight * backingScaleFactor;
+
+        uint8_t *rgba = (unsigned char *)calloc(viewWidthInPixels * viewHeightInPixels * 4, sizeof(unsigned char));
+        RetainPtr<CGContextRef> context = CGBitmapContextCreate(rgba, viewWidthInPixels, viewHeightInPixels, 8, 4 * viewWidthInPixels, colorSpace.get(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
+        CGContextDrawImage(context.get(), CGRectMake(0, 0, viewWidthInPixels, viewHeightInPixels), cgImage.get());
+
+        NSInteger pixelIndex = getPixelIndex(50, 50, viewWidthInPixels);
+        EXPECT_EQ(0, rgba[pixelIndex]);
+        EXPECT_EQ(255, rgba[pixelIndex + 1]);
+        EXPECT_EQ(0, rgba[pixelIndex + 2]);
+
+        pixelIndex = getPixelIndex(100, 100, viewWidthInPixels);
+        EXPECT_EQ(0, rgba[pixelIndex]);
+        EXPECT_EQ(255, rgba[pixelIndex + 1]);
+        EXPECT_EQ(0, rgba[pixelIndex + 2]);
+
+        free(rgba);
+
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to