diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-13 22:30:46 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-13 22:30:46 +0000 |
commit | f98d7e3cdcf671e035f6e0b8e5738be01243c8de (patch) | |
tree | 272e9fdef304f8cdcd358b2dfbe41809f0f27150 /chrome/renderer/render_widget.cc | |
parent | c1ae2105f9b941535dbc534226e3b33310c3ea44 (diff) | |
download | chromium_src-f98d7e3cdcf671e035f6e0b8e5738be01243c8de.zip chromium_src-f98d7e3cdcf671e035f6e0b8e5738be01243c8de.tar.gz chromium_src-f98d7e3cdcf671e035f6e0b8e5738be01243c8de.tar.bz2 |
Accelerated Compositing: screen garbage when scrolling
Re-work the way the compositor handles invalidations, scrolling
and repaint requests. Previously, compositor piggy-backed on the
software rendering path for handling of these events. This CL,
paired with webkit bug 45092 allows the compositor to track and
manage invalidations, scrolling and repainting independently,
allowing us to fix a number of accelerated rendering bugs stemming
from interaction with the software renderer.
Patch by Nat Duca (nduca@chromium.org)
R=darin
BUG=52519
TEST=none
Originally reviewed at http://codereview.chromium.org/3350006
Review URL: http://codereview.chromium.org/3368016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59293 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/render_widget.cc')
-rw-r--r-- | chrome/renderer/render_widget.cc | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 480285a..01c7b26 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -255,8 +255,10 @@ void RenderWidget::OnResize(const gfx::Size& new_size, // an ACK if we are resized to a non-empty rect. webwidget_->resize(new_size); if (!new_size.IsEmpty()) { - // Resize should have caused an invalidation of the entire view. - DCHECK(paint_aggregator_.HasPendingUpdate()); + if (!webwidget_->isAcceleratedCompositingActive()) { + // Resize should have caused an invalidation of the entire view. + DCHECK(paint_aggregator_.HasPendingUpdate()); + } // We will send the Resize_ACK flag once we paint again. set_next_paint_is_resize_ack(); @@ -285,7 +287,11 @@ void RenderWidget::OnWasRestored(bool needs_repainting) { set_next_paint_is_restore_ack(); // Generate a full repaint. - didInvalidateRect(gfx::Rect(size_.width(), size_.height())); + if (needs_repainting && !webwidget_->isAcceleratedCompositingActive()) { + didInvalidateRect(gfx::Rect(size_.width(), size_.height())); + } else { + scheduleComposite(); + } } void RenderWidget::OnRequestMoveAck() { @@ -471,6 +477,11 @@ void RenderWidget::DoDeferredUpdate() { return; } + // Layout may generate more invalidation. It may also enable the + // GPU acceleration, so make sure to run layout before we send the + // GpuRenderingActivated message. + webwidget_->layout(); + // If we are using accelerated compositing then all the drawing // to the associated window happens directly from the gpu process and the // browser process shouldn't do any drawing. @@ -486,9 +497,6 @@ void RenderWidget::DoDeferredUpdate() { routing_id_, is_gpu_rendering_active_)); } - // Layout may generate more invalidation. - webwidget_->layout(); - // OK, save the pending update to a local since painting may cause more // invalidation. Some WebCore rendering objects only layout when painted. PaintAggregator::PendingUpdate update = paint_aggregator_.GetPendingUpdate(); @@ -497,41 +505,49 @@ void RenderWidget::DoDeferredUpdate() { gfx::Rect scroll_damage = update.GetScrollDamage(); gfx::Rect bounds = update.GetPaintBounds().Union(scroll_damage); - // Compute a buffer for painting and cache it. - scoped_ptr<skia::PlatformCanvas> canvas( - RenderProcess::current()->GetDrawingCanvas(¤t_paint_buf_, bounds)); - if (!canvas.get()) { - NOTREACHED(); - return; - } - - // We may get back a smaller canvas than we asked for. - // TODO(darin): This seems like it could cause painting problems! - DCHECK_EQ(bounds.width(), canvas->getDevice()->width()); - DCHECK_EQ(bounds.height(), canvas->getDevice()->height()); - bounds.set_width(canvas->getDevice()->width()); - bounds.set_height(canvas->getDevice()->height()); + std::vector<gfx::Rect> copy_rects; + if (!is_gpu_rendering_active_) { + // Compute a buffer for painting and cache it. + scoped_ptr<skia::PlatformCanvas> canvas + (RenderProcess::current()->GetDrawingCanvas(¤t_paint_buf_, bounds)); + if (!canvas.get()) { + NOTREACHED(); + return; + } - HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size()); + // We may get back a smaller canvas than we asked for. + // TODO(darin): This seems like it could cause painting problems! + DCHECK_EQ(bounds.width(), canvas->getDevice()->width()); + DCHECK_EQ(bounds.height(), canvas->getDevice()->height()); + bounds.set_width(canvas->getDevice()->width()); + bounds.set_height(canvas->getDevice()->height()); - // TODO(darin): Re-enable painting multiple damage rects once the - // page-cycler regressions are resolved. See bug 29589. - if (update.scroll_rect.IsEmpty()) { - update.paint_rects.clear(); - update.paint_rects.push_back(bounds); - } + HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size()); - // The scroll damage is just another rectangle to paint and copy. - std::vector<gfx::Rect> copy_rects; - copy_rects.swap(update.paint_rects); - if (!scroll_damage.IsEmpty()) - copy_rects.push_back(scroll_damage); + // TODO(darin): Re-enable painting multiple damage rects once the + // page-cycler regressions are resolved. See bug 29589. + if (update.scroll_rect.IsEmpty()) { + update.paint_rects.clear(); + update.paint_rects.push_back(bounds); + } - for (size_t i = 0; i < copy_rects.size(); ++i) - PaintRect(copy_rects[i], bounds.origin(), canvas.get()); + // The scroll damage is just another rectangle to paint and copy. + copy_rects.swap(update.paint_rects); + if (!scroll_damage.IsEmpty()) + copy_rects.push_back(scroll_damage); + + for (size_t i = 0; i < copy_rects.size(); ++i) + PaintRect(copy_rects[i], bounds.origin(), canvas.get()); + } else { // Accelerated compositing path + // Begin painting. + bool finish = next_paint_is_resize_ack(); + webwidget_->composite(finish); + } + // sending an ack to browser process that the paint is complete... ViewHostMsg_UpdateRect_Params params; - params.bitmap = current_paint_buf_->id(); + params.bitmap = + current_paint_buf_ ? current_paint_buf_->id() : TransportDIB::Id(); params.bitmap_rect = bounds; params.dx = update.scroll_delta.x(); params.dy = update.scroll_delta.y(); @@ -559,9 +575,19 @@ void RenderWidget::DoDeferredUpdate() { } /////////////////////////////////////////////////////////////////////////////// -// WebWidgetDelegate +// WebWidgetClient void RenderWidget::didInvalidateRect(const WebRect& rect) { + if (webwidget_->isAcceleratedCompositingActive()) { + // Drop invalidates on the floor when we are in compositing mode. + // TODO(nduca): Stop WebViewImpl from sending invalidates in the first + // place. + if (!(rect.x == 0 && rect.y == 0 && + rect.width == 1 && rect.height == 1)) { + return; + } + } + // We only want one pending DoDeferredUpdate call at any time... bool update_pending = paint_aggregator_.HasPendingUpdate(); @@ -591,6 +617,11 @@ void RenderWidget::didInvalidateRect(const WebRect& rect) { } void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) { + // Drop scrolls on the floor when we are in compositing mode. + // TODO(nduca): stop WebViewImpl from sending scrolls in the first place. + if (webwidget_->isAcceleratedCompositingActive()) + return; + // We only want one pending DoDeferredUpdate call at any time... bool update_pending = paint_aggregator_.HasPendingUpdate(); @@ -619,6 +650,16 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) { this, &RenderWidget::CallDoDeferredUpdate)); } +void RenderWidget::scheduleComposite() { + // TODO(nduca): replace with something a little less hacky. The reason this + // hack is still used is because the Invalidate-DoDeferredUpdate loop + // contains a lot of host-renderer synchronization logic that is still + // important for the accelerated compositing case. The option of simply + // duplicating all that code is less desirable than "faking out" the + // invalidation path using a magical damage rect. + didInvalidateRect(WebRect(0,0,1,1)); +} + void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) { // TODO(darin): Eliminate this temporary. WebCursor cursor(cursor_info); @@ -681,10 +722,6 @@ void RenderWidget::closeWidgetSoon() { this, &RenderWidget::DoDeferredClose)); } -void RenderWidget::GenerateFullRepaint() { - didInvalidateRect(gfx::Rect(size_.width(), size_.height())); -} - void RenderWidget::Close() { if (webwidget_) { webwidget_->close(); @@ -838,8 +875,12 @@ void RenderWidget::OnMsgRepaint(const gfx::Size& size_to_paint) { return; set_next_paint_is_repaint_ack(); - gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height()); - didInvalidateRect(repaint_rect); + if (webwidget_->isAcceleratedCompositingActive()) { + scheduleComposite(); + } else { + gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height()); + didInvalidateRect(repaint_rect); + } } void RenderWidget::OnSetTextDirection(WebTextDirection direction) { @@ -862,6 +903,7 @@ void RenderWidget::SetHidden(bool hidden) { void RenderWidget::SetBackground(const SkBitmap& background) { background_ = background; + // Generate a full repaint. didInvalidateRect(gfx::Rect(size_.width(), size_.height())); } |