Chromium Code Reviews| Index: cc/playback/display_list_raster_source.cc |
| diff --git a/cc/playback/display_list_raster_source.cc b/cc/playback/display_list_raster_source.cc |
| index cc4f7a7807d4b95b21a292c48d7440b560fbc222..c9ef9897b12d9f4a60a19c4a2f134f186fd2e3f9 100644 |
| --- a/cc/playback/display_list_raster_source.cc |
| +++ b/cc/playback/display_list_raster_source.cc |
| @@ -8,13 +8,172 @@ |
| #include "cc/base/region.h" |
| #include "cc/debug/debug_colors.h" |
| #include "cc/playback/display_item_list.h" |
| +#include "cc/tiles/image_decode_controller.h" |
| #include "skia/ext/analysis_canvas.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkPictureRecorder.h" |
| +#include "third_party/skia/include/utils/SkNWayCanvas.h" |
| #include "ui/gfx/geometry/rect_conversions.h" |
| namespace cc { |
| +namespace { |
| + |
| +SkSize ExtractScale(const SkMatrix& matrix) { |
| + SkSize scale = SkSize::Make(matrix.getScaleX(), matrix.getScaleY()); |
| + if (matrix.getType() & SkMatrix::kAffine_Mask) { |
| + if (!matrix.decomposeScale(&scale)) |
| + scale.set(1, 1); |
| + } |
| + return scale; |
| +} |
| + |
| +class ImageHijackCanvas : public SkNWayCanvas { |
| + public: |
| + ImageHijackCanvas(int width, |
| + int height, |
| + ImageDecodeController* image_decode_controller) |
| + : SkNWayCanvas(width, height), |
| + image_decode_controller_(image_decode_controller) {} |
| + |
| + protected: |
| + // Ensure that pictures are unpacked by this canvas, instead of being |
| + // forwarded to the raster canvas. |
| + void onDrawPicture(const SkPicture* picture, |
| + const SkMatrix* matrix, |
| + const SkPaint* paint) override { |
| + SkCanvas::onDrawPicture(picture, matrix, paint); |
| + } |
| + |
| + void onDrawImage(const SkImage* image, |
| + SkScalar x, |
| + SkScalar y, |
| + const SkPaint* paint) override { |
| + if (!image->isLazyGenerated()) { |
| + SkNWayCanvas::onDrawImage(image, x, y, paint); |
| + return; |
| + } |
| + |
| + SkMatrix ctm = this->getTotalMatrix(); |
| + |
| + ScopedDecodedImageLock scoped_lock(image_decode_controller_, image, |
| + ExtractScale(ctm), paint); |
| + const DecodedDrawImage& decoded_image = scoped_lock.decoded_image(); |
| + const SkPaint* decoded_paint = scoped_lock.decoded_paint(); |
| + |
| + SkNWayCanvas::save(); |
| + SkNWayCanvas::scale(1.f / (decoded_image.scale_adjustment().width()), |
|
reed1
2015/10/27 17:35:07
Is scale_adjustment = scaled_version.width / origi
|
| + 1.f / (decoded_image.scale_adjustment().height())); |
| + SkNWayCanvas::onDrawImage(decoded_image.image(), x, y, decoded_paint); |
| + SkNWayCanvas::restore(); |
| + } |
| + |
| + void onDrawImageRect(const SkImage* image, |
| + const SkRect* src, |
| + const SkRect& dst, |
| + const SkPaint* paint, |
| + SrcRectConstraint constraint) override { |
| + if (!image->isLazyGenerated()) { |
| + SkNWayCanvas::onDrawImageRect(image, src, dst, paint, constraint); |
| + return; |
| + } |
| + |
| + SkMatrix ctm = this->getTotalMatrix(); |
| + SkRect src_storage; |
| + if (!src) { |
| + src_storage = SkRect::MakeIWH(image->width(), image->height()); |
| + src = &src_storage; |
| + } |
| + SkMatrix matrix; |
| + matrix.setRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit); |
| + matrix.postConcat(ctm); |
| + |
| + ScopedDecodedImageLock scoped_lock(image_decode_controller_, image, |
| + ExtractScale(matrix), paint); |
| + const DecodedDrawImage& decoded_image = scoped_lock.decoded_image(); |
| + const SkPaint* decoded_paint = scoped_lock.decoded_paint(); |
| + |
| + float x_scale = decoded_image.scale_adjustment().width(); |
| + float y_scale = decoded_image.scale_adjustment().height(); |
| + SkRect adjusted_src = |
| + SkRect::MakeXYWH(src->x() * x_scale, src->y() * y_scale, |
| + src->width() * x_scale, src->height() * y_scale); |
| + SkNWayCanvas::onDrawImageRect(decoded_image.image(), &adjusted_src, dst, |
| + decoded_paint, constraint); |
| + } |
| + |
| + void onDrawImageNine(const SkImage* image, |
| + const SkIRect& center, |
| + const SkRect& dst, |
| + const SkPaint* paint) override { |
| + if (!image->isLazyGenerated()) { |
| + SkNWayCanvas::onDrawImageNine(image, center, dst, paint); |
| + return; |
| + } |
| + |
| + SkMatrix ctm = this->getTotalMatrix(); |
| + ScopedDecodedImageLock scoped_lock(image_decode_controller_, image, |
| + ExtractScale(ctm), paint); |
| + const DecodedDrawImage& decoded_image = scoped_lock.decoded_image(); |
| + const SkPaint* decoded_paint = scoped_lock.decoded_paint(); |
| + |
| + float x_scale = decoded_image.scale_adjustment().width(); |
| + float y_scale = decoded_image.scale_adjustment().height(); |
| + SkIRect adjusted_center = SkIRect::MakeXYWH( |
| + static_cast<int>(std::floor(center.x() * x_scale)), |
| + static_cast<int>(std::floor(center.y() * y_scale)), |
| + static_cast<int>(std::ceil(center.width() * x_scale)), |
| + static_cast<int>(std::ceil(center.height() * y_scale))); |
| + SkNWayCanvas::onDrawImageNine(decoded_image.image(), adjusted_center, dst, |
| + decoded_paint); |
| + } |
| + |
| + private: |
| + class ScopedDecodedImageLock { |
| + public: |
| + ScopedDecodedImageLock(ImageDecodeController* image_decode_controller, |
| + const SkImage* image, |
| + const SkSize& scale, |
| + const SkPaint* paint) |
| + : image_decode_controller_(image_decode_controller), |
| + paint_(paint), |
| + draw_image_( |
| + image, |
| + scale, |
| + paint ? paint->getFilterQuality() : kNone_SkFilterQuality), |
| + decoded_draw_image_( |
| + image_decode_controller_->GetDecodedImage(draw_image_)) { |
| + DCHECK(image->isLazyGenerated()); |
| + if (paint) { |
| + decoded_paint_ = *paint; |
| + decoded_paint_.setFilterQuality(decoded_draw_image_.filter_quality()); |
| + } |
| + } |
| + |
| + ~ScopedDecodedImageLock() { |
| + image_decode_controller_->DrawWithImageFinished(draw_image_); |
| + } |
| + |
| + const DecodedDrawImage& decoded_image() const { |
| + return decoded_draw_image_; |
| + } |
| + const SkPaint* decoded_paint() const { |
| + return paint_ ? &decoded_paint_ : nullptr; |
| + } |
| + |
| + private: |
| + ImageDecodeController* image_decode_controller_; |
| + const SkPaint* paint_; |
| + DrawImage draw_image_; |
| + DecodedDrawImage decoded_draw_image_; |
| + SkPaint decoded_paint_; |
| + }; |
| + |
| + ImageDecodeController* image_decode_controller_; |
| +}; |
| + |
| +} // namespace |
| + |
| scoped_refptr<DisplayListRasterSource> |
| DisplayListRasterSource::CreateFromDisplayListRecordingSource( |
| const DisplayListRecordingSource* other, |
| @@ -38,7 +197,8 @@ DisplayListRasterSource::DisplayListRasterSource( |
| clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_), |
| slow_down_raster_scale_factor_for_debug_( |
| other->slow_down_raster_scale_factor_for_debug_), |
| - should_attempt_to_use_distance_field_text_(false) {} |
| + should_attempt_to_use_distance_field_text_(false), |
| + image_decode_controller_(nullptr) {} |
| DisplayListRasterSource::DisplayListRasterSource( |
| const DisplayListRasterSource* other, |
| @@ -56,7 +216,8 @@ DisplayListRasterSource::DisplayListRasterSource( |
| slow_down_raster_scale_factor_for_debug_( |
| other->slow_down_raster_scale_factor_for_debug_), |
| should_attempt_to_use_distance_field_text_( |
| - other->should_attempt_to_use_distance_field_text_) {} |
| + other->should_attempt_to_use_distance_field_text_), |
| + image_decode_controller_(other->image_decode_controller_) {} |
| DisplayListRasterSource::~DisplayListRasterSource() { |
| } |
| @@ -173,24 +334,29 @@ void DisplayListRasterSource::PrepareForPlaybackToCanvas( |
| } |
| void DisplayListRasterSource::RasterCommon( |
| - SkCanvas* canvas, |
| + SkCanvas* raster_canvas, |
| SkPicture::AbortCallback* callback, |
| const gfx::Rect& canvas_bitmap_rect, |
| const gfx::Rect& canvas_playback_rect, |
| float contents_scale) const { |
| - canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); |
| + SkImageInfo info = raster_canvas->imageInfo(); |
| + ImageHijackCanvas canvas(info.width(), info.height(), |
| + image_decode_controller_); |
| + canvas.addCanvas(raster_canvas); |
| + |
| + canvas.translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); |
| gfx::Rect content_rect = |
| gfx::ScaleToEnclosingRect(gfx::Rect(size_), contents_scale); |
| content_rect.Intersect(canvas_playback_rect); |
| - canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op); |
| + canvas.clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op); |
| DCHECK(display_list_.get()); |
| gfx::Rect canvas_target_playback_rect = |
| canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin(); |
| int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); |
| for (int i = 0; i < repeat_count; ++i) { |
| - display_list_->Raster(canvas, callback, canvas_target_playback_rect, |
| + display_list_->Raster(&canvas, callback, canvas_target_playback_rect, |
| contents_scale); |
| } |
| } |
| @@ -300,4 +466,12 @@ DisplayListRasterSource::CreateCloneWithoutLCDText() const { |
| new DisplayListRasterSource(this, can_use_lcd_text)); |
| } |
| +void DisplayListRasterSource::SetImageDecodeController( |
| + ImageDecodeController* image_decode_controller) { |
| + // This should only be set once. |
| + DCHECK(image_decode_controller); |
| + DCHECK(!image_decode_controller_); |
| + image_decode_controller_ = image_decode_controller; |
| +} |
| + |
| } // namespace cc |