WebWidget should be able to paint into a zoomed canvas without aliasing
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Aug 2012 20:24:56 +0000 (20:24 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Aug 2012 20:24:56 +0000 (20:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=92043

Reviewed by James Robinson.

If accelerated compositing is enabled, WebWidget::paint reads back from
the compositor rather than re-painting the widget. That approach works
well if the canvas we're rendering into is at a similar resolution to
the pixels in the compositor, but if the canvas has been scaled (e.g.,
to help the user disambiguate links), then reading back from the
compositor will cause aliasing artifacts.

This patch adds an option to paint to let the embedder request a
software re-rendering of the widget to avoid these aliasing artifacts.

* public/WebWidget.h:
(WebKit::WebWidget::paint):
* src/WebPagePopupImpl.cpp:
(WebKit::WebPagePopupImpl::paint):
* src/WebPagePopupImpl.h:
(WebPagePopupImpl):
* src/WebPopupMenuImpl.cpp:
(WebKit::WebPopupMenuImpl::paint):
* src/WebPopupMenuImpl.h:
* src/WebViewImpl.cpp:
(WebKit::canvasBackgroundForTransparencey):
(WebKit):
(WebKit::WebViewImpl::paint):
* src/WebViewImpl.h:
(WebViewImpl):

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

Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/public/WebWidget.h
Source/WebKit/chromium/src/WebPagePopupImpl.cpp
Source/WebKit/chromium/src/WebPagePopupImpl.h
Source/WebKit/chromium/src/WebPopupMenuImpl.cpp
Source/WebKit/chromium/src/WebPopupMenuImpl.h
Source/WebKit/chromium/src/WebViewImpl.cpp
Source/WebKit/chromium/src/WebViewImpl.h

index 0e25311..de57b5a 100644 (file)
@@ -1,3 +1,36 @@
+2012-08-22  Adam Barth  <abarth@webkit.org>
+
+        WebWidget should be able to paint into a zoomed canvas without aliasing
+        https://bugs.webkit.org/show_bug.cgi?id=92043
+
+        Reviewed by James Robinson.
+
+        If accelerated compositing is enabled, WebWidget::paint reads back from
+        the compositor rather than re-painting the widget. That approach works
+        well if the canvas we're rendering into is at a similar resolution to
+        the pixels in the compositor, but if the canvas has been scaled (e.g.,
+        to help the user disambiguate links), then reading back from the
+        compositor will cause aliasing artifacts.
+
+        This patch adds an option to paint to let the embedder request a
+        software re-rendering of the widget to avoid these aliasing artifacts.
+
+        * public/WebWidget.h:
+        (WebKit::WebWidget::paint):
+        * src/WebPagePopupImpl.cpp:
+        (WebKit::WebPagePopupImpl::paint):
+        * src/WebPagePopupImpl.h:
+        (WebPagePopupImpl):
+        * src/WebPopupMenuImpl.cpp:
+        (WebKit::WebPopupMenuImpl::paint):
+        * src/WebPopupMenuImpl.h:
+        * src/WebViewImpl.cpp:
+        (WebKit::canvasBackgroundForTransparencey):
+        (WebKit):
+        (WebKit::WebViewImpl::paint):
+        * src/WebViewImpl.h:
+        (WebViewImpl):
+
 2012-08-22  Eric Penner  <epenner@google.com>
 
         [chromium] Simplify updateContentRect, removing rect parameter, refactor unit tests.
index 8e4feca..ac16581 100644 (file)
@@ -41,6 +41,7 @@
 
 #define WEBKIT_HAS_NEW_FULLSCREEN_API 1
 #define WEBWIDGET_HAS_SETCOMPOSITORSURFACEREADY 1
+#define WEBWIDGET_HAS_PAINT_OPTIONS 1
 
 namespace WebKit {
 
@@ -90,6 +91,21 @@ public:
     // and it may result in calls to WebWidgetClient::didInvalidateRect.
     virtual void layout() { }
 
+    enum PaintOptions {
+        // Attempt to fulfill the painting request by reading back from the
+        // compositor, assuming we're using a compositor to render.
+        ReadbackFromCompositorIfAvailable,
+
+        // Force the widget to rerender onto the canvas using software. This
+        // mode ignores 3d transforms and ignores GPU-resident content, such
+        // as video, canvas, and WebGL.
+        //
+        // Note: This option exists on OS(ANDROID) and will hopefully be
+        //       removed once the link disambiguation feature renders using
+        //       the compositor.
+        ForceSoftwareRenderingAndIgnoreGPUResidentContent,
+    };
+
     // Called to paint the rectangular region within the WebWidget
     // onto the specified canvas at (viewPort.x,viewPort.y). You MUST call
     // Layout before calling this method. It is okay to call paint
@@ -97,7 +113,7 @@ public:
     // changes are made to the WebWidget (e.g., once events are
     // processed, it should be assumed that another call to layout is
     // warranted before painting again).
-    virtual void paint(WebCanvas*, const WebRect& viewPort) { }
+    virtual void paint(WebCanvas*, const WebRect& viewPort, PaintOptions = ReadbackFromCompositorIfAvailable) { }
 
     // In non-threaded compositing mode, triggers compositing of the current
     // layers onto the screen. You MUST call Layout before calling this method,
index fe945c0..980f81a 100644 (file)
@@ -225,7 +225,7 @@ void WebPagePopupImpl::layout()
     PageWidgetDelegate::layout(m_page.get());
 }
 
-void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect)
+void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions)
 {
     PageWidgetDelegate::paint(m_page.get(), 0, canvas, rect, PageWidgetDelegate::Opaque);
 }
index 76936a4..e6844bf 100644 (file)
@@ -72,7 +72,7 @@ private:
     virtual void setCompositorSurfaceReady() OVERRIDE;
     virtual void composite(bool) OVERRIDE;
     virtual void layout() OVERRIDE;
-    virtual void paint(WebCanvas*, const WebRect&) OVERRIDE;
+    virtual void paint(WebCanvas*, const WebRect&, PaintOptions = ReadbackFromCompositorIfAvailable) OVERRIDE;
     virtual void resize(const WebSize&) OVERRIDE;
     virtual void close() OVERRIDE;
     virtual bool handleInputEvent(const WebInputEvent&) OVERRIDE;
index ec89930..194dee5 100644 (file)
@@ -193,7 +193,7 @@ void WebPopupMenuImpl::layout()
 {
 }
 
-void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect)
+void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions)
 {
     if (!m_widget)
         return;
index c22a0bb..7f13e43 100644 (file)
@@ -73,7 +73,7 @@ public:
     virtual void willEndLiveResize() OVERRIDE;
     virtual void animate(double frameBeginTime) OVERRIDE;
     virtual void layout() OVERRIDE;
-    virtual void paint(WebCanvas*, const WebRect&) OVERRIDE;
+    virtual void paint(WebCanvas*, const WebRect&, PaintOptions = ReadbackFromCompositorIfAvailable) OVERRIDE;
     virtual void themeChanged() OVERRIDE;
     virtual void setCompositorSurfaceReady() OVERRIDE;
     virtual void composite(bool finish) OVERRIDE;
index b18e209..b937802 100644 (file)
@@ -1685,9 +1685,15 @@ void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect
 }
 #endif
 
-void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
+void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions option)
 {
-    if (isAcceleratedCompositingActive()) {
+#if !OS(ANDROID)
+    // ReadbackFromCompositorIfAvailable is the only option available on non-Android.
+    // Ideally, Android would always use ReadbackFromCompositorIfAvailable as well.
+    ASSERT(option == ReadbackFromCompositorIfAvailable);
+#endif
+
+    if (option == ReadbackFromCompositorIfAvailable && isAcceleratedCompositingActive()) {
 #if USE(ACCELERATED_COMPOSITING)
         // If a canvas was passed in, we use it to grab a copy of the
         // freshly-rendered pixels.
@@ -1699,12 +1705,24 @@ void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
         }
 #endif
     } else {
+        FrameView* view = page()->mainFrame()->view();
+        PaintBehavior oldPaintBehavior = view->paintBehavior();
+        if (isAcceleratedCompositingActive()) {
+            ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);            
+            view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers);
+        }
+
         double paintStart = currentTime();
         PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect, isTransparent() ? PageWidgetDelegate::Translucent : PageWidgetDelegate::Opaque);
         double paintEnd = currentTime();
         double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart);
         WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30);
         WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30);
+
+        if (isAcceleratedCompositingActive()) {
+            ASSERT(option == ForceSoftwareRenderingAndIgnoreGPUResidentContent);            
+            view->setPaintBehavior(oldPaintBehavior);
+        }
     }
 }
 
index b8dcad7..6954ab0 100644 (file)
@@ -143,7 +143,7 @@ public:
     virtual void setCompositorSurfaceReady();
     virtual void animate(double);
     virtual void layout(); // Also implements WebLayerTreeViewClient::layout()
-    virtual void paint(WebCanvas*, const WebRect&);
+    virtual void paint(WebCanvas*, const WebRect&, PaintOptions = ReadbackFromCompositorIfAvailable);
     virtual void themeChanged();
     virtual void composite(bool finish);
     virtual void setNeedsRedraw();