// Copyright 2012 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/layers/heads_up_display_layer_impl.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <vector>

#include "base/memory/shared_memory_mapping.h"
#include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "cc/debug/debug_colors.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_shader.h"
#include "cc/paint/record_paint_canvas.h"
#include "cc/paint/skia_paint_canvas.h"
#include "cc/raster/scoped_gpu_raster.h"
#include "cc/resources/memory_history.h"
#include "cc/trees/frame_rate_counter.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/platform_color.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/shared_image_trace_utils.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/config/gpu_feature_info.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkFont.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gl/trace_util.h"

namespace cc {

namespace {

void DrawArc(PaintCanvas* canvas,
             const SkRect& oval,
             SkScalar start_angle,
             SkScalar sweep_angle,
             const PaintFlags& flags) {
  DCHECK_GT(sweep_angle, 0.f);
  DCHECK_LT(sweep_angle, 360.f);
  SkPath path;
  path.moveTo(oval.centerX(), oval.centerY());
  path.arcTo(oval, start_angle, sweep_angle, false /* forceMoveTo */);
  path.close();
  canvas->drawPath(path, flags);
}

class DummyImageProvider : public ImageProvider {
 public:
  DummyImageProvider() = default;
  ~DummyImageProvider() override = default;
  ImageProvider::ScopedResult GetRasterContent(
      const DrawImage& draw_image) override {
    NOTREACHED();
    return ScopedResult();
  }
};

}  // namespace

HeadsUpDisplayLayerImpl::Graph::Graph(double indicator_value,
                                      double start_upper_bound)
    : value(0.0),
      min(0.0),
      max(0.0),
      current_upper_bound(start_upper_bound),
      default_upper_bound(start_upper_bound),
      indicator(indicator_value) {}

double HeadsUpDisplayLayerImpl::Graph::UpdateUpperBound() {
  double target_upper_bound = std::max(max, default_upper_bound);
  current_upper_bound += (target_upper_bound - current_upper_bound) * 0.5;
  return current_upper_bound;
}

HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
                                                 int id)
    : LayerImpl(tree_impl, id),
      internal_contents_scale_(1.f),
      fps_graph_(60.0, 80.0),
      paint_time_graph_(16.0, 48.0) {}

HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {
  ReleaseResources();
}

std::unique_ptr<LayerImpl> HeadsUpDisplayLayerImpl::CreateLayerImpl(
    LayerTreeImpl* tree_impl) {
  return HeadsUpDisplayLayerImpl::Create(tree_impl, id());
}

class HudGpuBacking : public ResourcePool::GpuBacking {
 public:
  ~HudGpuBacking() override {
    if (mailbox.IsZero())
      return;
    if (returned_sync_token.HasData())
      shared_image_interface->DestroySharedImage(returned_sync_token, mailbox);
    else if (mailbox_sync_token.HasData())
      shared_image_interface->DestroySharedImage(mailbox_sync_token, mailbox);
  }

  void OnMemoryDump(
      base::trace_event::ProcessMemoryDump* pmd,
      const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
      uint64_t tracing_process_id,
      int importance) const override {
    if (mailbox.IsZero())
      return;

    auto tracing_guid = gpu::GetSharedImageGUIDForTracing(mailbox);
    pmd->CreateSharedGlobalAllocatorDump(tracing_guid);
    pmd->AddOwnershipEdge(buffer_dump_guid, tracing_guid, importance);
  }

  gpu::SharedImageInterface* shared_image_interface = nullptr;
};

class HudSoftwareBacking : public ResourcePool::SoftwareBacking {
 public:
  ~HudSoftwareBacking() override {
    layer_tree_frame_sink->DidDeleteSharedBitmap(shared_bitmap_id);
  }

  void OnMemoryDump(
      base::trace_event::ProcessMemoryDump* pmd,
      const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
      uint64_t tracing_process_id,
      int importance) const override {
    pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid,
                                         shared_mapping.guid(), importance);
  }

  LayerTreeFrameSink* layer_tree_frame_sink;
  base::WritableSharedMemoryMapping shared_mapping;
};

bool HeadsUpDisplayLayerImpl::WillDraw(
    DrawMode draw_mode,
    viz::ClientResourceProvider* resource_provider) {
  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE &&
      !LayerImpl::WillDraw(draw_mode, resource_provider)) {
    return false;
  }

  int max_texture_size = layer_tree_impl()->max_texture_size();
  internal_contents_scale_ = GetIdealContentsScale();
  internal_content_bounds_ =
      gfx::ScaleToCeiledSize(bounds(), internal_contents_scale_);
  internal_content_bounds_.SetToMin(
      gfx::Size(max_texture_size, max_texture_size));

  return true;
}

void HeadsUpDisplayLayerImpl::AppendQuads(viz::RenderPass* render_pass,
                                          AppendQuadsData* append_quads_data) {
  viz::SharedQuadState* shared_quad_state =
      render_pass->CreateAndAppendSharedQuadState();
  PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_,
                                contents_opaque());

  // Appends a dummy quad here, which will be updated later once the resource
  // is ready in UpdateHudTexture(). We don't add a TextureDrawQuad directly
  // because we don't have a ResourceId for it yet, and ValidateQuadResources()
  // would fail. UpdateHudTexture() happens after all quads are appended for all
  // layers.
  gfx::Rect quad_rect(internal_content_bounds_);
  auto* quad = render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
  quad->SetNew(shared_quad_state, quad_rect, quad_rect, SK_ColorTRANSPARENT,
               false);
  ValidateQuadResources(quad);
  current_quad_ = quad;
}

void HeadsUpDisplayLayerImpl::UpdateHudTexture(
    DrawMode draw_mode,
    LayerTreeFrameSink* layer_tree_frame_sink,
    viz::ClientResourceProvider* resource_provider,
    bool gpu_raster,
    const viz::RenderPassList& list) {
  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
    return;

  // Update state that will be drawn.
  UpdateHudContents();

  // TODO(penghuang): Do not use worker_context_provider() when context_provider
  // is changed to RasterContextProvider.
  // https://crbug.com/c/1286950
  auto* raster_context_provider =
      gpu_raster ? layer_tree_frame_sink->worker_context_provider() : nullptr;
  base::Optional<viz::RasterContextProvider::ScopedRasterContextLock> lock;
  bool use_oopr = false;
  if (raster_context_provider) {
    lock.emplace(raster_context_provider);
    use_oopr =
        raster_context_provider->ContextCapabilities().supports_oop_raster;
    if (!use_oopr) {
      raster_context_provider = nullptr;
      lock.reset();
    }
  }

  auto* context_provider = layer_tree_frame_sink->context_provider();
  if (!pool_) {
    scoped_refptr<base::SingleThreadTaskRunner> task_runner =
        layer_tree_impl()->task_runner_provider()->HasImplThread()
            ? layer_tree_impl()->task_runner_provider()->ImplThreadTaskRunner()
            : layer_tree_impl()->task_runner_provider()->MainThreadTaskRunner();
    pool_ = std::make_unique<ResourcePool>(
        resource_provider, context_provider, std::move(task_runner),
        ResourcePool::kDefaultExpirationDelay,
        layer_tree_impl()->settings().disallow_non_exact_resource_reuse);
  }

  // Return ownership of the previous frame's resource to the pool, so we
  // can reuse it once it is not busy in the display compositor. This is safe to
  // do here because the previous frame has been shipped to the display
  // compositor by the time we UpdateHudTexture for the current frame.
  if (in_flight_resource_)
    pool_->ReleaseResource(std::move(in_flight_resource_));

  // Allocate a backing for the resource if needed, either for gpu or software
  // compositing.
  ResourcePool::InUsePoolResource pool_resource;
  if (draw_mode == DRAW_MODE_HARDWARE) {
    DCHECK(raster_context_provider || context_provider);
    const auto& caps = raster_context_provider
                           ? raster_context_provider->ContextCapabilities()
                           : context_provider->ContextCapabilities();
    viz::ResourceFormat format =
        gpu_raster ? viz::PlatformColor::BestSupportedRenderBufferFormat(caps)
                   : viz::PlatformColor::BestSupportedTextureFormat(caps);
    pool_resource = pool_->AcquireResource(internal_content_bounds_, format,
                                           gfx::ColorSpace());

    if (!pool_resource.gpu_backing()) {
      auto backing = std::make_unique<HudGpuBacking>();
      auto* sii = raster_context_provider
                      ? raster_context_provider->SharedImageInterface()
                      : context_provider->SharedImageInterface();
      backing->shared_image_interface = sii;
      backing->InitOverlayCandidateAndTextureTarget(
          pool_resource.format(), caps,
          layer_tree_impl()
              ->settings()
              .resource_settings.use_gpu_memory_buffer_resources);

      uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY;
      if (use_oopr) {
        flags |= gpu::SHARED_IMAGE_USAGE_RASTER |
                 gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
      } else if (gpu_raster) {
        flags |= gpu::SHARED_IMAGE_USAGE_GLES2 |
                 gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
      }
      if (backing->overlay_candidate)
        flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
      backing->mailbox =
          sii->CreateSharedImage(pool_resource.format(), pool_resource.size(),
                                 pool_resource.color_space(), flags);
      if (raster_context_provider) {
        auto* ri = raster_context_provider->RasterInterface();
        ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
      } else {
        auto* gl = context_provider->ContextGL();
        gl->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
      }
      pool_resource.set_gpu_backing(std::move(backing));
    } else if (pool_resource.gpu_backing()->returned_sync_token.HasData()) {
      if (raster_context_provider) {
        auto* ri = raster_context_provider->RasterInterface();
        ri->WaitSyncTokenCHROMIUM(
            pool_resource.gpu_backing()->returned_sync_token.GetConstData());
      } else {
        auto* gl = context_provider->ContextGL();
        gl->WaitSyncTokenCHROMIUM(
            pool_resource.gpu_backing()->returned_sync_token.GetConstData());
      }
      pool_resource.gpu_backing()->returned_sync_token = gpu::SyncToken();
    }
  } else {
    DCHECK_EQ(draw_mode, DRAW_MODE_SOFTWARE);

    pool_resource = pool_->AcquireResource(internal_content_bounds_,
                                           viz::RGBA_8888, gfx::ColorSpace());

    if (!pool_resource.software_backing()) {
      auto backing = std::make_unique<HudSoftwareBacking>();
      backing->layer_tree_frame_sink = layer_tree_frame_sink;
      backing->shared_bitmap_id = viz::SharedBitmap::GenerateId();
      base::MappedReadOnlyRegion shm =
          viz::bitmap_allocation::AllocateSharedBitmap(pool_resource.size(),
                                                       pool_resource.format());
      backing->shared_mapping = std::move(shm.mapping);

      layer_tree_frame_sink->DidAllocateSharedBitmap(std::move(shm.region),
                                                     backing->shared_bitmap_id);

      pool_resource.set_software_backing(std::move(backing));
    }
  }

  if (gpu_raster) {
    // If using |gpu_raster| we DrawHudContents() directly to a gpu texture,
    // which is wrapped in an SkSurface.
    DCHECK_EQ(draw_mode, DRAW_MODE_HARDWARE);
    DCHECK(pool_resource.gpu_backing());
    auto* backing = static_cast<HudGpuBacking*>(pool_resource.gpu_backing());

    if (use_oopr) {
      const auto& size = pool_resource.size();
      auto display_item_list = base::MakeRefCounted<DisplayItemList>(
          DisplayItemList::kTopLevelDisplayItemList);
      RecordPaintCanvas canvas(display_item_list.get(),
                               SkRect::MakeIWH(size.width(), size.height()));
      display_item_list->StartPaint();
      DrawHudContents(&canvas);
      display_item_list->EndPaintOfUnpaired(gfx::Rect(size));
      display_item_list->Finalize();

      auto* ri = raster_context_provider->RasterInterface();
      constexpr GLuint background_color = SkColorSetARGB(0, 0, 0, 0);
      constexpr GLuint msaa_sample_count = -1;
      constexpr bool can_use_lcd_text = true;
      ri->BeginRasterCHROMIUM(background_color, msaa_sample_count,
                              can_use_lcd_text, gfx::ColorSpace::CreateSRGB(),
                              backing->mailbox.name);
      gfx::Vector2dF post_translate(0.f, 0.f);
      DummyImageProvider image_provider;
      size_t max_op_size_limit =
          gpu::raster::RasterInterface::kDefaultMaxOpSizeHint;
      ri->RasterCHROMIUM(display_item_list.get(), &image_provider, size,
                         gfx::Rect(size), gfx::Rect(size), post_translate,
                         1.f /* post_scale */, false /* requires_clear */,
                         &max_op_size_limit);
      ri->EndRasterCHROMIUM();
      backing->mailbox_sync_token =
          viz::ClientResourceProvider::GenerateSyncTokenHelper(ri);
    } else {
      auto* gl = context_provider->ContextGL();
      GLuint mailbox_texture_id =
          gl->CreateAndTexStorage2DSharedImageCHROMIUM(backing->mailbox.name);
      gl->BeginSharedImageAccessDirectCHROMIUM(
          mailbox_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);

      {
        ScopedGpuRaster scoped_gpu_raster(context_provider);
        viz::ClientResourceProvider::ScopedSkSurface scoped_surface(
            context_provider->GrContext(),
            pool_resource.color_space().ToSkColorSpace(), mailbox_texture_id,
            backing->texture_target, pool_resource.size(),
            pool_resource.format(), false /* can_use_lcd_text */,
            0 /* msaa_sample_count */);
        SkSurface* surface = scoped_surface.surface();
        if (!surface) {
          pool_->ReleaseResource(std::move(pool_resource));
          return;
        }
        SkiaPaintCanvas canvas(surface->getCanvas());
        DrawHudContents(&canvas);
      }

      gl->EndSharedImageAccessDirectCHROMIUM(mailbox_texture_id);
      gl->DeleteTextures(1, &mailbox_texture_id);
      backing->mailbox_sync_token =
          viz::ClientResourceProvider::GenerateSyncTokenHelper(gl);
    }
  } else if (draw_mode == DRAW_MODE_HARDWARE) {
    // If not using |gpu_raster| but using gpu compositing, we DrawHudContents()
    // into a software bitmap and upload it to a texture for compositing.
    DCHECK(pool_resource.gpu_backing());
    auto* backing = static_cast<HudGpuBacking*>(pool_resource.gpu_backing());
    gpu::gles2::GLES2Interface* gl =
        layer_tree_impl()->context_provider()->ContextGL();

    if (!staging_surface_ ||
        gfx::SkISizeToSize(staging_surface_->getCanvas()->getBaseLayerSize()) !=
            pool_resource.size()) {
      staging_surface_ = SkSurface::MakeRasterN32Premul(
          pool_resource.size().width(), pool_resource.size().height());
    }

    SkiaPaintCanvas canvas(staging_surface_->getCanvas());
    DrawHudContents(&canvas);

    TRACE_EVENT0("cc", "UploadHudTexture");
    SkPixmap pixmap;
    staging_surface_->peekPixels(&pixmap);

    GLuint mailbox_texture_id =
        gl->CreateAndTexStorage2DSharedImageCHROMIUM(backing->mailbox.name);
    gl->BeginSharedImageAccessDirectCHROMIUM(
        mailbox_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);

    gl->BindTexture(backing->texture_target, mailbox_texture_id);
    DCHECK(GLSupportsFormat(pool_resource.format()));
    // We should use gl compatible format for skia SW rasterization.
    constexpr GLenum format = SK_B32_SHIFT ? GL_RGBA : GL_BGRA_EXT;
    constexpr GLenum type = GL_UNSIGNED_BYTE;
    gl->TexSubImage2D(
        backing->texture_target, 0, 0, 0, pool_resource.size().width(),
        pool_resource.size().height(), format, type, pixmap.addr());

    gl->EndSharedImageAccessDirectCHROMIUM(mailbox_texture_id);
    gl->DeleteTextures(1, &mailbox_texture_id);
    backing->mailbox_sync_token =
        viz::ClientResourceProvider::GenerateSyncTokenHelper(gl);
  } else {
    // If not using gpu compositing, we DrawHudContents() directly into a shared
    // memory bitmap, wrapped in an SkSurface, that can be shared to the display
    // compositor.
    DCHECK_EQ(draw_mode, DRAW_MODE_SOFTWARE);
    DCHECK(pool_resource.software_backing());

    SkImageInfo info = SkImageInfo::MakeN32Premul(
        pool_resource.size().width(), pool_resource.size().height());
    auto* backing =
        static_cast<HudSoftwareBacking*>(pool_resource.software_backing());
    sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(
        info, backing->shared_mapping.memory(), info.minRowBytes());

    SkiaPaintCanvas canvas(surface->getCanvas());
    DrawHudContents(&canvas);
  }

  // Exports the backing to the ResourceProvider, giving it a ResourceId that
  // can be used in a DrawQuad.
  bool exported = pool_->PrepareForExport(pool_resource);
  DCHECK(exported);
  viz::ResourceId resource_id = pool_resource.resource_id_for_export();

  // Save the resource to prevent reuse until it is exported to the display
  // compositor. Next time we come here, we can release it back to the pool as
  // it will be exported by then.
  in_flight_resource_ = std::move(pool_resource);

  // This iterates over the RenderPass list of quads to find the HUD quad, which
  // will always be in the root RenderPass.
  auto& render_pass = list.back();
  for (auto it = render_pass->quad_list.begin();
       it != render_pass->quad_list.end(); ++it) {
    if (*it == current_quad_) {
      const viz::SharedQuadState* sqs = current_quad_->shared_quad_state;
      gfx::Rect quad_rect = current_quad_->rect;
      gfx::Rect visible_rect = current_quad_->visible_rect;
      current_quad_ = nullptr;

      auto* quad =
          render_pass->quad_list.ReplaceExistingElement<viz::TextureDrawQuad>(
              it);

      const float vertex_opacity[] = {1.f, 1.f, 1.f, 1.f};
      quad->SetNew(sqs, quad_rect, visible_rect, /*needs_blending=*/true,
                   resource_id, /*premultiplied_alpha=*/true,
                   /*uv_top_left=*/gfx::PointF(),
                   /*uv_bottom_right=*/gfx::PointF(1.f, 1.f),
                   /*background_color=*/SK_ColorTRANSPARENT, vertex_opacity,
                   /*flipped=*/false,
                   /*nearest_neighbor=*/false, /*secure_output_only=*/false,
                   gfx::ProtectedVideoType::kClear);
      ValidateQuadResources(quad);
      break;
    }
  }
  // If this fails, we didn't find |current_quad_| in the root RenderPass, so we
  // didn't append it for the frame (why are we here then?), or it landed in
  // some other RenderPass, both of which are unexpected.
  DCHECK(!current_quad_);
}

void HeadsUpDisplayLayerImpl::ReleaseResources() {
  if (in_flight_resource_)
    pool_->ReleaseResource(std::move(in_flight_resource_));
  pool_.reset();
}

gfx::Rect HeadsUpDisplayLayerImpl::GetEnclosingRectInTargetSpace() const {
  DCHECK_GT(internal_contents_scale_, 0.f);
  return GetScaledEnclosingRectInTargetSpace(internal_contents_scale_);
}

void HeadsUpDisplayLayerImpl::SetHUDTypeface(sk_sp<SkTypeface> typeface) {
  if (typeface_ == typeface)
    return;

  DCHECK(typeface_.get() == nullptr);
  typeface_ = std::move(typeface);
  NoteLayerPropertyChanged();
}

const std::vector<gfx::Rect>& HeadsUpDisplayLayerImpl::LayoutShiftRects()
    const {
  return layout_shift_rects_;
}

void HeadsUpDisplayLayerImpl::SetLayoutShiftRects(
    const std::vector<gfx::Rect>& rects) {
  layout_shift_rects_ = rects;
}

void HeadsUpDisplayLayerImpl::PushPropertiesTo(LayerImpl* layer) {
  LayerImpl::PushPropertiesTo(layer);

  HeadsUpDisplayLayerImpl* layer_impl =
      static_cast<HeadsUpDisplayLayerImpl*>(layer);

  layer_impl->SetHUDTypeface(typeface_);
  layer_impl->SetLayoutShiftRects(layout_shift_rects_);
  layout_shift_rects_.clear();
}

void HeadsUpDisplayLayerImpl::UpdateHudContents() {
  const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();

  // Don't update numbers every frame so text is readable.
  base::TimeTicks now = layer_tree_impl()->CurrentBeginFrameArgs().frame_time;
  if (base::TimeDelta(now - time_of_last_graph_update_).InSecondsF() > 0.25f) {
    time_of_last_graph_update_ = now;

    if (debug_state.show_fps_counter) {
      FrameRateCounter* fps_counter = layer_tree_impl()->frame_rate_counter();
      fps_graph_.value = fps_counter->GetAverageFPS();
      fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max);
    }

    if (debug_state.ShowMemoryStats()) {
      MemoryHistory* memory_history = layer_tree_impl()->memory_history();
      if (memory_history->End())
        memory_entry_ = **memory_history->End();
      else
        memory_entry_ = MemoryHistory::Entry();
    }
  }

  fps_graph_.UpdateUpperBound();
  paint_time_graph_.UpdateUpperBound();
}

void HeadsUpDisplayLayerImpl::DrawHudContents(PaintCanvas* canvas) {
  const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();

  TRACE_EVENT0("cc", "DrawHudContents");
  canvas->clear(SkColorSetARGB(0, 0, 0, 0));
  canvas->save();
  canvas->scale(internal_contents_scale_, internal_contents_scale_);

  if (debug_state.ShowHudRects()) {
    DrawDebugRects(canvas, layer_tree_impl()->debug_rect_history());
    if (IsAnimatingHUDContents()) {
      layer_tree_impl()->SetNeedsRedraw();
    }
  }

  if (!debug_state.show_fps_counter) {
    canvas->restore();
    return;
  }

  SkRect area =
      DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0);
  area = DrawGpuRasterizationStatus(canvas, 0, area.bottom(),
                                    std::max<SkScalar>(area.width(), 150));

  if (debug_state.ShowMemoryStats() && memory_entry_.total_bytes_used)
    DrawMemoryDisplay(canvas, 0, area.bottom(),
                      std::max<SkScalar>(area.width(), 150));

  canvas->restore();
}

void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas,
                                       const PaintFlags& flags,
                                       const std::string& text,
                                       TextAlign align,
                                       int size,
                                       int x,
                                       int y) const {
  DCHECK(typeface_.get());
  SkFont font(typeface_, size);
  font.setEdging(SkFont::Edging::kAntiAlias);

  if (align == TextAlign::kCenter) {
    auto width =
        font.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
    x -= width * 0.5f;
  } else if (align == TextAlign::kRight) {
    auto width =
        font.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
    x -= width;
  }

  canvas->drawTextBlob(
      SkTextBlob::MakeFromText(text.c_str(), text.length(), font), x, y, flags);
}

void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas,
                                       const PaintFlags& flags,
                                       const std::string& text,
                                       TextAlign align,
                                       int size,
                                       const SkPoint& pos) const {
  DrawText(canvas, flags, text, align, size, pos.x(), pos.y());
}

void HeadsUpDisplayLayerImpl::DrawGraphBackground(PaintCanvas* canvas,
                                                  PaintFlags* flags,
                                                  const SkRect& bounds) const {
  flags->setColor(DebugColors::HUDBackgroundColor());
  canvas->drawRect(bounds, *flags);
}

void HeadsUpDisplayLayerImpl::DrawGraphLines(PaintCanvas* canvas,
                                             PaintFlags* flags,
                                             const SkRect& bounds,
                                             const Graph& graph) const {
  // Draw top and bottom line.
  flags->setColor(DebugColors::HUDSeparatorLineColor());
  canvas->drawLine(bounds.left(), bounds.top() - 1, bounds.right(),
                   bounds.top() - 1, *flags);
  canvas->drawLine(bounds.left(), bounds.bottom(), bounds.right(),
                   bounds.bottom(), *flags);

  // Draw indicator line (additive blend mode to increase contrast when drawn on
  // top of graph).
  flags->setColor(DebugColors::HUDIndicatorLineColor());
  flags->setBlendMode(SkBlendMode::kPlus);
  const double indicator_top =
      bounds.height() * (1.0 - graph.indicator / graph.current_upper_bound) -
      1.0;
  canvas->drawLine(bounds.left(), bounds.top() + indicator_top, bounds.right(),
                   bounds.top() + indicator_top, *flags);
  flags->setBlendMode(SkBlendMode::kSrcOver);
}

SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
    PaintCanvas* canvas,
    const FrameRateCounter* fps_counter,
    int right,
    int top) const {
  const int kPadding = 4;
  const int kGap = 6;

  const int kTitleFontHeight = 13;
  const int kFontHeight = 12;

  const int kGraphWidth =
      base::saturated_cast<int>(fps_counter->time_stamp_history_size()) - 2;
  const int kGraphHeight = 40;

  const int kHistogramWidth = 37;

  int width = kGraphWidth + kHistogramWidth + 4 * kPadding;
  int height = kTitleFontHeight + kFontHeight + kGraphHeight + 6 * kPadding + 2;
  int left = 0;
  SkRect area = SkRect::MakeXYWH(left, top, width, height);

  PaintFlags flags;
  DrawGraphBackground(canvas, &flags, area);

  SkRect title_bounds = SkRect::MakeXYWH(
      left + kPadding, top + kPadding, kGraphWidth + kHistogramWidth + kGap + 2,
      kTitleFontHeight);
  SkRect text_bounds =
      SkRect::MakeXYWH(left + kPadding, title_bounds.bottom() + 2 * kPadding,
                       kGraphWidth + kHistogramWidth + kGap + 2, kFontHeight);
  SkRect graph_bounds =
      SkRect::MakeXYWH(left + kPadding, text_bounds.bottom() + 2 * kPadding,
                       kGraphWidth, kGraphHeight);
  SkRect histogram_bounds =
      SkRect::MakeXYWH(graph_bounds.right() + kGap, graph_bounds.top(),
                       kHistogramWidth, kGraphHeight);

  const std::string title("Frame Rate");
  const std::string value_text =
      base::StringPrintf("%5.1f fps", fps_graph_.value);
  const std::string min_max_text =
      base::StringPrintf("%.0f-%.0f", fps_graph_.min, fps_graph_.max);

  VLOG(1) << value_text;

  flags.setColor(DebugColors::HUDTitleColor());
  DrawText(canvas, flags, title, TextAlign::kLeft, kTitleFontHeight,
           title_bounds.left(), title_bounds.bottom());

  flags.setColor(DebugColors::FPSDisplayTextAndGraphColor());
  DrawText(canvas, flags, value_text, TextAlign::kLeft, kFontHeight,
           text_bounds.left(), text_bounds.bottom());
  DrawText(canvas, flags, min_max_text, TextAlign::kRight, kFontHeight,
           text_bounds.right(), text_bounds.bottom());

  DrawGraphLines(canvas, &flags, graph_bounds, fps_graph_);

  // Collect graph and histogram data.
  SkPath path;

  const int kHistogramSize = 20;
  double histogram[kHistogramSize] = {1.0};
  double max_bucket_value = 1.0;

  for (FrameRateCounter::RingBufferType::Iterator it = --fps_counter->end(); it;
       --it) {
    base::TimeDelta delta = fps_counter->RecentFrameInterval(it.index() + 1);

    // Skip this particular instantaneous frame rate if it is not likely to have
    // been valid.
    if (!fps_counter->IsBadFrameInterval(delta)) {
      double fps = 1.0 / delta.InSecondsF();

      // Clamp the FPS to the range we want to plot visually.
      double p = fps / fps_graph_.current_upper_bound;
      if (p > 1.0)
        p = 1.0;

      // Plot this data point.
      SkPoint cur =
          SkPoint::Make(graph_bounds.left() + it.index(),
                        graph_bounds.bottom() - p * graph_bounds.height());
      if (path.isEmpty())
        path.moveTo(cur);
      else
        path.lineTo(cur);

      // Use the fps value to find the right bucket in the histogram.
      int bucket_index = floor(p * (kHistogramSize - 1));

      // Add the delta time to take the time spent at that fps rate into
      // account.
      histogram[bucket_index] += delta.InSecondsF();
      max_bucket_value = std::max(histogram[bucket_index], max_bucket_value);
    }
  }

  // Draw FPS histogram.
  flags.setColor(DebugColors::HUDSeparatorLineColor());
  canvas->drawLine(histogram_bounds.left() - 1, histogram_bounds.top() - 1,
                   histogram_bounds.left() - 1, histogram_bounds.bottom() + 1,
                   flags);
  canvas->drawLine(histogram_bounds.right() + 1, histogram_bounds.top() - 1,
                   histogram_bounds.right() + 1, histogram_bounds.bottom() + 1,
                   flags);

  flags.setColor(DebugColors::FPSDisplayTextAndGraphColor());
  const double bar_height = histogram_bounds.height() / kHistogramSize;

  for (int i = kHistogramSize - 1; i >= 0; --i) {
    if (histogram[i] > 0) {
      double bar_width =
          histogram[i] / max_bucket_value * histogram_bounds.width();
      canvas->drawRect(
          SkRect::MakeXYWH(histogram_bounds.left(),
                           histogram_bounds.bottom() - (i + 1) * bar_height,
                           bar_width, 1),
          flags);
    }
  }

  // Draw FPS graph.
  flags.setAntiAlias(true);
  flags.setStyle(PaintFlags::kStroke_Style);
  flags.setStrokeWidth(1);
  canvas->drawPath(path, flags);

  return area;
}

SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(PaintCanvas* canvas,
                                                  int right,
                                                  int top,
                                                  int width) const {
  const int kPadding = 4;
  const int kTitleFontHeight = 13;
  const int kFontHeight = 12;

  const int height = kTitleFontHeight + 2 * kFontHeight + 5 * kPadding;
  const int left = 0;
  const SkRect area = SkRect::MakeXYWH(left, top, width, height);

  const double kMegabyte = 1024.0 * 1024.0;

  PaintFlags flags;
  DrawGraphBackground(canvas, &flags, area);

  SkPoint title_pos =
      SkPoint::Make(left + kPadding, top + kFontHeight + kPadding);
  SkPoint stat1_pos = SkPoint::Make(left + width - kPadding - 1,
                                    top + kPadding + 2 * kFontHeight);
  SkPoint stat2_pos = SkPoint::Make(left + width - kPadding - 1,
                                    top + 2 * kPadding + 3 * kFontHeight);

  flags.setColor(DebugColors::HUDTitleColor());
  DrawText(canvas, flags, "GPU Memory", TextAlign::kLeft, kTitleFontHeight,
           title_pos);

  flags.setColor(DebugColors::MemoryDisplayTextColor());
  std::string text = base::StringPrintf(
      "%6.1f MB used", memory_entry_.total_bytes_used / kMegabyte);
  DrawText(canvas, flags, text, TextAlign::kRight, kFontHeight, stat1_pos);

  if (!memory_entry_.had_enough_memory)
    flags.setColor(SK_ColorRED);
  text = base::StringPrintf("%6.1f MB max ",
                            memory_entry_.total_budget_in_bytes / kMegabyte);

  DrawText(canvas, flags, text, TextAlign::kRight, kFontHeight, stat2_pos);

  // Draw memory graph.
  int length = 2 * kFontHeight + kPadding + 12;
  SkRect oval =
      SkRect::MakeXYWH(left + kPadding * 6,
                       top + kTitleFontHeight + kPadding * 3, length, length);
  flags.setAntiAlias(true);
  flags.setStyle(PaintFlags::kFill_Style);

  flags.setColor(SkColorSetARGB(64, 255, 255, 0));
  DrawArc(canvas, oval, 180, 180, flags);

  int radius = length / 2;
  int cx = oval.left() + radius;
  int cy = oval.top() + radius;
  double angle = ((double)memory_entry_.total_bytes_used /
                  memory_entry_.total_budget_in_bytes) *
                 180;

  SkColor colors[] = {SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN,
                      SkColorSetARGB(255, 255, 140, 0), SK_ColorRED};
  const SkScalar pos[] = {SkFloatToScalar(0.2f), SkFloatToScalar(0.4f),
                          SkFloatToScalar(0.6f), SkFloatToScalar(0.8f),
                          SkFloatToScalar(1.0f)};
  flags.setShader(PaintShader::MakeSweepGradient(cx, cy, colors, pos, 5,
                                                 SkTileMode::kClamp, 0, 360));
  flags.setAntiAlias(true);

  // Draw current status.
  flags.setStyle(PaintFlags::kStroke_Style);
  flags.setAlpha(32);
  flags.setStrokeWidth(4);
  DrawArc(canvas, oval, 180, angle, flags);

  flags.setStyle(PaintFlags::kFill_Style);
  flags.setColor(SkColorSetARGB(255, 0, 255, 0));
  DrawArc(canvas, oval, 180, angle, flags);
  flags.setShader(nullptr);

  return area;
}

SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(PaintCanvas* canvas,
                                                           int right,
                                                           int top,
                                                           int width) const {
  std::string status;
  SkColor color = SK_ColorRED;
  switch (layer_tree_impl()->GetGpuRasterizationStatus()) {
    case GpuRasterizationStatus::ON:
      status = "on";
      color = SK_ColorGREEN;
      break;
    case GpuRasterizationStatus::ON_FORCED:
      status = "on (forced)";
      color = SK_ColorGREEN;
      break;
    case GpuRasterizationStatus::OFF_DEVICE:
      status = "off (device)";
      color = SK_ColorRED;
      break;
  }

  if (status.empty())
    return SkRect::MakeEmpty();

  const int kPadding = 4;
  const int kTitleFontHeight = 13;
  const int kFontHeight = 12;

  const int height = kTitleFontHeight + kFontHeight + 3 * kPadding;
  const int left = 0;
  const SkRect area = SkRect::MakeXYWH(left, top, width, height);

  PaintFlags flags;
  DrawGraphBackground(canvas, &flags, area);

  SkPoint gpu_status_pos = SkPoint::Make(left + width - kPadding,
                                         top + 2 * kFontHeight + 2 * kPadding);
  flags.setColor(DebugColors::HUDTitleColor());
  DrawText(canvas, flags, "GPU Raster", TextAlign::kLeft, kTitleFontHeight,
           left + kPadding, top + kFontHeight + kPadding);
  flags.setColor(color);
  DrawText(canvas, flags, status, TextAlign::kRight, kFontHeight,
           gpu_status_pos);

  return area;
}

void HeadsUpDisplayLayerImpl::DrawDebugRect(
    PaintCanvas* canvas,
    PaintFlags* flags,
    const DebugRect& rect,
    SkColor stroke_color,
    SkColor fill_color,
    float stroke_width,
    const std::string& label_text) const {
  DCHECK(typeface_.get());
  gfx::Rect debug_layer_rect =
      gfx::ScaleToEnclosingRect(rect.rect, 1.0 / internal_contents_scale_,
                                1.0 / internal_contents_scale_);
  SkIRect sk_rect = RectToSkIRect(debug_layer_rect);
  flags->setColor(fill_color);
  flags->setStyle(PaintFlags::kFill_Style);
  canvas->drawIRect(sk_rect, *flags);

  flags->setColor(stroke_color);
  flags->setStyle(PaintFlags::kStroke_Style);
  flags->setStrokeWidth(SkFloatToScalar(stroke_width));
  canvas->drawIRect(sk_rect, *flags);

  if (label_text.length()) {
    const int kFontHeight = 12;
    const int kPadding = 3;

    // The debug_layer_rect may be huge, and converting to a floating point may
    // be lossy, so intersect with the HUD layer bounds first to prevent that.
    gfx::Rect clip_rect = debug_layer_rect;
    clip_rect.Intersect(gfx::Rect(internal_content_bounds_));
    SkRect sk_clip_rect = RectToSkRect(clip_rect);

    canvas->save();
    canvas->clipRect(sk_clip_rect);
    canvas->translate(sk_clip_rect.x(), sk_clip_rect.y());

    PaintFlags label_flags;
    label_flags.setColor(stroke_color);
    SkFont label_font(typeface_, kFontHeight);

    const SkScalar label_text_width = label_font.measureText(
        label_text.c_str(), label_text.length(), SkTextEncoding::kUTF8);
    canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding,
                                    kFontHeight + 2 * kPadding),
                     label_flags);

    label_flags.setColor(SkColorSetARGB(255, 50, 50, 50));
    DrawText(canvas, label_flags, label_text, TextAlign::kLeft, kFontHeight,
             kPadding, kFontHeight * 0.8f + kPadding);
    canvas->restore();
  }
}

void HeadsUpDisplayLayerImpl::DrawDebugRects(
    PaintCanvas* canvas,
    DebugRectHistory* debug_rect_history) {
  PaintFlags flags;

  const std::vector<DebugRect>& debug_rects = debug_rect_history->debug_rects();
  std::vector<DebugRect> new_paint_rects;
  std::vector<DebugRect> new_layout_shift_rects;

  for (size_t i = 0; i < debug_rects.size(); ++i) {
    SkColor stroke_color = 0;
    SkColor fill_color = 0;
    float stroke_width = 0.f;
    std::string label_text;

    switch (debug_rects[i].type) {
      case LAYOUT_SHIFT_RECT_TYPE:
        new_layout_shift_rects.push_back(debug_rects[i]);
        continue;
      case PAINT_RECT_TYPE:
        new_paint_rects.push_back(debug_rects[i]);
        continue;
      case PROPERTY_CHANGED_RECT_TYPE:
        stroke_color = DebugColors::PropertyChangedRectBorderColor();
        fill_color = DebugColors::PropertyChangedRectFillColor();
        stroke_width = DebugColors::PropertyChangedRectBorderWidth();
        break;
      case SURFACE_DAMAGE_RECT_TYPE:
        stroke_color = DebugColors::SurfaceDamageRectBorderColor();
        fill_color = DebugColors::SurfaceDamageRectFillColor();
        stroke_width = DebugColors::SurfaceDamageRectBorderWidth();
        break;
      case SCREEN_SPACE_RECT_TYPE:
        stroke_color = DebugColors::ScreenSpaceLayerRectBorderColor();
        fill_color = DebugColors::ScreenSpaceLayerRectFillColor();
        stroke_width = DebugColors::ScreenSpaceLayerRectBorderWidth();
        break;
      case TOUCH_EVENT_HANDLER_RECT_TYPE:
        stroke_color = DebugColors::TouchEventHandlerRectBorderColor();
        fill_color = DebugColors::TouchEventHandlerRectFillColor();
        stroke_width = DebugColors::TouchEventHandlerRectBorderWidth();
        label_text = "touch event listener: ";
        label_text.append(TouchActionToString(debug_rects[i].touch_action));
        break;
      case WHEEL_EVENT_HANDLER_RECT_TYPE:
        stroke_color = DebugColors::WheelEventHandlerRectBorderColor();
        fill_color = DebugColors::WheelEventHandlerRectFillColor();
        stroke_width = DebugColors::WheelEventHandlerRectBorderWidth();
        label_text = "mousewheel event listener";
        break;
      case SCROLL_EVENT_HANDLER_RECT_TYPE:
        stroke_color = DebugColors::ScrollEventHandlerRectBorderColor();
        fill_color = DebugColors::ScrollEventHandlerRectFillColor();
        stroke_width = DebugColors::ScrollEventHandlerRectBorderWidth();
        label_text = "scroll event listener";
        break;
      case NON_FAST_SCROLLABLE_RECT_TYPE:
        stroke_color = DebugColors::NonFastScrollableRectBorderColor();
        fill_color = DebugColors::NonFastScrollableRectFillColor();
        stroke_width = DebugColors::NonFastScrollableRectBorderWidth();
        label_text = "repaints on scroll";
        break;
      case MAIN_THREAD_SCROLLING_REASON_RECT_TYPE:
        stroke_color = DebugColors::MainThreadScrollingReasonRectBorderColor();
        fill_color = DebugColors::MainThreadScrollingReasonRectFillColor();
        stroke_width = DebugColors::MainThreadScrollingReasonRectBorderWidth();
        label_text = "main thread scrolling: ";
        label_text.append(base::ToLowerASCII(MainThreadScrollingReason::AsText(
            debug_rects[i].main_thread_scrolling_reasons)));
        break;
      case ANIMATION_BOUNDS_RECT_TYPE:
        stroke_color = DebugColors::LayerAnimationBoundsBorderColor();
        fill_color = DebugColors::LayerAnimationBoundsFillColor();
        stroke_width = DebugColors::LayerAnimationBoundsBorderWidth();
        label_text = "animation bounds";
        break;
    }

    DrawDebugRect(canvas, &flags, debug_rects[i], stroke_color, fill_color,
                  stroke_width, label_text);
  }

  if (new_paint_rects.size()) {
    paint_rects_.swap(new_paint_rects);
    paint_rects_fade_step_ = DebugColors::kFadeSteps;
  }
  if (paint_rects_fade_step_ > 0) {
    paint_rects_fade_step_--;
    for (size_t i = 0; i < paint_rects_.size(); ++i) {
      DrawDebugRect(canvas, &flags, paint_rects_[i],
                    DebugColors::PaintRectBorderColor(paint_rects_fade_step_),
                    DebugColors::PaintRectFillColor(paint_rects_fade_step_),
                    DebugColors::PaintRectBorderWidth(), "");
    }
  }

  if (new_layout_shift_rects.size()) {
    layout_shift_debug_rects_.swap(new_layout_shift_rects);
    layout_shift_rects_fade_step_ = DebugColors::kFadeSteps;
  }
  if (layout_shift_rects_fade_step_ > 0) {
    layout_shift_rects_fade_step_--;
    for (size_t i = 0; i < layout_shift_debug_rects_.size(); ++i) {
      DrawDebugRect(
          canvas, &flags, layout_shift_debug_rects_[i],
          DebugColors::LayoutShiftRectBorderColor(),
          DebugColors::LayoutShiftRectFillColor(layout_shift_rects_fade_step_),
          DebugColors::LayoutShiftRectBorderWidth(), "");
    }
  }
}

const char* HeadsUpDisplayLayerImpl::LayerTypeAsString() const {
  return "cc::HeadsUpDisplayLayerImpl";
}

void HeadsUpDisplayLayerImpl::AsValueInto(
    base::trace_event::TracedValue* dict) const {
  LayerImpl::AsValueInto(dict);
  dict->SetString("layer_name", "Heads Up Display Layer");
}

}  // namespace cc
