WebWidget should be able to paint into a zoomed canvas without aliasing
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 20 Aug 2012 23:57:24 +0000 (23:57 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 20 Aug 2012 23:57:24 +0000 (23:57 +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@126095 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 c007ca4..72b879b 100644 (file)
@@ -1,3 +1,36 @@
+2012-08-20  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-20  James Robinson  <jamesr@chromium.org>
 
         Unreviewed. Roll WebKit chromium DEPS forward.
index 8e4feca..b03beeb 100644 (file)
@@ -90,6 +90,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 +112,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 97339b3..2919fb9 100644 (file)
@@ -1686,9 +1686,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.
@@ -1700,12 +1706,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 431dad4..8d49f2e 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();