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..af9d030e7837053ed502048f15c25148f4a7ec55 100644 |
--- a/cc/playback/display_list_raster_source.cc |
+++ b/cc/playback/display_list_raster_source.cc |
@@ -8,13 +8,190 @@ |
#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 { |
+ |
+SkRect MapRect(const SkMatrix& matrix, const SkRect& src) { |
+ SkRect dst; |
+ matrix.mapRect(&dst, src); |
+ return dst; |
+} |
+ |
+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), |
+ canvas_bounds_(SkRect::MakeIWH(width, height)) {} |
+ |
+ 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(); |
+ if (!canvas_bounds_.intersects(MapRect( |
+ ctm, SkRect::MakeXYWH(x, y, image->width(), image->height())))) { |
+ return; |
+ } |
+ |
+ 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(); |
enne (OOO)
2015/10/29 22:59:45
Is it worth conditionalizing this save and restore
|
+ SkNWayCanvas::scale(1.f / (decoded_image.scale_adjustment().width()), |
+ 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(); |
+ if (!canvas_bounds_.intersects(MapRect(ctm, dst))) |
+ return; |
+ |
+ 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; |
+ } |
+ |
+ if (!canvas_bounds_.intersects(dst)) |
+ 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_->GetDecodedImageAndRef(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_; |
+ const SkRect canvas_bounds_; |
+}; |
+ |
+} // namespace |
+ |
scoped_refptr<DisplayListRasterSource> |
DisplayListRasterSource::CreateFromDisplayListRecordingSource( |
const DisplayListRecordingSource* other, |
@@ -38,7 +215,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 +234,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 +352,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 +484,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 |