diff options
author | ajuma <ajuma@chromium.org> | 2014-11-27 06:19:14 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-27 14:19:39 +0000 |
commit | 5e77f7d4da0dab1154d866112888e3c5d0e3dfa2 (patch) | |
tree | 838f039a09c94fb28eeeb09d99f34340e7c4d712 /cc | |
parent | 222b9c08723a0acd0327b8ff7a11f1254d241a99 (diff) | |
download | chromium_src-5e77f7d4da0dab1154d866112888e3c5d0e3dfa2.zip chromium_src-5e77f7d4da0dab1154d866112888e3c5d0e3dfa2.tar.gz chromium_src-5e77f7d4da0dab1154d866112888e3c5d0e3dfa2.tar.bz2 |
cc: Implement a display-list-based RecordingSource and RasterSource
This defines a RecordingSource that records into a display list. This also
defines a corresponding RasterSource.
Bug=None
Review URL: https://codereview.chromium.org/753263002
Cr-Commit-Position: refs/heads/master@{#305982}
Diffstat (limited to 'cc')
50 files changed, 1930 insertions, 58 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index af0aa30..c744c5b 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -330,10 +330,24 @@ component("cc") { "resources/bitmap_raster_worker_pool.h", "resources/bitmap_skpicture_content_layer_updater.cc", "resources/bitmap_skpicture_content_layer_updater.h", + "resources/clip_display_item.cc", + "resources/clip_display_item.h", "resources/content_layer_updater.cc", "resources/content_layer_updater.h", + "resources/display_item.cc", + "resources/display_item.h", + "resources/display_item_list.cc", + "resources/display_item_list.h", + "resources/display_list_raster_source.cc", + "resources/display_list_raster_source.h", + "resources/display_list_recording_source.cc", + "resources/display_list_recording_source.h", + "resources/drawing_display_item.cc", + "resources/drawing_display_item.h", "resources/eviction_tile_priority_queue.cc", "resources/eviction_tile_priority_queue.h", + "resources/filter_display_item.cc", + "resources/filter_display_item.h", "resources/gpu_raster_worker_pool.cc", "resources/gpu_raster_worker_pool.h", "resources/image_layer_updater.cc", @@ -373,6 +387,8 @@ component("cc") { "resources/raster_buffer.cc", "resources/raster_buffer.h", "resources/raster_source.h", + "resources/raster_source_helper.cc", + "resources/raster_source_helper.h", "resources/raster_tile_priority_queue.cc", "resources/raster_tile_priority_queue.h", "resources/raster_worker_pool.cc", @@ -428,6 +444,10 @@ component("cc") { "resources/tiling_set_eviction_queue.h", "resources/transferable_resource.cc", "resources/transferable_resource.h", + "resources/transform_display_item.cc", + "resources/transform_display_item.h", + "resources/transparency_display_item.cc", + "resources/transparency_display_item.h", "resources/ui_resource_bitmap.cc", "resources/ui_resource_bitmap.h", "resources/ui_resource_client.h", @@ -738,6 +758,7 @@ test("cc_unittests") { "quads/draw_quad_unittest.cc", "quads/list_container_unittest.cc", "quads/render_pass_unittest.cc", + "resources/display_item_list_unittest.cc", "resources/layer_quad_unittest.cc", "resources/picture_layer_tiling_set_unittest.cc", "resources/picture_layer_tiling_unittest.cc", diff --git a/cc/blink/BUILD.gn b/cc/blink/BUILD.gn index fac991b..138be59 100644 --- a/cc/blink/BUILD.gn +++ b/cc/blink/BUILD.gn @@ -33,6 +33,8 @@ component("blink") { "web_compositor_support_impl.h", "web_content_layer_impl.cc", "web_content_layer_impl.h", + "web_display_item_list_impl.cc", + "web_display_item_list_impl.h", "web_external_bitmap_impl.cc", "web_external_bitmap_impl.h", "web_external_texture_layer_impl.cc", diff --git a/cc/blink/cc_blink.gyp b/cc/blink/cc_blink.gyp index d9f19ea..892082c 100644 --- a/cc/blink/cc_blink.gyp +++ b/cc/blink/cc_blink.gyp @@ -36,6 +36,8 @@ 'web_compositor_support_impl.h', 'web_content_layer_impl.cc', 'web_content_layer_impl.h', + 'web_display_item_list_impl.cc', + 'web_display_item_list_impl.h', 'web_external_bitmap_impl.cc', 'web_external_bitmap_impl.h', 'web_external_texture_layer_impl.cc', diff --git a/cc/blink/web_compositor_support_impl.cc b/cc/blink/web_compositor_support_impl.cc index ae098fc..042908c 100644 --- a/cc/blink/web_compositor_support_impl.cc +++ b/cc/blink/web_compositor_support_impl.cc @@ -9,6 +9,7 @@ #include "cc/animation/transform_operations.h" #include "cc/blink/web_animation_impl.h" #include "cc/blink/web_content_layer_impl.h" +#include "cc/blink/web_display_item_list_impl.h" #include "cc/blink/web_external_texture_layer_impl.h" #include "cc/blink/web_filter_animation_curve_impl.h" #include "cc/blink/web_filter_operations_impl.h" @@ -27,6 +28,9 @@ using blink::WebCompositorAnimation; using blink::WebCompositorAnimationCurve; using blink::WebContentLayer; using blink::WebContentLayerClient; +#if WEB_DISPLAY_ITEM_LIST_IS_DEFINED +using blink::WebDisplayItemList; +#endif using blink::WebExternalTextureLayer; using blink::WebExternalTextureLayerClient; using blink::WebFilterAnimationCurve; @@ -91,6 +95,12 @@ WebScrollbarLayer* WebCompositorSupportImpl::createSolidColorScrollbarLayer( is_left_side_vertical_scrollbar); } +#if WEB_DISPLAY_ITEM_LIST_IS_DEFINED +WebDisplayItemList* WebCompositorSupportImpl::createDisplayItemList() { + return new WebDisplayItemListImpl(); +} +#endif + WebCompositorAnimation* WebCompositorSupportImpl::createAnimation( const blink::WebCompositorAnimationCurve& curve, blink::WebCompositorAnimation::TargetProperty target, diff --git a/cc/blink/web_compositor_support_impl.h b/cc/blink/web_compositor_support_impl.h index 0f6371a..1c5198c 100644 --- a/cc/blink/web_compositor_support_impl.h +++ b/cc/blink/web_compositor_support_impl.h @@ -10,6 +10,7 @@ #include "cc/blink/cc_blink_export.h" #include "third_party/WebKit/public/platform/WebCompositorAnimationCurve.h" #include "third_party/WebKit/public/platform/WebCompositorSupport.h" +#include "third_party/WebKit/public/platform/WebContentLayerClient.h" #include "third_party/WebKit/public/platform/WebLayer.h" #include "third_party/WebKit/public/platform/WebTransformOperations.h" @@ -41,6 +42,9 @@ class CC_BLINK_EXPORT WebCompositorSupportImpl int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar); +#if WEB_DISPLAY_ITEM_LIST_IS_DEFINED + virtual blink::WebDisplayItemList* createDisplayItemList(); +#endif virtual blink::WebCompositorAnimation* createAnimation( const blink::WebCompositorAnimationCurve& curve, blink::WebCompositorAnimation::TargetProperty target, diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc index d0a4cca..a6e2294 100644 --- a/cc/blink/web_content_layer_impl.cc +++ b/cc/blink/web_content_layer_impl.cc @@ -4,6 +4,7 @@ #include "cc/blink/web_content_layer_impl.h" +#include "cc/blink/web_display_item_list_impl.h" #include "cc/layers/content_layer.h" #include "cc/layers/picture_layer.h" #include "third_party/WebKit/public/platform/WebContentLayerClient.h" @@ -63,6 +64,24 @@ void WebContentLayerImpl::PaintContents( : blink::WebContentLayerClient::GraphicsContextDisabled); } +scoped_refptr<cc::DisplayItemList> +WebContentLayerImpl::PaintContentsToDisplayList( + const gfx::Rect& clip, + ContentLayerClient::GraphicsContextStatus graphics_context_status) { + if (!client_) + return cc::DisplayItemList::Create(); + + WebDisplayItemListImpl list; +#if WEB_DISPLAY_ITEM_LIST_IS_DEFINED + client_->paintContents( + &list, clip, can_use_lcd_text_, + graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED + ? blink::WebContentLayerClient::GraphicsContextEnabled + : blink::WebContentLayerClient::GraphicsContextDisabled); +#endif + return list.ToDisplayItemList(); +} + bool WebContentLayerImpl::FillsBoundsCompletely() const { return false; } diff --git a/cc/blink/web_content_layer_impl.h b/cc/blink/web_content_layer_impl.h index 8793840..148f4fc 100644 --- a/cc/blink/web_content_layer_impl.h +++ b/cc/blink/web_content_layer_impl.h @@ -40,6 +40,9 @@ class WebContentLayerImpl : public blink::WebContentLayer, const gfx::Rect& clip, ContentLayerClient::GraphicsContextStatus graphics_context_status) override; + scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus graphics_context_status) override; bool FillsBoundsCompletely() const override; scoped_ptr<WebLayerImpl> layer_; diff --git a/cc/blink/web_display_item_list_impl.cc b/cc/blink/web_display_item_list_impl.cc new file mode 100644 index 0000000..4ba3431 --- /dev/null +++ b/cc/blink/web_display_item_list_impl.cc @@ -0,0 +1,90 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/blink/web_display_item_list_impl.h" + +#include <vector> + +#include "cc/blink/web_blend_mode.h" +#include "cc/resources/clip_display_item.h" +#include "cc/resources/drawing_display_item.h" +#include "cc/resources/filter_display_item.h" +#include "cc/resources/transform_display_item.h" +#include "cc/resources/transparency_display_item.h" +#include "skia/ext/refptr.h" +#include "third_party/WebKit/public/platform/WebFloatRect.h" +#include "third_party/WebKit/public/platform/WebRect.h" +#include "third_party/skia/include/core/SkImageFilter.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/utils/SkMatrix44.h" +#include "ui/gfx/transform.h" + +namespace cc_blink { + +WebDisplayItemListImpl::WebDisplayItemListImpl() + : display_item_list_(cc::DisplayItemList::Create()) { +} + +scoped_refptr<cc::DisplayItemList> WebDisplayItemListImpl::ToDisplayItemList() { + return display_item_list_; +} + +void WebDisplayItemListImpl::appendDrawingItem( + SkPicture* picture, + const blink::WebFloatPoint& location) { + display_item_list_->AppendItem( + cc::DrawingDisplayItem::Create(skia::SharePtr(picture), location)); +} + +void WebDisplayItemListImpl::appendClipItem( + const blink::WebRect& clip_rect, + const blink::WebVector<SkRRect>& rounded_clip_rects) { + std::vector<SkRRect> rounded_rects; + for (size_t i = 0; i < rounded_clip_rects.size(); ++i) { + rounded_rects.push_back(rounded_clip_rects[i]); + } + display_item_list_->AppendItem( + cc::ClipDisplayItem::Create(clip_rect, rounded_rects)); +} + +void WebDisplayItemListImpl::appendEndClipItem() { + display_item_list_->AppendItem(cc::EndClipDisplayItem::Create()); +} + +void WebDisplayItemListImpl::appendTransformItem(const SkMatrix44& matrix) { + gfx::Transform transform; + transform.matrix() = matrix; + display_item_list_->AppendItem(cc::TransformDisplayItem::Create(transform)); +} + +void WebDisplayItemListImpl::appendTransparencyItem( + float opacity, + blink::WebBlendMode blend_mode) { + display_item_list_->AppendItem(cc::TransparencyDisplayItem::Create( + opacity, BlendModeToSkia(blend_mode))); +} + +void WebDisplayItemListImpl::appendEndTransformItem() { + display_item_list_->AppendItem(cc::EndTransformDisplayItem::Create()); +} + +void WebDisplayItemListImpl::appendEndTransparencyItem() { + display_item_list_->AppendItem(cc::EndTransparencyDisplayItem::Create()); +} + +void WebDisplayItemListImpl::appendFilterItem( + SkImageFilter* filter, + const blink::WebFloatRect& bounds) { + display_item_list_->AppendItem( + cc::FilterDisplayItem::Create(skia::SharePtr(filter), bounds)); +} + +void WebDisplayItemListImpl::appendEndFilterItem() { + display_item_list_->AppendItem(cc::EndFilterDisplayItem::Create()); +} + +WebDisplayItemListImpl::~WebDisplayItemListImpl() { +} + +} // namespace cc_blink diff --git a/cc/blink/web_display_item_list_impl.h b/cc/blink/web_display_item_list_impl.h new file mode 100644 index 0000000..4725498 --- /dev/null +++ b/cc/blink/web_display_item_list_impl.h @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_BLINK_WEB_DISPLAY_ITEM_LIST_IMPL_H_ +#define CC_BLINK_WEB_DISPLAY_ITEM_LIST_IMPL_H_ + +#include "base/memory/ref_counted.h" +#include "cc/blink/cc_blink_export.h" +#include "cc/resources/display_item_list.h" +#include "third_party/WebKit/public/platform/WebBlendMode.h" +#include "third_party/WebKit/public/platform/WebContentLayerClient.h" +#include "third_party/WebKit/public/platform/WebFloatPoint.h" +#include "third_party/WebKit/public/platform/WebVector.h" + +#if WEB_DISPLAY_ITEM_LIST_IS_DEFINED +#include "third_party/WebKit/public/platform/WebDisplayItemList.h" +#endif + +class SkImageFilter; +class SkMatrix44; +class SkPicture; +class SkRRect; + +namespace cc_blink { + +#if WEB_DISPLAY_ITEM_LIST_IS_DEFINED +class WebDisplayItemListImpl : public blink::WebDisplayItemList { +#else +class WebDisplayItemListImpl { +#endif + + public: + CC_BLINK_EXPORT WebDisplayItemListImpl(); + virtual ~WebDisplayItemListImpl(); + + scoped_refptr<cc::DisplayItemList> ToDisplayItemList(); + + // blink::WebDisplayItemList implementation. + virtual void appendDrawingItem(SkPicture* picture, + const blink::WebFloatPoint& location); + virtual void appendClipItem( + const blink::WebRect& clip_rect, + const blink::WebVector<SkRRect>& rounded_clip_rects); + virtual void appendEndClipItem(); + virtual void appendTransformItem(const SkMatrix44& matrix); + virtual void appendEndTransformItem(); + virtual void appendTransparencyItem(float opacity, + blink::WebBlendMode blend_mode); + virtual void appendEndTransparencyItem(); + virtual void appendFilterItem(SkImageFilter* filter, + const blink::WebFloatRect& bounds); + virtual void appendEndFilterItem(); + + private: + scoped_refptr<cc::DisplayItemList> display_item_list_; + + DISALLOW_COPY_AND_ASSIGN(WebDisplayItemListImpl); +}; + +} // namespace cc_blink + +#endif // CC_BLINK_WEB_DISPLAY_ITEM_LIST_IMPL_H_ @@ -358,10 +358,24 @@ 'resources/bitmap_raster_worker_pool.h', 'resources/bitmap_skpicture_content_layer_updater.cc', 'resources/bitmap_skpicture_content_layer_updater.h', + 'resources/clip_display_item.cc', + 'resources/clip_display_item.h', 'resources/content_layer_updater.cc', 'resources/content_layer_updater.h', + 'resources/display_item.cc', + 'resources/display_item.h', + 'resources/display_item_list.cc', + 'resources/display_item_list.h', + 'resources/display_list_raster_source.cc', + 'resources/display_list_raster_source.h', + 'resources/display_list_recording_source.cc', + 'resources/display_list_recording_source.h', + 'resources/drawing_display_item.cc', + 'resources/drawing_display_item.h', 'resources/eviction_tile_priority_queue.cc', 'resources/eviction_tile_priority_queue.h', + 'resources/filter_display_item.cc', + 'resources/filter_display_item.h', 'resources/gpu_raster_worker_pool.cc', 'resources/gpu_raster_worker_pool.h', 'resources/image_layer_updater.cc', @@ -401,6 +415,8 @@ 'resources/raster_buffer.cc', 'resources/raster_buffer.h', 'resources/raster_source.h', + 'resources/raster_source_helper.cc', + 'resources/raster_source_helper.h', 'resources/raster_tile_priority_queue.cc', 'resources/raster_tile_priority_queue.h', 'resources/raster_worker_pool.cc', @@ -457,6 +473,10 @@ 'resources/tiling_set_eviction_queue.h', 'resources/transferable_resource.cc', 'resources/transferable_resource.h', + 'resources/transform_display_item.cc', + 'resources/transform_display_item.h', + 'resources/transparency_display_item.cc', + 'resources/transparency_display_item.h', 'resources/ui_resource_bitmap.cc', 'resources/ui_resource_bitmap.h', 'resources/ui_resource_client.h', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index d4a031f..d0b1000 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -74,6 +74,7 @@ 'quads/draw_quad_unittest.cc', 'quads/list_container_unittest.cc', 'quads/render_pass_unittest.cc', + 'resources/display_item_list_unittest.cc', 'resources/layer_quad_unittest.cc', 'resources/picture_layer_tiling_set_unittest.cc', 'resources/picture_layer_tiling_unittest.cc', diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h index ea22e97..c8d3a7e 100644 --- a/cc/layers/content_layer_client.h +++ b/cc/layers/content_layer_client.h @@ -6,6 +6,7 @@ #define CC_LAYERS_CONTENT_LAYER_CLIENT_H_ #include "cc/base/cc_export.h" +#include "cc/resources/display_item_list.h" class SkCanvas; @@ -27,6 +28,10 @@ class CC_EXPORT ContentLayerClient { const gfx::Rect& clip, GraphicsContextStatus gc_status) = 0; + virtual scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) = 0; + // If true the layer may skip clearing the background before rasterizing, // because it will cover any uncleared data with content. virtual bool FillsBoundsCompletely() const = 0; diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc index dba506e..5d76618 100644 --- a/cc/layers/picture_image_layer.cc +++ b/cc/layers/picture_image_layer.cc @@ -60,6 +60,13 @@ void PictureImageLayer::PaintContents( canvas->drawBitmap(bitmap_, 0, 0); } +scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); +} + bool PictureImageLayer::FillsBoundsCompletely() const { return false; } diff --git a/cc/layers/picture_image_layer.h b/cc/layers/picture_image_layer.h index 3f8d68d..57c7de2 100644 --- a/cc/layers/picture_image_layer.h +++ b/cc/layers/picture_image_layer.h @@ -27,6 +27,9 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient { SkCanvas* canvas, const gfx::Rect& clip, ContentLayerClient::GraphicsContextStatus gc_status) override; + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override; bool FillsBoundsCompletely() const override; protected: diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index d734538..55241d0 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc @@ -7,6 +7,7 @@ #include "base/auto_reset.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer_impl.h" +#include "cc/resources/display_list_recording_source.h" #include "cc/resources/picture_pile.h" #include "cc/trees/layer_tree_impl.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -20,7 +21,6 @@ scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) { PictureLayer::PictureLayer(ContentLayerClient* client) : client_(client), - recording_source_(new PicturePile), instrumentation_object_tracker_(id()), update_source_frame_number_(-1), can_use_lcd_text_for_update_(true), @@ -79,6 +79,13 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { Layer::SetLayerTreeHost(host); if (host) { + if (!recording_source_) { + if (host->settings().use_display_lists) { + recording_source_.reset(new DisplayListRecordingSource); + } else { + recording_source_.reset(new PicturePile); + } + } recording_source_->SetMinContentsScale( host->settings().minimum_contents_scale); recording_source_->SetTileGridSize(host->settings().default_tile_grid_size); diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc index 3f81ef8..ac20e4c 100644 --- a/cc/layers/picture_layer_unittest.cc +++ b/cc/layers/picture_layer_unittest.cc @@ -24,6 +24,12 @@ class MockContentLayerClient : public ContentLayerClient { SkCanvas* canvas, const gfx::Rect& clip, ContentLayerClient::GraphicsContextStatus gc_status) override {} + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } bool FillsBoundsCompletely() const override { return false; }; }; @@ -73,6 +79,9 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) { TEST(PictureLayerTest, SuitableForGpuRasterization) { MockContentLayerClient client; scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client); + FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); + scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client); + host->SetRootLayer(layer); RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); // Layer is suitable for gpu rasterization by default. diff --git a/cc/resources/clip_display_item.cc b/cc/resources/clip_display_item.cc new file mode 100644 index 0000000..9277eea --- /dev/null +++ b/cc/resources/clip_display_item.cc @@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/clip_display_item.h" + +#include "third_party/skia/include/core/SkCanvas.h" + +namespace cc { + +ClipDisplayItem::ClipDisplayItem(gfx::Rect clip_rect, + const std::vector<SkRRect>& rounded_clip_rects) + : clip_rect_(clip_rect), rounded_clip_rects_(rounded_clip_rects) { +} + +ClipDisplayItem::~ClipDisplayItem() { +} + +void ClipDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->save(); + canvas->clipRect(SkRect::MakeXYWH(clip_rect_.x(), clip_rect_.y(), + clip_rect_.width(), clip_rect_.height())); + for (size_t i = 0; i < rounded_clip_rects_.size(); ++i) { + if (rounded_clip_rects_[i].isRect()) { + canvas->clipRect(rounded_clip_rects_[i].rect()); + } else { + bool antialiased = true; + canvas->clipRRect(rounded_clip_rects_[i], SkRegion::kIntersect_Op, + antialiased); + } + } +} + +bool ClipDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int ClipDisplayItem::ApproximateOpCount() const { + return 1; +} + +EndClipDisplayItem::EndClipDisplayItem() { +} + +EndClipDisplayItem::~EndClipDisplayItem() { +} + +void EndClipDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->restore(); +} + +bool EndClipDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int EndClipDisplayItem::ApproximateOpCount() const { + return 0; +} + +} // namespace cc diff --git a/cc/resources/clip_display_item.h b/cc/resources/clip_display_item.h new file mode 100644 index 0000000..82deefd --- /dev/null +++ b/cc/resources/clip_display_item.h @@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_CLIP_DISPLAY_ITEM_H_ +#define CC_RESOURCES_CLIP_DISPLAY_ITEM_H_ + +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/resources/display_item.h" +#include "third_party/skia/include/core/SkRRect.h" +#include "ui/gfx/geometry/rect.h" + +class SkCanvas; +class SkDrawPictureCallback; + +namespace cc { + +class CC_EXPORT ClipDisplayItem : public DisplayItem { + public: + virtual ~ClipDisplayItem(); + + static scoped_ptr<ClipDisplayItem> Create( + gfx::Rect clip_rect, + const std::vector<SkRRect>& rounded_clip_rects) { + return make_scoped_ptr(new ClipDisplayItem(clip_rect, rounded_clip_rects)); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + ClipDisplayItem(gfx::Rect clip_rect, + const std::vector<SkRRect>& rounded_clip_rects); + + private: + gfx::Rect clip_rect_; + std::vector<SkRRect> rounded_clip_rects_; +}; + +class CC_EXPORT EndClipDisplayItem : public DisplayItem { + public: + virtual ~EndClipDisplayItem(); + + static scoped_ptr<EndClipDisplayItem> Create() { + return make_scoped_ptr(new EndClipDisplayItem()); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + EndClipDisplayItem(); +}; + +} // namespace cc + +#endif // CC_RESOURCES_CLIP_DISPLAY_ITEM_H_ diff --git a/cc/resources/display_item.cc b/cc/resources/display_item.cc new file mode 100644 index 0000000..33069a53 --- /dev/null +++ b/cc/resources/display_item.cc @@ -0,0 +1,12 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/display_item.h" + +namespace cc { + +DisplayItem::DisplayItem() { +} + +} // namespace cc diff --git a/cc/resources/display_item.h b/cc/resources/display_item.h new file mode 100644 index 0000000..e080267 --- /dev/null +++ b/cc/resources/display_item.h @@ -0,0 +1,33 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_DISPLAY_ITEM_H_ +#define CC_RESOURCES_DISPLAY_ITEM_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "ui/gfx/rect.h" + +class SkCanvas; +class SkDrawPictureCallback; + +namespace cc { + +class CC_EXPORT DisplayItem { + public: + virtual ~DisplayItem() {} + + virtual void Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const = 0; + + virtual bool IsSuitableForGpuRasterization() const = 0; + virtual int ApproximateOpCount() const = 0; + + protected: + DisplayItem(); +}; + +} // namespace cc + +#endif // CC_RESOURCES_DISPLAY_ITEM_H_ diff --git a/cc/resources/display_item_list.cc b/cc/resources/display_item_list.cc new file mode 100644 index 0000000..bd93e49 --- /dev/null +++ b/cc/resources/display_item_list.cc @@ -0,0 +1,69 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/display_item_list.h" + +#include "base/debug/trace_event.h" +#include "base/debug/trace_event_argument.h" +#include "third_party/skia/include/core/SkCanvas.h" + +namespace cc { + +DisplayItemList::DisplayItemList() + : is_suitable_for_gpu_rasterization_(true), approximate_op_count_(0) { +} + +scoped_refptr<DisplayItemList> DisplayItemList::Create() { + return make_scoped_refptr(new DisplayItemList()); +} + +DisplayItemList::~DisplayItemList() { +} + +void DisplayItemList::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback, + float contents_scale) const { + canvas->save(); + canvas->scale(contents_scale, contents_scale); + for (size_t i = 0; i < items_.size(); ++i) { + items_[i]->Raster(canvas, callback); + } + canvas->restore(); +} + +void DisplayItemList::AppendItem(scoped_ptr<DisplayItem> item) { + is_suitable_for_gpu_rasterization_ &= item->IsSuitableForGpuRasterization(); + approximate_op_count_ += item->ApproximateOpCount(); + items_.push_back(item.Pass()); +} + +bool DisplayItemList::IsSuitableForGpuRasterization() const { + // This is more permissive than Picture's implementation, since none of the + // items might individually trigger a veto even though they collectively have + // enough "bad" operations that a corresponding Picture would get vetoed. + return is_suitable_for_gpu_rasterization_; +} + +int DisplayItemList::ApproximateOpCount() const { + return approximate_op_count_; +} + +scoped_refptr<base::debug::ConvertableToTraceFormat> DisplayItemList::AsValue() + const { + scoped_refptr<base::debug::TracedValue> state = + new base::debug::TracedValue(); + + // TODO(ajuma): Include the value of each item. + state->SetInteger("length", items_.size()); + return state; +} + +void DisplayItemList::EmitTraceSnapshot() const { + TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( + TRACE_DISABLED_BY_DEFAULT("cc.debug") "," TRACE_DISABLED_BY_DEFAULT( + "devtools.timeline.picture"), + "cc::DisplayItemList", this, AsValue()); +} + +} // namespace cc diff --git a/cc/resources/display_item_list.h b/cc/resources/display_item_list.h new file mode 100644 index 0000000..fe25880 --- /dev/null +++ b/cc/resources/display_item_list.h @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_DISPLAY_ITEM_LIST_H_ +#define CC_RESOURCES_DISPLAY_ITEM_LIST_H_ + +#include "base/debug/trace_event.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/base/scoped_ptr_vector.h" +#include "cc/resources/display_item.h" +#include "ui/gfx/rect.h" + +class SkCanvas; +class SkDrawPictureCallback; + +namespace cc { + +class CC_EXPORT DisplayItemList + : public base::RefCountedThreadSafe<DisplayItemList> { + public: + static scoped_refptr<DisplayItemList> Create(); + + void Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback, + float contents_scale) const; + + void AppendItem(scoped_ptr<DisplayItem> item); + + bool IsSuitableForGpuRasterization() const; + int ApproximateOpCount() const; + + scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const; + + void EmitTraceSnapshot() const; + + private: + DisplayItemList(); + ~DisplayItemList(); + ScopedPtrVector<DisplayItem> items_; + bool is_suitable_for_gpu_rasterization_; + int approximate_op_count_; + + friend class base::RefCountedThreadSafe<DisplayItemList>; + DISALLOW_COPY_AND_ASSIGN(DisplayItemList); +}; + +} // namespace cc + +#endif // CC_RESOURCES_DISPLAY_ITEM_LIST_H_ diff --git a/cc/resources/display_item_list_unittest.cc b/cc/resources/display_item_list_unittest.cc new file mode 100644 index 0000000..d6455a2 --- /dev/null +++ b/cc/resources/display_item_list_unittest.cc @@ -0,0 +1,166 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/display_item_list.h" + +#include <vector> + +#include "cc/resources/clip_display_item.h" +#include "cc/resources/drawing_display_item.h" +#include "cc/resources/transform_display_item.h" +#include "cc/test/skia_common.h" +#include "skia/ext/refptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" +#include "ui/gfx/skia_util.h" + +namespace cc { +namespace { + +TEST(DisplayItemListTest, SingleDrawingItem) { + gfx::Rect layer_rect(100, 100); + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + skia::RefPtr<SkPicture> picture; + SkPaint blue_paint; + blue_paint.setColor(SK_ColorBLUE); + SkPaint red_paint; + red_paint.setColor(SK_ColorRED); + unsigned char pixels[4 * 100 * 100] = {0}; + scoped_refptr<DisplayItemList> list = DisplayItemList::Create(); + + canvas = skia::SharePtr( + recorder.beginRecording(layer_rect.width(), layer_rect.height())); + canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint); + canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint); + picture = skia::AdoptRef(recorder.endRecording()); + gfx::PointF offset(8.f, 9.f); + list->AppendItem(DrawingDisplayItem::Create(picture, offset)); + DrawDisplayList(pixels, layer_rect, list); + + SkBitmap expected_bitmap; + unsigned char expected_pixels[4 * 100 * 100] = {0}; + SkImageInfo info = + SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); + expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); + SkCanvas expected_canvas(expected_bitmap); + expected_canvas.clipRect(gfx::RectToSkRect(layer_rect)); + expected_canvas.drawRectCoords(0.f + offset.x(), 0.f + offset.y(), + 60.f + offset.x(), 60.f + offset.y(), + red_paint); + expected_canvas.drawRectCoords(50.f + offset.x(), 50.f + offset.y(), + 75.f + offset.x(), 75.f + offset.y(), + blue_paint); + + EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); +} + +TEST(DisplayItemListTest, ClipItem) { + gfx::Rect layer_rect(100, 100); + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + skia::RefPtr<SkPicture> picture; + SkPaint blue_paint; + blue_paint.setColor(SK_ColorBLUE); + SkPaint red_paint; + red_paint.setColor(SK_ColorRED); + unsigned char pixels[4 * 100 * 100] = {0}; + scoped_refptr<DisplayItemList> list = DisplayItemList::Create(); + + canvas = skia::SharePtr( + recorder.beginRecording(layer_rect.width(), layer_rect.height())); + canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint); + picture = skia::AdoptRef(recorder.endRecording()); + gfx::PointF first_offset(8.f, 9.f); + list->AppendItem(DrawingDisplayItem::Create(picture, first_offset)); + + gfx::Rect clip_rect(60, 60, 10, 10); + list->AppendItem(ClipDisplayItem::Create(clip_rect, std::vector<SkRRect>())); + + canvas = skia::SharePtr( + recorder.beginRecording(layer_rect.width(), layer_rect.height())); + canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint); + picture = skia::AdoptRef(recorder.endRecording()); + gfx::PointF second_offset(2.f, 3.f); + list->AppendItem(DrawingDisplayItem::Create(picture, second_offset)); + + list->AppendItem(EndClipDisplayItem::Create()); + + DrawDisplayList(pixels, layer_rect, list); + + SkBitmap expected_bitmap; + unsigned char expected_pixels[4 * 100 * 100] = {0}; + SkImageInfo info = + SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); + expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); + SkCanvas expected_canvas(expected_bitmap); + expected_canvas.clipRect(gfx::RectToSkRect(layer_rect)); + expected_canvas.drawRectCoords(0.f + first_offset.x(), 0.f + first_offset.y(), + 60.f + first_offset.x(), + 60.f + first_offset.y(), red_paint); + expected_canvas.clipRect(gfx::RectToSkRect(clip_rect)); + expected_canvas.drawRectCoords( + 50.f + second_offset.x(), 50.f + second_offset.y(), + 75.f + second_offset.x(), 75.f + second_offset.y(), blue_paint); + + EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); +} + +TEST(DisplayItemListTest, TransformItem) { + gfx::Rect layer_rect(100, 100); + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + skia::RefPtr<SkPicture> picture; + SkPaint blue_paint; + blue_paint.setColor(SK_ColorBLUE); + SkPaint red_paint; + red_paint.setColor(SK_ColorRED); + unsigned char pixels[4 * 100 * 100] = {0}; + scoped_refptr<DisplayItemList> list = DisplayItemList::Create(); + + canvas = skia::SharePtr( + recorder.beginRecording(layer_rect.width(), layer_rect.height())); + canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint); + picture = skia::AdoptRef(recorder.endRecording()); + gfx::PointF first_offset(8.f, 9.f); + list->AppendItem(DrawingDisplayItem::Create(picture, first_offset)); + + gfx::Transform transform; + transform.Rotate(45.0); + list->AppendItem(TransformDisplayItem::Create(transform)); + + canvas = skia::SharePtr( + recorder.beginRecording(layer_rect.width(), layer_rect.height())); + canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint); + picture = skia::AdoptRef(recorder.endRecording()); + gfx::PointF second_offset(2.f, 3.f); + list->AppendItem(DrawingDisplayItem::Create(picture, second_offset)); + + list->AppendItem(EndTransformDisplayItem::Create()); + + DrawDisplayList(pixels, layer_rect, list); + + SkBitmap expected_bitmap; + unsigned char expected_pixels[4 * 100 * 100] = {0}; + SkImageInfo info = + SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); + expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); + SkCanvas expected_canvas(expected_bitmap); + expected_canvas.clipRect(gfx::RectToSkRect(layer_rect)); + expected_canvas.drawRectCoords(0.f + first_offset.x(), 0.f + first_offset.y(), + 60.f + first_offset.x(), + 60.f + first_offset.y(), red_paint); + expected_canvas.setMatrix(transform.matrix()); + expected_canvas.drawRectCoords( + 50.f + second_offset.x(), 50.f + second_offset.y(), + 75.f + second_offset.x(), 75.f + second_offset.y(), blue_paint); + + EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); +} + +} // namespace +} // namespace cc diff --git a/cc/resources/display_list_raster_source.cc b/cc/resources/display_list_raster_source.cc new file mode 100644 index 0000000..9f47e0e --- /dev/null +++ b/cc/resources/display_list_raster_source.cc @@ -0,0 +1,204 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/display_list_raster_source.h" + +#include "base/debug/trace_event.h" +#include "cc/base/region.h" +#include "cc/debug/debug_colors.h" +#include "cc/resources/display_item_list.h" +#include "cc/resources/raster_source_helper.h" +#include "skia/ext/analysis_canvas.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" +#include "ui/gfx/geometry/rect_conversions.h" + +namespace { + +#ifdef NDEBUG +const bool kDefaultClearCanvasSetting = false; +#else +const bool kDefaultClearCanvasSetting = true; +#endif + +} // namespace + +namespace cc { + +scoped_refptr<DisplayListRasterSource> DisplayListRasterSource::Create() { + return make_scoped_refptr(new DisplayListRasterSource); +} + +scoped_refptr<DisplayListRasterSource> +DisplayListRasterSource::CreateFromDisplayListRecordingSource( + const DisplayListRecordingSource* other) { + return make_scoped_refptr(new DisplayListRasterSource(other)); +} + +DisplayListRasterSource::DisplayListRasterSource() + : background_color_(SK_ColorTRANSPARENT), + requires_clear_(true), + can_use_lcd_text_(true), + is_solid_color_(false), + solid_color_(SK_ColorTRANSPARENT), + clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), + slow_down_raster_scale_factor_for_debug_(0), + should_attempt_to_use_distance_field_text_(false) { +} + +DisplayListRasterSource::DisplayListRasterSource( + const DisplayListRecordingSource* other) + : display_list_(other->display_list_), + background_color_(SK_ColorTRANSPARENT), + requires_clear_(true), + can_use_lcd_text_(other->can_use_lcd_text_), + is_solid_color_(other->is_solid_color_), + solid_color_(other->solid_color_), + recorded_viewport_(other->recorded_viewport_), + size_(other->size_), + clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), + slow_down_raster_scale_factor_for_debug_( + other->slow_down_raster_scale_factor_for_debug_), + should_attempt_to_use_distance_field_text_(false) { +} + +DisplayListRasterSource::~DisplayListRasterSource() { +} + +void DisplayListRasterSource::PlaybackToSharedCanvas( + SkCanvas* canvas, + const gfx::Rect& canvas_rect, + float contents_scale) const { + RasterCommon(canvas, NULL, canvas_rect, contents_scale, false); +} + +void DisplayListRasterSource::RasterForAnalysis(skia::AnalysisCanvas* canvas, + const gfx::Rect& canvas_rect, + float contents_scale) const { + RasterCommon(canvas, canvas, canvas_rect, contents_scale, true); +} + +void DisplayListRasterSource::PlaybackToCanvas(SkCanvas* canvas, + const gfx::Rect& canvas_rect, + float contents_scale) const { + RasterSourceHelper::PrepareForPlaybackToCanvas( + canvas, canvas_rect, gfx::Rect(size_), contents_scale, background_color_, + clear_canvas_with_debug_color_, requires_clear_); + + RasterCommon(canvas, NULL, canvas_rect, contents_scale, false); +} + +void DisplayListRasterSource::RasterCommon(SkCanvas* canvas, + SkDrawPictureCallback* callback, + const gfx::Rect& canvas_rect, + float contents_scale, + bool is_analysis) const { + canvas->translate(-canvas_rect.x(), -canvas_rect.y()); + gfx::Rect content_rect = + gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(size_), contents_scale)); + content_rect.Intersect(canvas_rect); + + canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op); + + DCHECK(display_list_.get()); + display_list_->Raster(canvas, callback, contents_scale); +} + +skia::RefPtr<SkPicture> DisplayListRasterSource::GetFlattenedPicture() { + TRACE_EVENT0("cc", "DisplayListRasterSource::GetFlattenedPicture"); + + gfx::Rect display_list_rect(size_); + SkPictureRecorder recorder; + SkCanvas* canvas = recorder.beginRecording(display_list_rect.width(), + display_list_rect.height()); + if (!display_list_rect.IsEmpty()) + PlaybackToCanvas(canvas, display_list_rect, 1.0); + skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + + return picture; +} + +void DisplayListRasterSource::PerformSolidColorAnalysis( + const gfx::Rect& content_rect, + float contents_scale, + RasterSource::SolidColorAnalysis* analysis) const { + DCHECK(analysis); + TRACE_EVENT0("cc", "DisplayListRasterSource::PerformSolidColorAnalysis"); + + gfx::Rect layer_rect = + gfx::ScaleToEnclosingRect(content_rect, 1.0f / contents_scale); + + layer_rect.Intersect(gfx::Rect(size_)); + skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height()); + RasterForAnalysis(&canvas, layer_rect, 1.0f); + analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color); +} + +void DisplayListRasterSource::GatherPixelRefs( + const gfx::Rect& content_rect, + float contents_scale, + std::vector<SkPixelRef*>* pixel_refs) const { + // TODO(ajuma): Implement this. +} + +bool DisplayListRasterSource::CoversRect(const gfx::Rect& content_rect, + float contents_scale) const { + if (size_.IsEmpty()) + return false; + gfx::Rect layer_rect = + gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale); + layer_rect.Intersect(gfx::Rect(size_)); + + return recorded_viewport_.Contains(layer_rect); +} + +gfx::Size DisplayListRasterSource::GetSize() const { + return size_; +} + +bool DisplayListRasterSource::IsSolidColor() const { + return is_solid_color_; +} + +SkColor DisplayListRasterSource::GetSolidColor() const { + DCHECK(IsSolidColor()); + return solid_color_; +} + +bool DisplayListRasterSource::HasRecordings() const { + return !!display_list_.get(); +} + +void DisplayListRasterSource::SetShouldAttemptToUseDistanceFieldText() { + should_attempt_to_use_distance_field_text_ = true; +} + +void DisplayListRasterSource::SetBackgoundColor(SkColor background_color) { + background_color_ = background_color; +} + +void DisplayListRasterSource::SetRequiresClear(bool requires_clear) { + requires_clear_ = requires_clear; +} + +bool DisplayListRasterSource::ShouldAttemptToUseDistanceFieldText() const { + return should_attempt_to_use_distance_field_text_; +} + +void DisplayListRasterSource::AsValueInto( + base::debug::TracedValue* array) const { + if (display_list_.get()) + TracedValue::AppendIDRef(display_list_.get(), array); +} + +void DisplayListRasterSource::DidBeginTracing() { + if (display_list_.get()) + display_list_->EmitTraceSnapshot(); +} + +bool DisplayListRasterSource::CanUseLCDText() const { + return can_use_lcd_text_; +} + +} // namespace cc diff --git a/cc/resources/display_list_raster_source.h b/cc/resources/display_list_raster_source.h new file mode 100644 index 0000000..80f8868 --- /dev/null +++ b/cc/resources/display_list_raster_source.h @@ -0,0 +1,93 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_DISPLAY_LIST_RASTER_SOURCE_H_ +#define CC_RESOURCES_DISPLAY_LIST_RASTER_SOURCE_H_ + +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/debug/rendering_stats_instrumentation.h" +#include "cc/resources/display_list_recording_source.h" +#include "cc/resources/raster_source.h" +#include "skia/ext/analysis_canvas.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkPicture.h" + +namespace cc { +class DisplayItemList; + +class CC_EXPORT DisplayListRasterSource : public RasterSource { + public: + static scoped_refptr<DisplayListRasterSource> Create(); + static scoped_refptr<DisplayListRasterSource> + CreateFromDisplayListRecordingSource(const DisplayListRecordingSource* other); + + // RasterSource overrides. + void PlaybackToCanvas(SkCanvas* canvas, + const gfx::Rect& canvas_rect, + float contents_scale) const override; + void PlaybackToSharedCanvas(SkCanvas* canvas, + const gfx::Rect& canvas_rect, + float contents_scale) const override; + void PerformSolidColorAnalysis( + const gfx::Rect& content_rect, + float contents_scale, + RasterSource::SolidColorAnalysis* analysis) const override; + bool IsSolidColor() const override; + SkColor GetSolidColor() const override; + gfx::Size GetSize() const override; + void GatherPixelRefs(const gfx::Rect& content_rect, + float contents_scale, + std::vector<SkPixelRef*>* pixel_refs) const override; + bool CoversRect(const gfx::Rect& content_rect, + float contents_scale) const override; + bool HasRecordings() const override; + void SetShouldAttemptToUseDistanceFieldText() override; + void SetBackgoundColor(SkColor background_color) override; + void SetRequiresClear(bool requires_clear) override; + bool ShouldAttemptToUseDistanceFieldText() const override; + void DidBeginTracing() override; + void AsValueInto(base::debug::TracedValue* array) const override; + skia::RefPtr<SkPicture> GetFlattenedPicture() override; + bool CanUseLCDText() const override; + + protected: + DisplayListRasterSource(); + explicit DisplayListRasterSource(const DisplayListRecordingSource* other); + ~DisplayListRasterSource() override; + + scoped_refptr<DisplayItemList> display_list_; + SkColor background_color_; + bool requires_clear_; + bool can_use_lcd_text_; + bool is_solid_color_; + SkColor solid_color_; + gfx::Rect recorded_viewport_; + gfx::Size size_; + bool clear_canvas_with_debug_color_; + int slow_down_raster_scale_factor_for_debug_; + + private: + // Called when analyzing a tile. We can use AnalysisCanvas as + // SkDrawPictureCallback, which allows us to early out from analysis. + void RasterForAnalysis(skia::AnalysisCanvas* canvas, + const gfx::Rect& canvas_rect, + float contents_scale) const; + + void RasterCommon(SkCanvas* canvas, + SkDrawPictureCallback* callback, + const gfx::Rect& canvas_rect, + float contents_scale, + bool is_analysis) const; + + bool should_attempt_to_use_distance_field_text_; + + DISALLOW_COPY_AND_ASSIGN(DisplayListRasterSource); +}; + +} // namespace cc + +#endif // CC_RESOURCES_DISPLAY_LIST_RASTER_SOURCE_H_ diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc new file mode 100644 index 0000000..3c0e0e4 --- /dev/null +++ b/cc/resources/display_list_recording_source.cc @@ -0,0 +1,158 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/display_list_recording_source.h" + +#include <algorithm> + +#include "cc/base/region.h" +#include "cc/layers/content_layer_client.h" +#include "cc/resources/display_item_list.h" +#include "cc/resources/display_list_raster_source.h" +#include "skia/ext/analysis_canvas.h" + +namespace { + +// Layout pixel buffer around the visible layer rect to record. Any base +// picture that intersects the visible layer rect expanded by this distance +// will be recorded. +const int kPixelDistanceToRecord = 8000; +// We don't perform solid color analysis on images that have more than 10 skia +// operations. +const int kOpCountThatIsOkToAnalyze = 10; + +} // namespace + +namespace cc { + +DisplayListRecordingSource::DisplayListRecordingSource() + : slow_down_raster_scale_factor_for_debug_(0), + can_use_lcd_text_(true), + is_solid_color_(false), + solid_color_(SK_ColorTRANSPARENT), + pixel_record_distance_(kPixelDistanceToRecord), + is_suitable_for_gpu_rasterization_(true) { +} + +DisplayListRecordingSource::~DisplayListRecordingSource() { +} + +bool DisplayListRecordingSource::UpdateAndExpandInvalidation( + ContentLayerClient* painter, + Region* invalidation, + bool can_use_lcd_text, + const gfx::Size& layer_size, + const gfx::Rect& visible_layer_rect, + int frame_number, + Picture::RecordingMode recording_mode) { + bool updated = false; + + if (size_ != layer_size) { + size_ = layer_size; + updated = true; + } + + if (can_use_lcd_text_ != can_use_lcd_text) { + can_use_lcd_text_ = can_use_lcd_text; + invalidation->Union(gfx::Rect(GetSize())); + updated = true; + } + + gfx::Rect old_recorded_viewport = recorded_viewport_; + recorded_viewport_ = visible_layer_rect; + recorded_viewport_.Inset(-pixel_record_distance_, -pixel_record_distance_); + recorded_viewport_.Intersect(gfx::Rect(GetSize())); + + if (recorded_viewport_ != old_recorded_viewport) { + // Invalidate newly-exposed and no-longer-exposed areas. + Region newly_exposed_region(recorded_viewport_); + newly_exposed_region.Subtract(old_recorded_viewport); + invalidation->Union(newly_exposed_region); + + Region no_longer_exposed_region(old_recorded_viewport); + no_longer_exposed_region.Subtract(recorded_viewport_); + invalidation->Union(no_longer_exposed_region); + + updated = true; + } + + if (!updated && !invalidation->Intersects(recorded_viewport_)) + return false; + + // TODO(ajuma): Does repeating this way really makes sense with display lists? + // With Blink caching recordings, repeated calls will not cause re-recording. + int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); + for (int i = 0; i < repeat_count; ++i) { + display_list_ = painter->PaintContentsToDisplayList( + recorded_viewport_, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED); + } + is_suitable_for_gpu_rasterization_ = + display_list_->IsSuitableForGpuRasterization(); + + DetermineIfSolidColor(); + display_list_->EmitTraceSnapshot(); + return true; +} + +gfx::Size DisplayListRecordingSource::GetSize() const { + return size_; +} + +void DisplayListRecordingSource::SetEmptyBounds() { + size_ = gfx::Size(); + Clear(); +} + +void DisplayListRecordingSource::SetMinContentsScale(float min_contents_scale) { +} + +void DisplayListRecordingSource::SetTileGridSize( + const gfx::Size& tile_grid_size) { +} + +void DisplayListRecordingSource::SetSlowdownRasterScaleFactor(int factor) { + slow_down_raster_scale_factor_for_debug_ = factor; +} + +void DisplayListRecordingSource::SetUnsuitableForGpuRasterizationForTesting() { + is_suitable_for_gpu_rasterization_ = false; +} + +bool DisplayListRecordingSource::IsSuitableForGpuRasterization() const { + return is_suitable_for_gpu_rasterization_; +} + +scoped_refptr<RasterSource> DisplayListRecordingSource::CreateRasterSource() + const { + return scoped_refptr<RasterSource>( + DisplayListRasterSource::CreateFromDisplayListRecordingSource(this)); +} + +SkTileGridFactory::TileGridInfo +DisplayListRecordingSource::GetTileGridInfoForTesting() const { + return SkTileGridFactory::TileGridInfo(); +} + +void DisplayListRecordingSource::DetermineIfSolidColor() { + DCHECK(display_list_.get()); + is_solid_color_ = false; + solid_color_ = SK_ColorTRANSPARENT; + + if (display_list_->ApproximateOpCount() > kOpCountThatIsOkToAnalyze) + return; + + skia::AnalysisCanvas canvas(recorded_viewport_.width(), + recorded_viewport_.height()); + canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y()); + display_list_->Raster(&canvas, nullptr, 1.f); + is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); +} + +void DisplayListRecordingSource::Clear() { + recorded_viewport_ = gfx::Rect(); + display_list_ = NULL; + is_solid_color_ = false; +} + +} // namespace cc diff --git a/cc/resources/display_list_recording_source.h b/cc/resources/display_list_recording_source.h new file mode 100644 index 0000000..6bc8208 --- /dev/null +++ b/cc/resources/display_list_recording_source.h @@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_DISPLAY_LIST_RECORDING_SOURCE_H_ +#define CC_RESOURCES_DISPLAY_LIST_RECORDING_SOURCE_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/resources/recording_source.h" + +namespace cc { +class DisplayItemList; +class DisplayListRasterSource; + +class CC_EXPORT DisplayListRecordingSource : public RecordingSource { + public: + DisplayListRecordingSource(); + ~DisplayListRecordingSource() override; + + // RecordingSource overrides. + bool UpdateAndExpandInvalidation( + ContentLayerClient* painter, + Region* invalidation, + bool can_use_lcd_text, + const gfx::Size& layer_size, + const gfx::Rect& visible_layer_rect, + int frame_number, + Picture::RecordingMode recording_mode) override; + scoped_refptr<RasterSource> CreateRasterSource() const override; + gfx::Size GetSize() const final; + void SetEmptyBounds() override; + void SetMinContentsScale(float min_contents_scale) override; + void SetSlowdownRasterScaleFactor(int factor) override; + bool IsSuitableForGpuRasterization() const override; + void SetTileGridSize(const gfx::Size& tile_grid_size) override; + void SetUnsuitableForGpuRasterizationForTesting() override; + SkTileGridFactory::TileGridInfo GetTileGridInfoForTesting() const override; + + protected: + void Clear(); + + gfx::Rect recorded_viewport_; + gfx::Size size_; + int slow_down_raster_scale_factor_for_debug_; + bool can_use_lcd_text_; + bool is_solid_color_; + SkColor solid_color_; + int pixel_record_distance_; + + scoped_refptr<DisplayItemList> display_list_; + + private: + friend class DisplayListRasterSource; + + void DetermineIfSolidColor(); + + bool is_suitable_for_gpu_rasterization_; + + DISALLOW_COPY_AND_ASSIGN(DisplayListRecordingSource); +}; + +} // namespace cc + +#endif // CC_RESOURCES_DISPLAY_LIST_RECORDING_SOURCE_H_ diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc new file mode 100644 index 0000000..94e3787 --- /dev/null +++ b/cc/resources/drawing_display_item.cc @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/drawing_display_item.h" + +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkMatrix.h" +#include "third_party/skia/include/core/SkPicture.h" + +namespace cc { + +DrawingDisplayItem::DrawingDisplayItem(skia::RefPtr<SkPicture> picture, + gfx::PointF location) + : picture_(picture), location_(location) { +} + +DrawingDisplayItem::~DrawingDisplayItem() { +} + +void DrawingDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->save(); + canvas->translate(location_.x(), location_.y()); + if (callback) + picture_->draw(canvas, callback); + else + canvas->drawPicture(picture_.get()); + canvas->restore(); +} + +bool DrawingDisplayItem::IsSuitableForGpuRasterization() const { + return picture_->suitableForGpuRasterization(NULL); +} + +int DrawingDisplayItem::ApproximateOpCount() const { + return picture_->approximateOpCount(); +} + +} // namespace cc diff --git a/cc/resources/drawing_display_item.h b/cc/resources/drawing_display_item.h new file mode 100644 index 0000000..672a417 --- /dev/null +++ b/cc/resources/drawing_display_item.h @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_DRAWING_DISPLAY_ITEM_H_ +#define CC_RESOURCES_DRAWING_DISPLAY_ITEM_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/resources/display_item.h" +#include "skia/ext/refptr.h" +#include "ui/gfx/geometry/point_f.h" + +class SkCanvas; +class SkDrawPictureCallback; +class SkPicture; + +namespace cc { + +class CC_EXPORT DrawingDisplayItem : public DisplayItem { + public: + virtual ~DrawingDisplayItem(); + + static scoped_ptr<DrawingDisplayItem> Create(skia::RefPtr<SkPicture> picture, + gfx::PointF location) { + return make_scoped_ptr(new DrawingDisplayItem(picture, location)); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + DrawingDisplayItem(skia::RefPtr<SkPicture> picture, gfx::PointF location); + + private: + skia::RefPtr<SkPicture> picture_; + gfx::PointF location_; +}; + +} // namespace cc + +#endif // CC_RESOURCES_DRAWING_DISPLAY_ITEM_H_ diff --git a/cc/resources/filter_display_item.cc b/cc/resources/filter_display_item.cc new file mode 100644 index 0000000..a2c29c9 --- /dev/null +++ b/cc/resources/filter_display_item.cc @@ -0,0 +1,67 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/filter_display_item.h" + +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkImageFilter.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkXfermode.h" +#include "ui/gfx/skia_util.h" + +namespace cc { + +FilterDisplayItem::FilterDisplayItem(skia::RefPtr<SkImageFilter> filter, + gfx::RectF bounds) + : filter_(filter), bounds_(bounds) { +} + +FilterDisplayItem::~FilterDisplayItem() { +} + +void FilterDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->save(); + SkRect boundaries; + filter_->computeFastBounds(gfx::RectFToSkRect(bounds_), &boundaries); + canvas->translate(bounds_.x(), bounds_.y()); + boundaries.offset(-bounds_.x(), -bounds_.y()); + + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + paint.setImageFilter(filter_.get()); + canvas->saveLayer(&boundaries, &paint); + + canvas->translate(-bounds_.x(), -bounds_.y()); +} + +bool FilterDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int FilterDisplayItem::ApproximateOpCount() const { + return 1; +} + +EndFilterDisplayItem::EndFilterDisplayItem() { +} + +EndFilterDisplayItem::~EndFilterDisplayItem() { +} + +void EndFilterDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->restore(); + canvas->restore(); +} + +bool EndFilterDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int EndFilterDisplayItem::ApproximateOpCount() const { + return 0; +} + +} // namespace cc diff --git a/cc/resources/filter_display_item.h b/cc/resources/filter_display_item.h new file mode 100644 index 0000000..3c8c669 --- /dev/null +++ b/cc/resources/filter_display_item.h @@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_FILTER_DISPLAY_ITEM_H_ +#define CC_RESOURCES_FILTER_DISPLAY_ITEM_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/resources/display_item.h" +#include "skia/ext/refptr.h" +#include "ui/gfx/geometry/rect_f.h" + +class SkCanvas; +class SkDrawPictureCallback; +class SkImageFilter; + +namespace cc { + +class CC_EXPORT FilterDisplayItem : public DisplayItem { + public: + virtual ~FilterDisplayItem(); + + static scoped_ptr<FilterDisplayItem> Create( + skia::RefPtr<SkImageFilter> filter, + gfx::RectF bounds) { + return make_scoped_ptr(new FilterDisplayItem(filter, bounds)); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + FilterDisplayItem(skia::RefPtr<SkImageFilter> filter, gfx::RectF bounds); + + private: + skia::RefPtr<SkImageFilter> filter_; + gfx::RectF bounds_; +}; + +class CC_EXPORT EndFilterDisplayItem : public DisplayItem { + public: + virtual ~EndFilterDisplayItem(); + + static scoped_ptr<EndFilterDisplayItem> Create() { + return make_scoped_ptr(new EndFilterDisplayItem()); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + EndFilterDisplayItem(); +}; + +} // namespace cc + +#endif // CC_RESOURCES_FILTER_DISPLAY_ITEM_H_ diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index 2655d24..834f32d 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc @@ -9,6 +9,7 @@ #include "cc/base/region.h" #include "cc/debug/debug_colors.h" #include "cc/resources/picture_pile_impl.h" +#include "cc/resources/raster_source_helper.h" #include "skia/ext/analysis_canvas.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -87,62 +88,9 @@ void PicturePileImpl::RasterForAnalysis(skia::AnalysisCanvas* canvas, void PicturePileImpl::PlaybackToCanvas(SkCanvas* canvas, const gfx::Rect& canvas_rect, float contents_scale) const { - canvas->discard(); - if (clear_canvas_with_debug_color_) { - // Any non-painted areas in the content bounds will be left in this color. - canvas->clear(DebugColors::NonPaintedFillColor()); - } - - // If this picture has opaque contents, it is guaranteeing that it will - // draw an opaque rect the size of the layer. If it is not, then we must - // clear this canvas ourselves. - if (requires_clear_) { - TRACE_EVENT_INSTANT0("cc", "SkCanvas::clear", TRACE_EVENT_SCOPE_THREAD); - // Clearing is about ~4x faster than drawing a rect even if the content - // isn't covering a majority of the canvas. - canvas->clear(SK_ColorTRANSPARENT); - } else { - // Even if completely covered, for rasterizations that touch the edge of the - // layer, we also need to raster the background color underneath the last - // texel (since the recording won't cover it) and outside the last texel - // (due to linear filtering when using this texture). - gfx::Rect content_tiling_rect = gfx::ToEnclosingRect( - gfx::ScaleRect(gfx::Rect(tiling_.tiling_size()), contents_scale)); - - // The final texel of content may only be partially covered by a - // rasterization; this rect represents the content rect that is fully - // covered by content. - gfx::Rect deflated_content_tiling_rect = content_tiling_rect; - deflated_content_tiling_rect.Inset(0, 0, 1, 1); - if (!deflated_content_tiling_rect.Contains(canvas_rect)) { - if (clear_canvas_with_debug_color_) { - // Any non-painted areas outside of the content bounds are left in - // this color. If this is seen then it means that cc neglected to - // rerasterize a tile that used to intersect with the content rect - // after the content bounds grew. - canvas->save(); - canvas->translate(-canvas_rect.x(), -canvas_rect.y()); - canvas->clipRect(gfx::RectToSkRect(content_tiling_rect), - SkRegion::kDifference_Op); - canvas->drawColor(DebugColors::MissingResizeInvalidations(), - SkXfermode::kSrc_Mode); - canvas->restore(); - } - - // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X - // faster than clearing, so special case this. - canvas->save(); - canvas->translate(-canvas_rect.x(), -canvas_rect.y()); - gfx::Rect inflated_content_tiling_rect = content_tiling_rect; - inflated_content_tiling_rect.Inset(0, 0, -1, -1); - canvas->clipRect(gfx::RectToSkRect(inflated_content_tiling_rect), - SkRegion::kReplace_Op); - canvas->clipRect(gfx::RectToSkRect(deflated_content_tiling_rect), - SkRegion::kDifference_Op); - canvas->drawColor(background_color_, SkXfermode::kSrc_Mode); - canvas->restore(); - } - } + RasterSourceHelper::PrepareForPlaybackToCanvas( + canvas, canvas_rect, gfx::Rect(tiling_.tiling_size()), contents_scale, + background_color_, clear_canvas_with_debug_color_, requires_clear_); RasterCommon(canvas, NULL, diff --git a/cc/resources/raster_source_helper.cc b/cc/resources/raster_source_helper.cc new file mode 100644 index 0000000..f7ef305 --- /dev/null +++ b/cc/resources/raster_source_helper.cc @@ -0,0 +1,81 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/raster_source_helper.h" + +#include "base/debug/trace_event.h" +#include "cc/debug/debug_colors.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/skia_util.h" + +namespace cc { + +void RasterSourceHelper::PrepareForPlaybackToCanvas( + SkCanvas* canvas, + const gfx::Rect& canvas_rect, + const gfx::Rect& source_rect, + float contents_scale, + SkColor background_color, + bool clear_canvas_with_debug_color, + bool requires_clear) { + canvas->discard(); + if (clear_canvas_with_debug_color) { + // Any non-painted areas in the content bounds will be left in this color. + canvas->clear(DebugColors::NonPaintedFillColor()); + } + + // If this raster source has opaque contents, it is guaranteeing that it will + // draw an opaque rect the size of the layer. If it is not, then we must + // clear this canvas ourselves. + if (requires_clear) { + TRACE_EVENT_INSTANT0("cc", "SkCanvas::clear", TRACE_EVENT_SCOPE_THREAD); + // Clearing is about ~4x faster than drawing a rect even if the content + // isn't covering a majority of the canvas. + canvas->clear(SK_ColorTRANSPARENT); + } else { + // Even if completely covered, for rasterizations that touch the edge of the + // layer, we also need to raster the background color underneath the last + // texel (since the recording won't cover it) and outside the last texel + // (due to linear filtering when using this texture). + gfx::Rect content_rect = + gfx::ToEnclosingRect(gfx::ScaleRect(source_rect, contents_scale)); + + // The final texel of content may only be partially covered by a + // rasterization; this rect represents the content rect that is fully + // covered by content. + gfx::Rect deflated_content_rect = content_rect; + deflated_content_rect.Inset(0, 0, 1, 1); + if (!deflated_content_rect.Contains(canvas_rect)) { + if (clear_canvas_with_debug_color) { + // Any non-painted areas outside of the content bounds are left in + // this color. If this is seen then it means that cc neglected to + // rerasterize a tile that used to intersect with the content rect + // after the content bounds grew. + canvas->save(); + canvas->translate(-canvas_rect.x(), -canvas_rect.y()); + canvas->clipRect(gfx::RectToSkRect(content_rect), + SkRegion::kDifference_Op); + canvas->drawColor(DebugColors::MissingResizeInvalidations(), + SkXfermode::kSrc_Mode); + canvas->restore(); + } + + // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X + // faster than clearing, so special case this. + canvas->save(); + canvas->translate(-canvas_rect.x(), -canvas_rect.y()); + gfx::Rect inflated_content_rect = content_rect; + inflated_content_rect.Inset(0, 0, -1, -1); + canvas->clipRect(gfx::RectToSkRect(inflated_content_rect), + SkRegion::kReplace_Op); + canvas->clipRect(gfx::RectToSkRect(deflated_content_rect), + SkRegion::kDifference_Op); + canvas->drawColor(background_color, SkXfermode::kSrc_Mode); + canvas->restore(); + } + } +} + +} // namespace cc diff --git a/cc/resources/raster_source_helper.h b/cc/resources/raster_source_helper.h new file mode 100644 index 0000000..abdea3e --- /dev/null +++ b/cc/resources/raster_source_helper.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_RASTER_SOURCE_HELPER_H_ +#define CC_RESOURCES_RASTER_SOURCE_HELPER_H_ + +#include "cc/base/cc_export.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/rect.h" + +class SkCanvas; + +namespace cc { + +class CC_EXPORT RasterSourceHelper { + public: + static void PrepareForPlaybackToCanvas(SkCanvas* canvas, + const gfx::Rect& canvas_rect, + const gfx::Rect& source_rect, + float contents_scale, + SkColor background_color, + bool clear_canvas_with_debug_color, + bool requires_clear); +}; + +} // namespace cc + +#endif // CC_RESOURCES_RASTER_SOURCE_HELPER_H_ diff --git a/cc/resources/transform_display_item.cc b/cc/resources/transform_display_item.cc new file mode 100644 index 0000000..62528da --- /dev/null +++ b/cc/resources/transform_display_item.cc @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/transform_display_item.h" + +#include "third_party/skia/include/core/SkCanvas.h" + +namespace cc { + +TransformDisplayItem::TransformDisplayItem(const gfx::Transform& transform) + : transform_(transform) { +} + +TransformDisplayItem::~TransformDisplayItem() { +} + +void TransformDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->save(); + if (!transform_.IsIdentity()) + canvas->concat(transform_.matrix()); +} + +bool TransformDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int TransformDisplayItem::ApproximateOpCount() const { + return 1; +} + +EndTransformDisplayItem::EndTransformDisplayItem() { +} + +EndTransformDisplayItem::~EndTransformDisplayItem() { +} + +void EndTransformDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->restore(); +} + +bool EndTransformDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int EndTransformDisplayItem::ApproximateOpCount() const { + return 0; +} + +} // namespace cc diff --git a/cc/resources/transform_display_item.h b/cc/resources/transform_display_item.h new file mode 100644 index 0000000..9d289c2 --- /dev/null +++ b/cc/resources/transform_display_item.h @@ -0,0 +1,58 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_TRANSFORM_DISPLAY_ITEM_H_ +#define CC_RESOURCES_TRANSFORM_DISPLAY_ITEM_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/resources/display_item.h" +#include "ui/gfx/transform.h" + +class SkCanvas; +class SkDrawPictureCallback; + +namespace cc { + +class CC_EXPORT TransformDisplayItem : public DisplayItem { + public: + virtual ~TransformDisplayItem(); + + static scoped_ptr<TransformDisplayItem> Create( + const gfx::Transform& transform) { + return make_scoped_ptr(new TransformDisplayItem(transform)); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + explicit TransformDisplayItem(const gfx::Transform& transform); + + private: + gfx::Transform transform_; +}; + +class CC_EXPORT EndTransformDisplayItem : public DisplayItem { + public: + virtual ~EndTransformDisplayItem(); + + static scoped_ptr<EndTransformDisplayItem> Create() { + return make_scoped_ptr(new EndTransformDisplayItem()); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + EndTransformDisplayItem(); +}; + +} // namespace cc + +#endif // CC_RESOURCES_TRANSFORM_DISPLAY_ITEM_H_ diff --git a/cc/resources/transparency_display_item.cc b/cc/resources/transparency_display_item.cc new file mode 100644 index 0000000..2d8d492 --- /dev/null +++ b/cc/resources/transparency_display_item.cc @@ -0,0 +1,57 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/transparency_display_item.h" + +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkXfermode.h" +#include "ui/gfx/skia_util.h" + +namespace cc { + +TransparencyDisplayItem::TransparencyDisplayItem(float opacity, + SkXfermode::Mode blend_mode) + : opacity_(opacity), blend_mode_(blend_mode) { +} + +TransparencyDisplayItem::~TransparencyDisplayItem() { +} + +void TransparencyDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + SkPaint paint; + paint.setXfermodeMode(blend_mode_); + paint.setAlpha(opacity_ * 255); + canvas->saveLayer(NULL, &paint); +} + +bool TransparencyDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int TransparencyDisplayItem::ApproximateOpCount() const { + return 1; +} + +EndTransparencyDisplayItem::EndTransparencyDisplayItem() { +} + +EndTransparencyDisplayItem::~EndTransparencyDisplayItem() { +} + +void EndTransparencyDisplayItem::Raster(SkCanvas* canvas, + SkDrawPictureCallback* callback) const { + canvas->restore(); +} + +bool EndTransparencyDisplayItem::IsSuitableForGpuRasterization() const { + return true; +} + +int EndTransparencyDisplayItem::ApproximateOpCount() const { + return 0; +} + +} // namespace cc diff --git a/cc/resources/transparency_display_item.h b/cc/resources/transparency_display_item.h new file mode 100644 index 0000000..f0cc40b --- /dev/null +++ b/cc/resources/transparency_display_item.h @@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_TRANSPARENCY_DISPLAY_ITEM_H_ +#define CC_RESOURCES_TRANSPARENCY_DISPLAY_ITEM_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/resources/display_item.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkXfermode.h" +#include "ui/gfx/geometry/rect_f.h" + +class SkCanvas; +class SkDrawPictureCallback; + +namespace cc { + +class CC_EXPORT TransparencyDisplayItem : public DisplayItem { + public: + virtual ~TransparencyDisplayItem(); + + static scoped_ptr<TransparencyDisplayItem> Create( + float opacity, + SkXfermode::Mode blend_mode) { + return make_scoped_ptr(new TransparencyDisplayItem(opacity, blend_mode)); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + TransparencyDisplayItem(float opacity, SkXfermode::Mode blend_mode); + + private: + float opacity_; + SkXfermode::Mode blend_mode_; +}; + +class CC_EXPORT EndTransparencyDisplayItem : public DisplayItem { + public: + virtual ~EndTransparencyDisplayItem(); + + static scoped_ptr<EndTransparencyDisplayItem> Create() { + return make_scoped_ptr(new EndTransparencyDisplayItem()); + } + + void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; + + bool IsSuitableForGpuRasterization() const override; + int ApproximateOpCount() const override; + + protected: + EndTransparencyDisplayItem(); +}; + +} // namespace cc + +#endif // CC_RESOURCES_TRANSPARENCY_DISPLAY_ITEM_H_ diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc index 5463aed..46d1baa 100644 --- a/cc/test/fake_content_layer_client.cc +++ b/cc/test/fake_content_layer_client.cc @@ -4,7 +4,10 @@ #include "cc/test/fake_content_layer_client.h" +#include "cc/resources/clip_display_item.h" +#include "cc/resources/drawing_display_item.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" #include "ui/gfx/skia_util.h" namespace cc { @@ -52,6 +55,58 @@ void FakeContentLayerClient::PaintContents( } } +scoped_refptr<DisplayItemList> +FakeContentLayerClient::PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) { + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + skia::RefPtr<SkPicture> picture; + scoped_refptr<DisplayItemList> list = DisplayItemList::Create(); + list->AppendItem(ClipDisplayItem::Create(clip, std::vector<SkRRect>())); + + for (RectPaintVector::const_iterator it = draw_rects_.begin(); + it != draw_rects_.end(); ++it) { + const gfx::RectF& draw_rect = it->first; + const SkPaint& paint = it->second; + canvas = skia::SharePtr( + recorder.beginRecording(draw_rect.width(), draw_rect.height())); + canvas->drawRectCoords(0.f, 0.f, draw_rect.width(), draw_rect.height(), + paint); + picture = skia::AdoptRef(recorder.endRecording()); + list->AppendItem(DrawingDisplayItem::Create( + picture, gfx::PointF(draw_rect.x(), draw_rect.y()))); + } + + for (BitmapVector::const_iterator it = draw_bitmaps_.begin(); + it != draw_bitmaps_.end(); ++it) { + canvas = skia::SharePtr( + recorder.beginRecording(it->bitmap.width(), it->bitmap.height())); + canvas->drawBitmap(it->bitmap, 0.f, 0.f, &it->paint); + picture = skia::AdoptRef(recorder.endRecording()); + list->AppendItem(DrawingDisplayItem::Create( + picture, gfx::PointF(it->point.x(), it->point.y()))); + } + + if (fill_with_nonsolid_color_) { + gfx::RectF draw_rect = clip; + bool red = true; + while (!draw_rect.IsEmpty()) { + SkPaint paint; + paint.setColor(red ? SK_ColorRED : SK_ColorBLUE); + canvas = + skia::SharePtr(recorder.beginRecording(clip.width(), clip.height())); + canvas->drawRect(gfx::RectFToSkRect(draw_rect), paint); + picture = skia::AdoptRef(recorder.endRecording()); + list->AppendItem(DrawingDisplayItem::Create(picture, gfx::PointF())); + draw_rect.Inset(1, 1); + } + } + + list->AppendItem(EndClipDisplayItem::Create()); + return list; +} + bool FakeContentLayerClient::FillsBoundsCompletely() const { return false; } } // namespace cc diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h index 141bc97..1060d08 100644 --- a/cc/test/fake_content_layer_client.h +++ b/cc/test/fake_content_layer_client.h @@ -31,6 +31,9 @@ class FakeContentLayerClient : public ContentLayerClient { SkCanvas* canvas, const gfx::Rect& rect, ContentLayerClient::GraphicsContextStatus gc_status) override; + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override; bool FillsBoundsCompletely() const override; void set_fill_with_nonsolid_color(bool nonsolid) { diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc index 1ccb2d1..ef61e21 100644 --- a/cc/test/skia_common.cc +++ b/cc/test/skia_common.cc @@ -4,6 +4,7 @@ #include "cc/test/skia_common.h" +#include "cc/resources/display_item_list.h" #include "cc/resources/picture.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -26,6 +27,18 @@ void DrawPicture(unsigned char* buffer, picture->Raster(&canvas, NULL, negated_content_region, 1.0f); } +void DrawDisplayList(unsigned char* buffer, + const gfx::Rect& layer_rect, + scoped_refptr<DisplayItemList> list) { + SkImageInfo info = + SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); + SkBitmap bitmap; + bitmap.installPixels(info, buffer, info.minRowBytes()); + SkCanvas canvas(bitmap); + canvas.clipRect(gfx::RectToSkRect(layer_rect)); + list->Raster(&canvas, NULL, 1.0f); +} + void CreateBitmap(const gfx::Size& size, const char* uri, SkBitmap* bitmap) { SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); diff --git a/cc/test/skia_common.h b/cc/test/skia_common.h index 3bafa0b..51ebcc5 100644 --- a/cc/test/skia_common.h +++ b/cc/test/skia_common.h @@ -18,11 +18,16 @@ class Size; namespace cc { class Picture; +class DisplayItemList; void DrawPicture(unsigned char* buffer, const gfx::Rect& layer_rect, scoped_refptr<Picture> picture); +void DrawDisplayList(unsigned char* buffer, + const gfx::Rect& layer_rect, + scoped_refptr<DisplayItemList> list); + void CreateBitmap(const gfx::Size& size, const char* uri, SkBitmap* bitmap); } // namespace cc diff --git a/cc/test/solid_color_content_layer_client.cc b/cc/test/solid_color_content_layer_client.cc index 237dbb6..701f004 100644 --- a/cc/test/solid_color_content_layer_client.cc +++ b/cc/test/solid_color_content_layer_client.cc @@ -25,6 +25,14 @@ void SolidColorContentLayerClient::PaintContents( paint); } +scoped_refptr<DisplayItemList> +SolidColorContentLayerClient::PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); +} + bool SolidColorContentLayerClient::FillsBoundsCompletely() const { return false; } diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h index 7a962cf..93fca84 100644 --- a/cc/test/solid_color_content_layer_client.h +++ b/cc/test/solid_color_content_layer_client.h @@ -20,6 +20,9 @@ class SolidColorContentLayerClient : public ContentLayerClient { SkCanvas* canvas, const gfx::Rect& rect, ContentLayerClient::GraphicsContextStatus gc_status) override; + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override; bool FillsBoundsCompletely() const override; private: diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 7a282c1..b9acf5a 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc @@ -59,6 +59,12 @@ class MockContentLayerClient : public ContentLayerClient { SkCanvas* canvas, const gfx::Rect& clip, ContentLayerClient::GraphicsContextStatus gc_status) override {} + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } bool FillsBoundsCompletely() const override { return false; } }; diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc index c494914..1235e15 100644 --- a/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -47,6 +47,13 @@ class MaskContentLayerClient : public ContentLayerClient { } } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } + private: gfx::Size bounds_; }; diff --git a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc index e7dd149..a5ccb8b 100644 --- a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc +++ b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc @@ -80,6 +80,13 @@ class BlueYellowLayerClient : public ContentLayerClient { paint); } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } + private: gfx::Rect layer_rect_; }; diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 62f567e..a1e82f8 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -1114,6 +1114,12 @@ class TestOpacityChangeLayerDelegate : public ContentLayerClient { if (test_layer_) test_layer_->SetOpacity(0.f); } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } bool FillsBoundsCompletely() const override { return false; } private: @@ -2323,6 +2329,13 @@ class LayerTreeHostTestLCDChange : public LayerTreeHostTest { ++paint_count_; } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } + bool FillsBoundsCompletely() const override { return false; } private: @@ -2593,6 +2606,13 @@ class LayerTreeHostTestChangeLayerPropertiesInPaintContents layer_->SetBounds(gfx::Size(2, 2)); } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + const gfx::Rect& clip, + GraphicsContextStatus gc_status) override { + NOTIMPLEMENTED(); + return DisplayItemList::Create(); + } + bool FillsBoundsCompletely() const override { return false; } private: diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index 50e47c9..0f8f8d6 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc @@ -65,7 +65,8 @@ LayerTreeSettings::LayerTreeSettings() ignore_root_layer_flings(false), scheduled_raster_task_limit(32), use_occlusion_for_tile_prioritization(false), - record_full_layer(false) { + record_full_layer(false), + use_display_lists(false) { } LayerTreeSettings::~LayerTreeSettings() {} diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index 66d0586..3c2a72b 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h @@ -78,6 +78,7 @@ class CC_EXPORT LayerTreeSettings { size_t scheduled_raster_task_limit; bool use_occlusion_for_tile_prioritization; bool record_full_layer; + bool use_display_lists; LayerTreeDebugState initial_debug_state; }; |