// 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/playback/display_list_raster_source.h"

#include <stddef.h>

#include "base/containers/adapters.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/region.h"
#include "cc/debug/debug_colors.h"
#include "cc/playback/discardable_image_map.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/core/SkTLazy.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {

namespace {

SkIRect RoundOutRect(const SkRect& rect) {
  SkIRect result;
  rect.roundOut(&result);
  return result;
}

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 = getTotalMatrix();

    SkSize scale;
    bool is_decomposable = ExtractScale(ctm, &scale);
    ScopedDecodedImageLock scoped_lock(
        image_decode_controller_, image,
        SkRect::MakeIWH(image->width(), image->height()), scale,
        is_decomposable, ctm.hasPerspective(), paint);
    const DecodedDrawImage& decoded_image = scoped_lock.decoded_image();
    if (!decoded_image.image())
      return;

    DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().width()));
    DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().height()));
    const SkPaint* decoded_paint = scoped_lock.decoded_paint();

    bool need_scale = !decoded_image.is_scale_adjustment_identity();
    if (need_scale) {
      SkNWayCanvas::save();
      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);
    if (need_scale)
      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;
    }

    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(getTotalMatrix());

    SkSize scale;
    bool is_decomposable = ExtractScale(matrix, &scale);
    ScopedDecodedImageLock scoped_lock(image_decode_controller_, image, *src,
                                       scale, is_decomposable,
                                       matrix.hasPerspective(), paint);
    const DecodedDrawImage& decoded_image = scoped_lock.decoded_image();
    if (!decoded_image.image())
      return;

    const SkPaint* decoded_paint = scoped_lock.decoded_paint();

    SkRect adjusted_src =
        src->makeOffset(decoded_image.src_rect_offset().width(),
                        decoded_image.src_rect_offset().height());
    if (!decoded_image.is_scale_adjustment_identity()) {
      float x_scale = decoded_image.scale_adjustment().width();
      float y_scale = decoded_image.scale_adjustment().height();
      adjusted_src = SkRect::MakeXYWH(
          adjusted_src.x() * x_scale, adjusted_src.y() * y_scale,
          adjusted_src.width() * x_scale, adjusted_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 {
    // No cc embedder issues image nine calls.
    NOTREACHED();
  }

 private:
  class ScopedDecodedImageLock {
   public:
    ScopedDecodedImageLock(ImageDecodeController* image_decode_controller,
                           const SkImage* image,
                           const SkRect& src_rect,
                           const SkSize& scale,
                           bool is_decomposable,
                           bool has_perspective,
                           const SkPaint* paint)
        : image_decode_controller_(image_decode_controller),
          draw_image_(image,
                      RoundOutRect(src_rect),
                      scale,
                      paint ? paint->getFilterQuality() : kNone_SkFilterQuality,
                      has_perspective,
                      is_decomposable),
          decoded_draw_image_(
              image_decode_controller_->GetDecodedImageForDraw(draw_image_)) {
      DCHECK(image->isLazyGenerated());
      if (paint)
        decoded_paint_.set(*paint)->setFilterQuality(
            decoded_draw_image_.filter_quality());
    }

    ~ScopedDecodedImageLock() {
      image_decode_controller_->DrawWithImageFinished(draw_image_,
                                                      decoded_draw_image_);
    }

    const DecodedDrawImage& decoded_image() const {
      return decoded_draw_image_;
    }
    const SkPaint* decoded_paint() const {
      return decoded_paint_.getMaybeNull();
    }

   private:
    ImageDecodeController* image_decode_controller_;
    DrawImage draw_image_;
    DecodedDrawImage decoded_draw_image_;
    // TODO(fmalita): use base::Optional when it becomes available
    SkTLazy<SkPaint> decoded_paint_;
  };

  ImageDecodeController* image_decode_controller_;
};

}  // namespace

scoped_refptr<DisplayListRasterSource>
DisplayListRasterSource::CreateFromDisplayListRecordingSource(
    const DisplayListRecordingSource* other,
    bool can_use_lcd_text) {
  return make_scoped_refptr(
      new DisplayListRasterSource(other, can_use_lcd_text));
}

DisplayListRasterSource::DisplayListRasterSource(
    const DisplayListRecordingSource* other,
    bool can_use_lcd_text)
    : display_list_(other->display_list_),
      painter_reported_memory_usage_(other->painter_reported_memory_usage_),
      background_color_(other->background_color_),
      requires_clear_(other->requires_clear_),
      can_use_lcd_text_(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_(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),
      image_decode_controller_(nullptr) {
  // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
  // Don't register a dump provider in these cases.
  // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
  if (base::ThreadTaskRunnerHandle::IsSet()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "cc::DisplayListRasterSource",
        base::ThreadTaskRunnerHandle::Get());
  }
}

DisplayListRasterSource::DisplayListRasterSource(
    const DisplayListRasterSource* other,
    bool can_use_lcd_text)
    : display_list_(other->display_list_),
      painter_reported_memory_usage_(other->painter_reported_memory_usage_),
      background_color_(other->background_color_),
      requires_clear_(other->requires_clear_),
      can_use_lcd_text_(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_(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_(
          other->should_attempt_to_use_distance_field_text_),
      image_decode_controller_(other->image_decode_controller_) {
  // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
  // Don't register a dump provider in these cases.
  // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
  if (base::ThreadTaskRunnerHandle::IsSet()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "cc::DisplayListRasterSource",
        base::ThreadTaskRunnerHandle::Get());
  }
}

DisplayListRasterSource::~DisplayListRasterSource() {
  // For MemoryDumpProvider deregistration to work correctly, this must happen
  // on the same thread that the DisplayListRasterSource was created on.
  DCHECK(memory_dump_thread_checker_.CalledOnValidThread());
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

void DisplayListRasterSource::PlaybackToSharedCanvas(
    SkCanvas* raster_canvas,
    const gfx::Rect& canvas_rect,
    float contents_scale) const {
  // TODO(vmpstr): This can be improved by plumbing whether the tile itself has
  // discardable images. This way we would only pay for the hijack canvas if the
  // tile actually needed it.
  if (display_list_->MayHaveDiscardableImages()) {
    const SkImageInfo& info = raster_canvas->imageInfo();
    ImageHijackCanvas canvas(info.width(), info.height(),
                             image_decode_controller_);
    canvas.addCanvas(raster_canvas);

    RasterCommon(&canvas, nullptr, canvas_rect, canvas_rect, contents_scale);
  } else {
    RasterCommon(raster_canvas, nullptr, canvas_rect, canvas_rect,
                 contents_scale);
  }
}

void DisplayListRasterSource::RasterForAnalysis(skia::AnalysisCanvas* canvas,
                                                const gfx::Rect& canvas_rect,
                                                float contents_scale) const {
  RasterCommon(canvas, canvas, canvas_rect, canvas_rect, contents_scale);
}

void DisplayListRasterSource::PlaybackToCanvas(
    SkCanvas* raster_canvas,
    const gfx::Rect& canvas_bitmap_rect,
    const gfx::Rect& canvas_playback_rect,
    float contents_scale) const {
  PrepareForPlaybackToCanvas(raster_canvas, canvas_bitmap_rect,
                             canvas_playback_rect, contents_scale);

  SkImageInfo info = raster_canvas->imageInfo();
  ImageHijackCanvas canvas(info.width(), info.height(),
                           image_decode_controller_);
  canvas.addCanvas(raster_canvas);
  RasterCommon(&canvas, NULL, canvas_bitmap_rect, canvas_playback_rect,
               contents_scale);
}

void DisplayListRasterSource::PrepareForPlaybackToCanvas(
    SkCanvas* canvas,
    const gfx::Rect& canvas_bitmap_rect,
    const gfx::Rect& canvas_playback_rect,
    float contents_scale) const {
  // TODO(hendrikw): See if we can split this up into separate functions.
  bool partial_update = canvas_bitmap_rect != canvas_playback_rect;

  if (!partial_update)
    canvas->discard();
  if (clear_canvas_with_debug_color_) {
    // Any non-painted areas in the content bounds will be left in this color.
    if (!partial_update) {
      canvas->clear(DebugColors::NonPaintedFillColor());
    } else {
      canvas->save();
      canvas->clipRect(gfx::RectToSkRect(
          canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin()));
      canvas->drawColor(DebugColors::NonPaintedFillColor());
      canvas->restore();
    }
  }

  // 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.
    if (!partial_update) {
      canvas->clear(SK_ColorTRANSPARENT);
    } else {
      canvas->save();
      canvas->clipRect(gfx::RectToSkRect(
          canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin()));
      canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kClear_Mode);
      canvas->restore();
    }
  } 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::ScaleToEnclosingRect(gfx::Rect(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_rect = content_rect;
    deflated_content_rect.Inset(0, 0, 1, 1);
    deflated_content_rect.Intersect(canvas_playback_rect);
    if (!deflated_content_rect.Contains(canvas_playback_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_bitmap_rect.x(), -canvas_bitmap_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_bitmap_rect.x(), -canvas_bitmap_rect.y());
      gfx::Rect inflated_content_rect = content_rect;
      // Only clear edges that will be inside the canvas_playback_rect, else we
      // clear things that are still valid from a previous raster.
      inflated_content_rect.Inset(0, 0, -1, -1);
      inflated_content_rect.Intersect(canvas_playback_rect);
      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();
    }
  }
}

void DisplayListRasterSource::RasterCommon(
    SkCanvas* 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());
  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);

  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,
                          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()) {
    PrepareForPlaybackToCanvas(canvas, display_list_rect, display_list_rect,
                               1.f);
    RasterCommon(canvas, nullptr, display_list_rect, display_list_rect, 1.f);
  }
  skia::RefPtr<SkPicture> picture =
      skia::AdoptRef(recorder.endRecordingAsPicture());

  return picture;
}

size_t DisplayListRasterSource::GetPictureMemoryUsage() const {
  if (!display_list_)
    return 0;
  return display_list_->ApproximateMemoryUsage() +
         painter_reported_memory_usage_;
}

bool DisplayListRasterSource::PerformSolidColorAnalysis(
    const gfx::Rect& content_rect,
    float contents_scale,
    SkColor* color) const {
  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);
  return canvas.GetColorIfSolid(color);
}

void DisplayListRasterSource::GetDiscardableImagesInRect(
    const gfx::Rect& layer_rect,
    float raster_scale,
    std::vector<DrawImage>* images) const {
  DCHECK_EQ(0u, images->size());
  display_list_->GetDiscardableImagesInRect(layer_rect, raster_scale, images);
}

bool DisplayListRasterSource::HasDiscardableImageInRect(
    const gfx::Rect& layer_rect) const {
  return display_list_ && display_list_->HasDiscardableImageInRect(layer_rect);
}

bool DisplayListRasterSource::CoversRect(const gfx::Rect& layer_rect) const {
  if (size_.IsEmpty())
    return false;
  gfx::Rect bounded_rect = layer_rect;
  bounded_rect.Intersect(gfx::Rect(size_));
  return recorded_viewport_.Contains(bounded_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();
}

gfx::Rect DisplayListRasterSource::RecordedViewport() const {
  return recorded_viewport_;
}

void DisplayListRasterSource::SetShouldAttemptToUseDistanceFieldText() {
  should_attempt_to_use_distance_field_text_ = true;
}

bool DisplayListRasterSource::ShouldAttemptToUseDistanceFieldText() const {
  return should_attempt_to_use_distance_field_text_;
}

void DisplayListRasterSource::AsValueInto(
    base::trace_event::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_;
}

scoped_refptr<DisplayListRasterSource>
DisplayListRasterSource::CreateCloneWithoutLCDText() const {
  bool can_use_lcd_text = false;
  return scoped_refptr<DisplayListRasterSource>(
      new DisplayListRasterSource(this, can_use_lcd_text));
}

void DisplayListRasterSource::SetImageDecodeController(
    ImageDecodeController* image_decode_controller) {
  DCHECK(image_decode_controller);
  // Note that although this function should only be called once, tests tend to
  // call it several times using the same controller.
  DCHECK(!image_decode_controller_ ||
         image_decode_controller_ == image_decode_controller);
  image_decode_controller_ = image_decode_controller;
}

bool DisplayListRasterSource::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  DCHECK(memory_dump_thread_checker_.CalledOnValidThread());

  uint64_t memory_usage = GetPictureMemoryUsage();
  if (memory_usage > 0) {
    std::string dump_name = base::StringPrintf(
        "cc/display_lists/display_list_raster_source_%p", this);
    base::trace_event::MemoryAllocatorDump* dump =
        pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                    base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                    memory_usage);
  }
  return true;
}

}  // namespace cc
