Title: [215176] trunk/Tools
Revision
215176
Author
commit-qu...@webkit.org
Date
2017-04-10 03:16:26 -0700 (Mon, 10 Apr 2017)

Log Message

WTR: Avoid conversion from platform image to WKImage and then to platform image again when dumping pixel results
https://bugs.webkit.org/show_bug.cgi?id=170653

Patch by Carlos Garcia Campos <cgar...@igalia.com> on 2017-04-10
Reviewed by Tim Horton.

When dumping pixels from a web view snapshot, we create a platform image that is then converted to a WKImage,
which is a ShareableBitmap, so the image is rendered into a graphics context. Then we immediately extract the
platform image back from the WKImage to dump the pixels. We could avoid that conversion by taking the web
snapshot from TestInvocation::dumpPixelsAndCompareWithExpected().

* WebKitTestRunner/PlatformWebView.h: Add PlatformImage typedef and use it as return value of windowSnapshotImage().
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::dumpResults): Pass the WKImage to dumpPixelsAndCompareWithExpected() only when pixel
results were created in the web process.
* WebKitTestRunner/TestInvocation.h: Make WKImage a default paramater of dumpPixelsAndCompareWithExpected().
* WebKitTestRunner/cairo/TestInvocationCairo.cpp:
(WTR::TestInvocation::dumpPixelsAndCompareWithExpected): Create the cairo surface from the given WKimage in case
of web contents snapshot, and use PlatformWebView::windowSnapshotImage() in case of web view snapshot.
* WebKitTestRunner/cg/TestInvocationCG.cpp:
(WTR::createCGContextFromCGImage): Changed to receive a CGImageRef and renamed.
(WTR::createCGContextFromImage): Get the CGImageRef from the WKImage and call createCGContextFromCGImage().
(WTR::paintRepaintRectOverlay): It receives now the image size instead of the WKImage.
(WTR::TestInvocation::dumpPixelsAndCompareWithExpected): Create the CGContextRef from the WKImage in case of web
contents snpashot, and use PlatformWebView::windowSnapshotImage() in case of web view snapshot.
* WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
(WTR::PlatformWebView::windowSnapshotImage): Return the cairo surface instead of creating a WKImage. Also use
RGB24 format to match what mac does (kCGWindowImageShouldBeOpaque).
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::windowSnapshotImage): Return the CGImageRef instead of creating a WKImage.
* WebKitTestRunner/mac/PlatformWebViewMac.mm:
(WTR::PlatformWebView::windowSnapshotImage): Ditto.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (215175 => 215176)


--- trunk/Tools/ChangeLog	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/ChangeLog	2017-04-10 10:16:26 UTC (rev 215176)
@@ -1,3 +1,37 @@
+2017-04-10  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        WTR: Avoid conversion from platform image to WKImage and then to platform image again when dumping pixel results
+        https://bugs.webkit.org/show_bug.cgi?id=170653
+
+        Reviewed by Tim Horton.
+
+        When dumping pixels from a web view snapshot, we create a platform image that is then converted to a WKImage,
+        which is a ShareableBitmap, so the image is rendered into a graphics context. Then we immediately extract the
+        platform image back from the WKImage to dump the pixels. We could avoid that conversion by taking the web
+        snapshot from TestInvocation::dumpPixelsAndCompareWithExpected().
+
+        * WebKitTestRunner/PlatformWebView.h: Add PlatformImage typedef and use it as return value of windowSnapshotImage().
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::dumpResults): Pass the WKImage to dumpPixelsAndCompareWithExpected() only when pixel
+        results were created in the web process.
+        * WebKitTestRunner/TestInvocation.h: Make WKImage a default paramater of dumpPixelsAndCompareWithExpected().
+        * WebKitTestRunner/cairo/TestInvocationCairo.cpp:
+        (WTR::TestInvocation::dumpPixelsAndCompareWithExpected): Create the cairo surface from the given WKimage in case
+        of web contents snapshot, and use PlatformWebView::windowSnapshotImage() in case of web view snapshot.
+        * WebKitTestRunner/cg/TestInvocationCG.cpp:
+        (WTR::createCGContextFromCGImage): Changed to receive a CGImageRef and renamed.
+        (WTR::createCGContextFromImage): Get the CGImageRef from the WKImage and call createCGContextFromCGImage().
+        (WTR::paintRepaintRectOverlay): It receives now the image size instead of the WKImage.
+        (WTR::TestInvocation::dumpPixelsAndCompareWithExpected): Create the CGContextRef from the WKImage in case of web
+        contents snpashot, and use PlatformWebView::windowSnapshotImage() in case of web view snapshot.
+        * WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
+        (WTR::PlatformWebView::windowSnapshotImage): Return the cairo surface instead of creating a WKImage. Also use
+        RGB24 format to match what mac does (kCGWindowImageShouldBeOpaque).
+        * WebKitTestRunner/ios/PlatformWebViewIOS.mm:
+        (WTR::PlatformWebView::windowSnapshotImage): Return the CGImageRef instead of creating a WKImage.
+        * WebKitTestRunner/mac/PlatformWebViewMac.mm:
+        (WTR::PlatformWebView::windowSnapshotImage): Ditto.
+
 2017-04-10  Chris Dumez  <cdu...@apple.com>
 
         Drop Timer::startOneShot() overload taking a double

Modified: trunk/Tools/WebKitTestRunner/PlatformWebView.h (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/PlatformWebView.h	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/PlatformWebView.h	2017-04-10 10:16:26 UTC (rev 215176)
@@ -27,15 +27,16 @@
 #define PlatformWebView_h
 
 #include "TestOptions.h"
-#include <WebKit/WKRetainPtr.h>
 
 #if PLATFORM(COCOA) && !defined(BUILDING_GTK__)
 #include <WebKit/WKFoundation.h>
+#include <wtf/RetainPtr.h>
 OBJC_CLASS NSView;
 OBJC_CLASS UIView;
 OBJC_CLASS TestRunnerWKWebView;
 OBJC_CLASS WKWebViewConfiguration;
 OBJC_CLASS WebKitTestRunnerWindow;
+typedef struct CGImage *CGImageRef;
 
 #if WK_API_ENABLED
 typedef TestRunnerWKWebView *PlatformWKView;
@@ -43,10 +44,12 @@
 typedef NSView *PlatformWKView;
 #endif
 typedef WebKitTestRunnerWindow *PlatformWindow;
+typedef RetainPtr<CGImageRef> PlatformImage;
 #elif defined(BUILDING_GTK__)
 typedef struct _GtkWidget GtkWidget;
 typedef WKViewRef PlatformWKView;
 typedef GtkWidget* PlatformWindow;
+typedef cairo_surface_t *PlatformImage;
 #elif PLATFORM(EFL)
 typedef Evas_Object* PlatformWKView;
 typedef Ecore_Evas* PlatformWindow;
@@ -92,7 +95,7 @@
 
     bool viewSupportsOptions(const TestOptions&) const;
 
-    WKRetainPtr<WKImageRef> windowSnapshotImage();
+    PlatformImage windowSnapshotImage();
     const TestOptions& options() const { return m_options; }
 
     void changeWindowScaleIfNeeded(float newScale);

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2017-04-10 10:16:26 UTC (rev 215176)
@@ -267,7 +267,7 @@
 
     if (m_dumpPixels) {
         if (m_pixelResult)
-            dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebContents);
+            dumpPixelsAndCompareWithExpected(SnapshotResultType::WebContents, m_repaintRects.get(), m_pixelResult.get());
         else if (m_pixelResultIsPending) {
             m_gotRepaint = false;
             WKPageForceRepaint(TestController::singleton().mainWebView()->page(), this, TestInvocation::forceRepaintDoneCallback);
@@ -278,8 +278,7 @@
                 return;
             }
 
-            WKRetainPtr<WKImageRef> windowSnapshot = TestController::singleton().mainWebView()->windowSnapshotImage();
-            dumpPixelsAndCompareWithExpected(windowSnapshot.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebView);
+            dumpPixelsAndCompareWithExpected(SnapshotResultType::WebView, m_repaintRects.get());
         }
     }
 

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.h (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/TestInvocation.h	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.h	2017-04-10 10:16:26 UTC (rev 215176)
@@ -75,7 +75,7 @@
     void dumpResults();
     static void dump(const char* textToStdout, const char* textToStderr = 0, bool seenError = false);
     enum class SnapshotResultType { WebView, WebContents };
-    void dumpPixelsAndCompareWithExpected(WKImageRef, WKArrayRef repaintRects, SnapshotResultType);
+    void dumpPixelsAndCompareWithExpected(SnapshotResultType, WKArrayRef repaintRects, WKImageRef = nullptr);
     void dumpAudio(WKDataRef);
     bool compareActualHashToExpectedAndDumpResults(const char[33]);
 

Modified: trunk/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp	2017-04-10 10:16:26 UTC (rev 215176)
@@ -106,9 +106,17 @@
     cairo_destroy(context);
 }
 
-void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef image, WKArrayRef repaintRects, SnapshotResultType)
+void TestInvocation::dumpPixelsAndCompareWithExpected(SnapshotResultType snapshotType, WKArrayRef repaintRects, WKImageRef image)
 {
-    cairo_surface_t* surface = WKImageCreateCairoSurface(image);
+    cairo_surface_t* surface = nullptr;
+    switch (snapshotType) {
+    case SnapshotResultType::WebContents:
+        surface = WKImageCreateCairoSurface(image);
+        break;
+    case SnapshotResultType::WebView:
+        surface = TestController::singleton().mainWebView()->windowSnapshotImage();
+        break;
+    }
 
     if (repaintRects)
         paintRepaintRectOverlay(surface, repaintRects);

Modified: trunk/Tools/WebKitTestRunner/cg/TestInvocationCG.cpp (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/cg/TestInvocationCG.cpp	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/cg/TestInvocationCG.cpp	2017-04-10 10:16:26 UTC (rev 215176)
@@ -46,12 +46,10 @@
 
 namespace WTR {
 
-static CGContextRef createCGContextFromImage(WKImageRef wkImage)
+static CGContextRef createCGContextFromCGImage(CGImageRef image)
 {
-    RetainPtr<CGImageRef> image = adoptCF(WKImageCreateCGImage(wkImage));
-
-    size_t pixelsWide = CGImageGetWidth(image.get());
-    size_t pixelsHigh = CGImageGetHeight(image.get());
+    size_t pixelsWide = CGImageGetWidth(image);
+    size_t pixelsHigh = CGImageGetHeight(image);
     size_t rowBytes = (4 * pixelsWide + 63) & ~63;
 
     // Creating this bitmap in the device color space should prevent any color conversion when the image of the web view is drawn into it.
@@ -60,10 +58,16 @@
     if (!context)
         return nullptr;
 
-    CGContextDrawImage(context, CGRectMake(0, 0, pixelsWide, pixelsHigh), image.get());
+    CGContextDrawImage(context, CGRectMake(0, 0, pixelsWide, pixelsHigh), image);
     return context;
 }
 
+static CGContextRef createCGContextFromImage(WKImageRef wkImage)
+{
+    RetainPtr<CGImageRef> image = adoptCF(WKImageCreateCGImage(wkImage));
+    return createCGContextFromCGImage(image.get());
+}
+
 void computeMD5HashStringForContext(CGContextRef bitmapContext, char hashString[33])
 {
     if (!bitmapContext) {
@@ -118,10 +122,8 @@
     printPNG(data, dataLength, checksum);
 }
 
-static void paintRepaintRectOverlay(CGContextRef context, WKImageRef image, WKArrayRef repaintRects)
+static void paintRepaintRectOverlay(CGContextRef context, WKSize imageSize, WKArrayRef repaintRects)
 {
-    WKSize imageSize = WKImageGetSize(image);
-
     CGContextSaveGState(context);
 
     // Using a transparency layer is easier than futzing with clipping.
@@ -146,14 +148,31 @@
     CGContextRestoreGState(context);
 }
 
-void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef image, WKArrayRef repaintRects, SnapshotResultType snapshotType)
+void TestInvocation::dumpPixelsAndCompareWithExpected(SnapshotResultType snapshotType, WKArrayRef repaintRects, WKImageRef wkImage)
 {
-    if (!image) {
-        WTFLogAlways("dumpPixelsAndCompareWithExpected: image is null\n");
-        return;
+    RetainPtr<CGContextRef> context;
+    WKSize imageSize;
+
+    switch (snapshotType) {
+    case SnapshotResultType::WebContents:
+        if (!wkImage) {
+            WTFLogAlways("dumpPixelsAndCompareWithExpected: image is null\n");
+            return;
+        }
+        context = adoptCF(createCGContextFromImage(wkImage));
+        imageSize = WKImageGetSize(wkImage);
+        break;
+    case SnapshotResultType::WebView:
+        auto image = TestController::singleton().mainWebView()->windowSnapshotImage();
+        if (!image) {
+            WTFLogAlways("dumpPixelsAndCompareWithExpected: image is null\n");
+            return;
+        }
+        context = adoptCF(createCGContextFromCGImage(image.get()));
+        imageSize = WKSizeMake(CGImageGetWidth(image.get()), CGImageGetHeight(image.get()));
+        break;
     }
 
-    RetainPtr<CGContextRef> context = adoptCF(createCGContextFromImage(image));
     if (!context) {
         WTFLogAlways("dumpPixelsAndCompareWithExpected: context is null\n");
         return;
@@ -161,7 +180,7 @@
 
     // A non-null repaintRects array means we're doing a repaint test.
     if (repaintRects)
-        paintRepaintRectOverlay(context.get(), image, repaintRects);
+        paintRepaintRectOverlay(context.get(), imageSize, repaintRects);
 
     char actualHash[33];
     computeMD5HashStringForContext(context.get(), actualHash);

Modified: trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp	2017-04-10 10:16:26 UTC (rev 215176)
@@ -132,7 +132,7 @@
 {
 }
 
-WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
+cairo_surface_t* PlatformWebView::windowSnapshotImage()
 {
     int width = gtk_widget_get_allocated_width(GTK_WIDGET(m_view));
     int height = gtk_widget_get_allocated_height(GTK_WIDGET(m_view));
@@ -140,16 +140,13 @@
     while (gtk_events_pending())
         gtk_main_iteration();
 
-    cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+    cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
 
     cairo_t* context = cairo_create(imageSurface);
     gtk_widget_draw(GTK_WIDGET(m_view), context);
     cairo_destroy(context);
 
-    WKRetainPtr<WKImageRef> wkImage = adoptWK(WKImageCreateFromCairoSurface(imageSurface, 0 /* options */));
-
-    cairo_surface_destroy(imageSurface);
-    return wkImage;
+    return imageSurface;
 }
 
 void PlatformWebView::didInitializeClients()

Modified: trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm	2017-04-10 10:16:26 UTC (rev 215176)
@@ -250,8 +250,15 @@
     // Retina only surface.
 }
 
-WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
+#if !USE(IOSURFACE)
+static void releaseDataProviderData(void* info, const void*, size_t)
 {
+    CARenderServerDestroyBuffer(static_cast<CARenderServerBufferRef>(info));
+}
+#endif
+
+RetainPtr<CGImageRef> PlatformWebView::windowSnapshotImage()
+{
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 #if USE(IOSURFACE)
     return nullptr;
@@ -279,14 +286,11 @@
     size_t rowBytes = CARenderServerGetBufferRowBytes(buffer);
 
     static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
-    RetainPtr<CGDataProviderRef> provider = adoptCF(CGDataProviderCreateWithData(0, data, CARenderServerGetBufferDataSize(buffer), nullptr));
+    RetainPtr<CGDataProviderRef> provider = adoptCF(CGDataProviderCreateWithData(0, data, CARenderServerGetBufferDataSize(buffer), releaseDataProviderData));
     
     RetainPtr<CGImageRef> cgImage = adoptCF(CGImageCreate(bufferWidth, bufferHeight, 8, 32, rowBytes, sRGBSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, provider.get(), 0, false, kCGRenderingIntentDefault));
-    WKRetainPtr<WKImageRef> result = adoptWK(WKImageCreateFromCGImage(cgImage.get(), 0));
 
-    CARenderServerDestroyBuffer(buffer);
-
-    return result;
+    return cgImage;
 #endif
     END_BLOCK_OBJC_EXCEPTIONS;
 }

Modified: trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm (215175 => 215176)


--- trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm	2017-04-10 10:01:46 UTC (rev 215175)
+++ trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm	2017-04-10 10:16:26 UTC (rev 215176)
@@ -271,7 +271,7 @@
     [m_window makeFirstResponder:platformView()];
 }
 
-WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
+RetainPtr<CGImageRef> PlatformWebView::windowSnapshotImage()
 {
     [platformView() display];
     CGWindowImageOption options = kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque;
@@ -279,10 +279,7 @@
     if ([m_window backingScaleFactor] == 1)
         options |= kCGWindowImageNominalResolution;
 
-    RetainPtr<CGImageRef> windowSnapshotImage = adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, [m_window windowNumber], options));
-
-    // windowSnapshotImage will be in GenericRGB, as we've set the main display's color space to GenericRGB.
-    return adoptWK(WKImageCreateFromCGImage(windowSnapshotImage.get(), 0));
+    return adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, [m_window windowNumber], options));
 }
 
 bool PlatformWebView::viewSupportsOptions(const TestOptions& options) const
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to