// 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/raster/gpu_raster_buffer_provider.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "build/chromeos_buildflags.h"
#include "cc/base/histograms.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_recorder.h"
#include "cc/raster/raster_source.h"
#include "cc/raster/scoped_gpu_raster.h"
#include "cc/raster/scoped_grcontext_access.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/gpu/raster_context_provider.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 "skia/ext/legacy_display_globals.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "url/gurl.h"

namespace cc {
namespace {

static void RasterizeSourceOOP(
    const RasterSource* raster_source,
    bool resource_has_previous_content,
    gpu::Mailbox* mailbox,
    const gpu::SyncToken& sync_token,
    GLenum texture_target,
    bool texture_is_overlay_candidate,
    const gfx::Size& resource_size,
    viz::ResourceFormat resource_format,
    const gfx::ColorSpace& color_space,
    const gfx::Rect& raster_full_rect,
    const gfx::Rect& playback_rect,
    const gfx::AxisTransform2d& transform,
    const RasterSource::PlaybackSettings& playback_settings,
    viz::RasterContextProvider* context_provider,
    bool is_using_raw_draw) {
  gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
  bool mailbox_needs_clear = false;
  if (mailbox->IsZero()) {
    DCHECK(!sync_token.HasData());
    auto* sii = context_provider->SharedImageInterface();
    uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY |
                     gpu::SHARED_IMAGE_USAGE_RASTER |
                     gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
    if (texture_is_overlay_candidate) {
      flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
    } else if (is_using_raw_draw) {
      flags |= gpu::SHARED_IMAGE_USAGE_RAW_DRAW;
    }
    *mailbox = sii->CreateSharedImage(
        resource_format, resource_size, color_space, kTopLeft_GrSurfaceOrigin,
        kPremul_SkAlphaType, flags, gpu::kNullSurfaceHandle);
    mailbox_needs_clear = true;
    ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
  } else {
    ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
  }

  // Assume legacy MSAA if sample count is positive.
  gpu::raster::MsaaMode msaa_mode = playback_settings.msaa_sample_count > 0
                                        ? gpu::raster::kMSAA
                                        : gpu::raster::kNoMSAA;

  // With Raw Draw, the framebuffer will be the rasterization target. It cannot
  // support LCD text, so disable LCD text for Raw Draw backings.
  // TODO(penghuang): remove it when GrSlug can be serialized.
  bool is_raw_draw_backing = is_using_raw_draw && !texture_is_overlay_candidate;
  bool use_lcd_text = playback_settings.use_lcd_text && !is_raw_draw_backing;
  ri->BeginRasterCHROMIUM(raster_source->background_color(),
                          mailbox_needs_clear,
                          playback_settings.msaa_sample_count, msaa_mode,
                          use_lcd_text, color_space, mailbox->name);
  gfx::Vector2dF recording_to_raster_scale = transform.scale();
  recording_to_raster_scale.Scale(1 / raster_source->recording_scale_factor());
  gfx::Size content_size = raster_source->GetContentSize(transform.scale());

  // TODO(enne): could skip the clear on new textures, as the service side has
  // to do that anyway.  resource_has_previous_content implies that the texture
  // is not new, but the reverse does not hold, so more plumbing is needed.
  ri->RasterCHROMIUM(
      raster_source->GetDisplayItemList().get(),
      playback_settings.image_provider, content_size, raster_full_rect,
      playback_rect, transform.translation(), recording_to_raster_scale,
      raster_source->requires_clear(),
      const_cast<RasterSource*>(raster_source)->max_op_size_hint());
  ri->EndRasterCHROMIUM();

  // TODO(ericrk): Handle unpremultiply+dither for 4444 cases.
  // https://crbug.com/789153
}

static void RasterizeSource(
    const RasterSource* raster_source,
    bool resource_has_previous_content,
    gpu::Mailbox* mailbox,
    const gpu::SyncToken& sync_token,
    GLenum texture_target,
    bool texture_is_overlay_candidate,
    const gfx::Size& resource_size,
    viz::ResourceFormat resource_format,
    const gfx::ColorSpace& color_space,
    const gfx::Rect& raster_full_rect,
    const gfx::Rect& playback_rect,
    const gfx::AxisTransform2d& transform,
    const RasterSource::PlaybackSettings& playback_settings,
    viz::RasterContextProvider* context_provider,
    const gfx::Size& max_tile_size) {
  gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
  if (mailbox->IsZero()) {
    auto* sii = context_provider->SharedImageInterface();
    uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY |
                     gpu::SHARED_IMAGE_USAGE_GLES2 |
                     gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
    if (texture_is_overlay_candidate)
      flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
    *mailbox = sii->CreateSharedImage(
        resource_format, resource_size, color_space, kTopLeft_GrSurfaceOrigin,
        kPremul_SkAlphaType, flags, gpu::kNullSurfaceHandle);
    ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
  } else {
    // Wait on the SyncToken that was created on the compositor thread after
    // making the mailbox. This ensures that the mailbox we consume here is
    // valid by the time the consume command executes.
    ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
  }
  GLuint texture_id = ri->CreateAndConsumeForGpuRaster(*mailbox);
  ri->BeginSharedImageAccessDirectCHROMIUM(
      texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
  {
    ScopedGrContextAccess gr_context_access(context_provider);
    SkSurface* surface;
    sk_sp<SkColorSpace> sk_color_space = color_space.ToSkColorSpace();
    viz::ClientResourceProvider::ScopedSkSurface scoped_surface(
        context_provider->GrContext(), sk_color_space, texture_id,
        texture_target, resource_size, resource_format,
        skia::LegacyDisplayGlobals::ComputeSurfaceProps(
            playback_settings.use_lcd_text),
        playback_settings.msaa_sample_count);
    surface = scoped_surface.surface();

    // Allocating an SkSurface will fail after a lost context.  Pretend we
    // rasterized, as the contents of the resource don't matter anymore.
    if (!surface) {
      DLOG(ERROR) << "Failed to allocate raster surface";
      return;
    }

    SkCanvas* canvas = surface->getCanvas();

    // As an optimization, inform Skia to discard when not doing partial raster.
    if (raster_full_rect == playback_rect)
      canvas->discard();

    gfx::Size content_size = raster_source->GetContentSize(transform.scale());
    raster_source->PlaybackToCanvas(canvas, content_size, raster_full_rect,
                                    playback_rect, transform,
                                    playback_settings);
  }
  ri->EndSharedImageAccessDirectCHROMIUM(texture_id);
  ri->DeleteGpuRasterTexture(texture_id);
}

}  // namespace

// Subclass for InUsePoolResource that holds ownership of a gpu-rastered backing
// and does cleanup of the backing when destroyed.
class GpuRasterBufferProvider::GpuRasterBacking
    : public ResourcePool::GpuBacking {
 public:
  ~GpuRasterBacking() override {
    if (mailbox.IsZero())
      return;
    auto* sii = worker_context_provider->SharedImageInterface();
    if (returned_sync_token.HasData())
      sii->DestroySharedImage(returned_sync_token, mailbox);
    else if (mailbox_sync_token.HasData())
      sii->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);
  }

  // The ContextProvider used to clean up the mailbox
  raw_ptr<viz::RasterContextProvider> worker_context_provider = nullptr;
};

GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
    GpuRasterBufferProvider* client,
    const ResourcePool::InUsePoolResource& in_use_resource,
    GpuRasterBacking* backing,
    bool resource_has_previous_content,
    bool depends_on_at_raster_decodes,
    bool depends_on_hardware_accelerated_jpeg_candidates,
    bool depends_on_hardware_accelerated_webp_candidates)
    : client_(client),
      backing_(backing),
      resource_size_(in_use_resource.size()),
      resource_format_(in_use_resource.format()),
      color_space_(in_use_resource.color_space()),
      resource_has_previous_content_(resource_has_previous_content),
      depends_on_at_raster_decodes_(depends_on_at_raster_decodes),
      depends_on_hardware_accelerated_jpeg_candidates_(
          depends_on_hardware_accelerated_jpeg_candidates),
      depends_on_hardware_accelerated_webp_candidates_(
          depends_on_hardware_accelerated_webp_candidates),
      before_raster_sync_token_(backing->returned_sync_token),
      texture_target_(backing->texture_target),
      texture_is_overlay_candidate_(backing->overlay_candidate),
      mailbox_(backing->mailbox) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
  // Only do this in Chrome OS with OOP-R because:
  //   1) We will use this timestamp to measure raster scheduling delay and we
  //      only need to collect that data to assess the impact of hardware
  //      acceleration of image decodes which works only on Chrome OS with
  //      OOP-R.
  //   2) We use CLOCK_MONOTONIC in that OS to get timestamps, so we can assert
  //      certain assumptions.
  if (client_->enable_oop_rasterization_)
    creation_time_ = base::TimeTicks::Now();
#endif
}

GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
  // This SyncToken was created on the worker context after rastering the
  // texture content.
  backing_->mailbox_sync_token = after_raster_sync_token_;
  if (after_raster_sync_token_.HasData()) {
    // The returned SyncToken was waited on in Playback. We know Playback
    // happened if the |after_raster_sync_token_| was set.
    backing_->returned_sync_token = gpu::SyncToken();
  }
  backing_->mailbox = mailbox_;
}

void GpuRasterBufferProvider::RasterBufferImpl::Playback(
    const RasterSource* raster_source,
    const gfx::Rect& raster_full_rect,
    const gfx::Rect& raster_dirty_rect,
    uint64_t new_content_id,
    const gfx::AxisTransform2d& transform,
    const RasterSource::PlaybackSettings& playback_settings,
    const GURL& url) {
  TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
  // The |before_raster_sync_token_| passed in here was created on the
  // compositor thread, or given back with the texture for reuse. This call
  // returns another SyncToken generated on the worker thread to synchronize
  // with after the raster is complete.
  after_raster_sync_token_ = client_->PlaybackOnWorkerThread(
      &mailbox_, texture_target_, texture_is_overlay_candidate_,
      before_raster_sync_token_, resource_size_, resource_format_, color_space_,
      resource_has_previous_content_, raster_source, raster_full_rect,
      raster_dirty_rect, new_content_id, transform, playback_settings, url,
      creation_time_, depends_on_at_raster_decodes_,
      depends_on_hardware_accelerated_jpeg_candidates_,
      depends_on_hardware_accelerated_webp_candidates_);
}

bool GpuRasterBufferProvider::RasterBufferImpl::
    SupportsBackgroundThreadPriority() const {
  return true;
}

GpuRasterBufferProvider::GpuRasterBufferProvider(
    viz::ContextProvider* compositor_context_provider,
    viz::RasterContextProvider* worker_context_provider,
    bool use_gpu_memory_buffer_resources,
    viz::ResourceFormat tile_format,
    const gfx::Size& max_tile_size,
    bool unpremultiply_and_dither_low_bit_depth_tiles,
    bool enable_oop_rasterization,
    RasterQueryQueue* const pending_raster_queries,
    float raster_metric_probability)
    : compositor_context_provider_(compositor_context_provider),
      worker_context_provider_(worker_context_provider),
      use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources),
      tile_format_(tile_format),
      max_tile_size_(max_tile_size),
      enable_oop_rasterization_(enable_oop_rasterization),
      pending_raster_queries_(pending_raster_queries),
      random_generator_(static_cast<uint32_t>(base::RandUint64())),
      bernoulli_distribution_(raster_metric_probability),
      is_using_raw_draw_(features::IsUsingRawDraw()) {
  DCHECK(pending_raster_queries);
  DCHECK(compositor_context_provider);
  DCHECK(worker_context_provider);
}

GpuRasterBufferProvider::~GpuRasterBufferProvider() {
}

std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
    const ResourcePool::InUsePoolResource& resource,
    uint64_t resource_content_id,
    uint64_t previous_content_id,
    bool depends_on_at_raster_decodes,
    bool depends_on_hardware_accelerated_jpeg_candidates,
    bool depends_on_hardware_accelerated_webp_candidates) {
  if (!resource.gpu_backing()) {
    auto backing = std::make_unique<GpuRasterBacking>();
    backing->worker_context_provider = worker_context_provider_;
    backing->InitOverlayCandidateAndTextureTarget(
        resource.format(), compositor_context_provider_->ContextCapabilities(),
        use_gpu_memory_buffer_resources_);
    resource.set_gpu_backing(std::move(backing));
  }
  GpuRasterBacking* backing =
      static_cast<GpuRasterBacking*>(resource.gpu_backing());
  bool resource_has_previous_content =
      resource_content_id && resource_content_id == previous_content_id;
  return std::make_unique<RasterBufferImpl>(
      this, resource, backing, resource_has_previous_content,
      depends_on_at_raster_decodes,
      depends_on_hardware_accelerated_jpeg_candidates,
      depends_on_hardware_accelerated_webp_candidates);
}

void GpuRasterBufferProvider::Flush() {
  compositor_context_provider_->ContextSupport()->FlushPendingWork();
}

viz::ResourceFormat GpuRasterBufferProvider::GetResourceFormat() const {
  return tile_format_;
}

bool GpuRasterBufferProvider::IsResourcePremultiplied() const {
  return !ShouldUnpremultiplyAndDitherResource(GetResourceFormat());
}

bool GpuRasterBufferProvider::IsResourceReadyToDraw(
    const ResourcePool::InUsePoolResource& resource) const {
  const gpu::SyncToken& sync_token = resource.gpu_backing()->mailbox_sync_token;
  // This SyncToken() should have been set by calling OrderingBarrier() before
  // calling this.
  DCHECK(sync_token.HasData());

  // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
  return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
      sync_token);
}

bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
  return true;
}

uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback(
    const std::vector<const ResourcePool::InUsePoolResource*>& resources,
    base::OnceClosure callback,
    uint64_t pending_callback_id) const {
  gpu::SyncToken latest_sync_token;
  for (const auto* in_use : resources) {
    const gpu::SyncToken& sync_token =
        in_use->gpu_backing()->mailbox_sync_token;
    if (sync_token.release_count() > latest_sync_token.release_count())
      latest_sync_token = sync_token;
  }
  uint64_t callback_id = latest_sync_token.release_count();
  DCHECK_NE(callback_id, 0u);

  // If the callback is different from the one the caller is already waiting on,
  // pass the callback through to SignalSyncToken. Otherwise the request is
  // redundant.
  if (callback_id != pending_callback_id) {
    // Use the compositor context because we want this callback on the
    // compositor thread.
    compositor_context_provider_->ContextSupport()->SignalSyncToken(
        latest_sync_token, std::move(callback));
  }

  return callback_id;
}

void GpuRasterBufferProvider::Shutdown() {
}

gpu::SyncToken GpuRasterBufferProvider::PlaybackOnWorkerThread(
    gpu::Mailbox* mailbox,
    GLenum texture_target,
    bool texture_is_overlay_candidate,
    const gpu::SyncToken& sync_token,
    const gfx::Size& resource_size,
    viz::ResourceFormat resource_format,
    const gfx::ColorSpace& color_space,
    bool resource_has_previous_content,
    const RasterSource* raster_source,
    const gfx::Rect& raster_full_rect,
    const gfx::Rect& raster_dirty_rect,
    uint64_t new_content_id,
    const gfx::AxisTransform2d& transform,
    const RasterSource::PlaybackSettings& playback_settings,
    const GURL& url,
    base::TimeTicks raster_buffer_creation_time,
    bool depends_on_at_raster_decodes,
    bool depends_on_hardware_accelerated_jpeg_candidates,
    bool depends_on_hardware_accelerated_webp_candidates) {
  RasterQuery query;
  query.depends_on_hardware_accelerated_jpeg_candidates =
      depends_on_hardware_accelerated_jpeg_candidates;
  query.depends_on_hardware_accelerated_webp_candidates =
      depends_on_hardware_accelerated_webp_candidates;
  gpu::SyncToken raster_finished_token = PlaybackOnWorkerThreadInternal(
      mailbox, texture_target, texture_is_overlay_candidate, sync_token,
      resource_size, resource_format, color_space,
      resource_has_previous_content, raster_source, raster_full_rect,
      raster_dirty_rect, new_content_id, transform, playback_settings, url,
      depends_on_at_raster_decodes, &query);

  if (query.raster_duration_query_id) {
    if (query.raster_start_query_id)
      query.raster_buffer_creation_time = raster_buffer_creation_time;

    // Note that it is important to scope the raster context lock to
    // PlaybackOnWorkerThreadInternal and release it before calling this
    // function to avoid a deadlock in
    // RasterQueryQueue::CheckRasterFinishedQueries which acquires the raster
    // context lock while holding a lock used in the function.
    pending_raster_queries_->Append(std::move(query));
  }

  return raster_finished_token;
}

gpu::SyncToken GpuRasterBufferProvider::PlaybackOnWorkerThreadInternal(
    gpu::Mailbox* mailbox,
    GLenum texture_target,
    bool texture_is_overlay_candidate,
    const gpu::SyncToken& sync_token,
    const gfx::Size& resource_size,
    viz::ResourceFormat resource_format,
    const gfx::ColorSpace& color_space,
    bool resource_has_previous_content,
    const RasterSource* raster_source,
    const gfx::Rect& raster_full_rect,
    const gfx::Rect& raster_dirty_rect,
    uint64_t new_content_id,
    const gfx::AxisTransform2d& transform,
    const RasterSource::PlaybackSettings& playback_settings,
    const GURL& url,
    bool depends_on_at_raster_decodes,
    RasterQuery* query) {
  viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
      worker_context_provider_, url.possibly_invalid_spec().c_str());
  gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
  DCHECK(ri);

  const bool measure_raster_metric = bernoulli_distribution_(random_generator_);

  gfx::Rect playback_rect = raster_full_rect;
  if (resource_has_previous_content) {
    playback_rect.Intersect(raster_dirty_rect);
  }
  DCHECK(!playback_rect.IsEmpty())
      << "Why are we rastering a tile that's not dirty?";

  if (measure_raster_metric) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
    // Use a query to detect when the GPU side is ready to start issuing raster
    // work to the driver. We will use the resulting timestamp to measure raster
    // scheduling delay. We only care about this in Chrome OS and when OOP-R is
    // enabled because we will use this timestamp to measure raster scheduling
    // delay and we only need to collect that data to assess the impact of
    // hardware acceleration of image decodes which work only in Chrome OS with
    // OOP-R. Furthermore, we don't count raster work that depends on at-raster
    // image decodes. This is because we want the delay to always include
    // image decoding and uploading time, and at-raster decodes should be
    // relatively rare.
    if (enable_oop_rasterization_ && !depends_on_at_raster_decodes) {
      ri->GenQueriesEXT(1, &query->raster_start_query_id);
      DCHECK_GT(query->raster_start_query_id, 0u);
      ri->QueryCounterEXT(query->raster_start_query_id,
                          GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM);
    }
#endif

    // Use a query to time the GPU side work for rasterizing this tile.
    ri->GenQueriesEXT(1, &query->raster_duration_query_id);
    DCHECK_GT(query->raster_duration_query_id, 0u);
    ri->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM,
                      query->raster_duration_query_id);
  }

  {
    absl::optional<base::ElapsedTimer> timer;
    if (measure_raster_metric)
      timer.emplace();
    if (enable_oop_rasterization_) {
      RasterizeSourceOOP(raster_source, resource_has_previous_content, mailbox,
                         sync_token, texture_target,
                         texture_is_overlay_candidate, resource_size,
                         resource_format, color_space, raster_full_rect,
                         playback_rect, transform, playback_settings,
                         worker_context_provider_, is_using_raw_draw_);
    } else {
      RasterizeSource(raster_source, resource_has_previous_content, mailbox,
                      sync_token, texture_target, texture_is_overlay_candidate,
                      resource_size, resource_format, color_space,
                      raster_full_rect, playback_rect, transform,
                      playback_settings, worker_context_provider_,
                      max_tile_size_);
    }
    if (measure_raster_metric) {
      query->worker_raster_duration = timer->Elapsed();
      ri->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
    }
  }

  // Generate sync token for cross context synchronization.
  return viz::ClientResourceProvider::GenerateSyncTokenHelper(ri);
}

bool GpuRasterBufferProvider::ShouldUnpremultiplyAndDitherResource(
    viz::ResourceFormat format) const {
  // TODO(crbug.com/1151490): Re-enable for OOPR.
  return false;
}

}  // namespace cc
