chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "components/viz/service/display_embedder/skia_output_surface_impl.h"

#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "base/containers/heap_array.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_util.h"
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "components/viz/service/debugger/viz_debugger.h"
#include "components/viz/service/display/external_use_client.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/render_pass_alpha_type.h"
#include "components/viz/service/display_embedder/image_context_impl.h"
#include "components/viz/service/display_embedder/skia_output_surface_dependency.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/graphite_cache_controller.h"
#include "gpu/command_buffer/service/graphite_image_provider.h"
#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/shared_image/shared_image_factory.h"
#include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h"
#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
#include "gpu/command_buffer/service/single_task_sequence.h"
#include "gpu/command_buffer/service/skia_utils.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/ipc/service/context_url.h"
#include "gpu/vulkan/buildflags.h"
#include "skia/buildflags.h"
#include "skia/ext/legacy_display_globals.h"
#include "skia/ext/skia_trace_memory_dump_impl.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/gpu/GpuTypes.h"
#include "third_party/skia/include/gpu/GrYUVABackendTextures.h"
#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
#include "third_party/skia/include/gpu/graphite/Image.h"
#include "third_party/skia/include/gpu/graphite/Recorder.h"
#include "third_party/skia/include/gpu/graphite/YUVABackendTextures.h"
#include "third_party/skia/include/private/chromium/GrPromiseImageTexture.h"
#include "third_party/skia/include/private/chromium/SkImageChromium.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_gl_api_implementation.h"

#if BUILDFLAG(ENABLE_VULKAN)
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h"
#include "third_party/skia/include/gpu/vk/VulkanTypes.h"
#endif  // BUILDFLAG(ENABLE_VULKAN)

#if BUILDFLAG(IS_WIN)
#include "components/viz/service/display/dc_layer_overlay.h"
#endif

namespace viz {

namespace {

// Records memory dumps and responds to memory pressure signals for Graphite Viz
// via a global object.
class GraphiteVizMemoryAssistant
    : public base::trace_event::MemoryDumpProvider {};

// FulfillForPlane is a struct that contains the ImageContext `context` used for
// fulfilling an GrPromiseImageTexture identified by `plane_index`. The
// plane_index is 0 for single planar formats and can be between [0, 3] for
// multiplanar formats.
struct FulfillForPlane {};

sk_sp<GrPromiseImageTexture> FulfillGanesh(void* fulfill) {}

std::tuple<skgpu::graphite::BackendTexture, void*> FulfillGraphite(
    void* fulfill) {}

void ReleaseGraphite(void* fulfill) {}

void CleanUp(void* fulfill) {}

void CleanUpArray(void* fulfill_array) {}

gpu::ContextUrl& GetActiveUrl() {}

scoped_refptr<gpu::raster::GraphiteCacheController>
GetOrCreateGraphiteCacheController(skgpu::graphite::Recorder* recorder) {}

}  // namespace

SkiaOutputSurfaceImpl::ScopedPaint::ScopedPaint(
    GrDeferredDisplayListRecorder* root_ddl_recorder,
    bool skip_draw_for_tests)
    :{}

SkiaOutputSurfaceImpl::ScopedPaint::ScopedPaint(
    const GrSurfaceCharacterization& characterization,
    const gpu::Mailbox& mailbox,
    bool skip_draw_for_tests)
    :{}

SkiaOutputSurfaceImpl::ScopedPaint::ScopedPaint(
    skgpu::graphite::Recorder* recorder,
    const SkImageInfo& image_info,
    skgpu::graphite::TextureInfo texture_info,
    const gpu::Mailbox& mailbox,
    bool skip_draw_for_tests)
    :{}

SkiaOutputSurfaceImpl::ScopedPaint::~ScopedPaint() {}

void SkiaOutputSurfaceImpl::ScopedPaint::Initialize(bool skip_draw_for_tests) {}

sk_sp<GrDeferredDisplayList> SkiaOutputSurfaceImpl::ScopedPaint::DetachDDL() {}

std::unique_ptr<skgpu::graphite::Recording>
SkiaOutputSurfaceImpl::ScopedPaint::SnapRecording() {}

// static
std::unique_ptr<SkiaOutputSurface> SkiaOutputSurfaceImpl::Create(
    DisplayCompositorMemoryAndTaskController* display_controller,
    const RendererSettings& renderer_settings,
    const DebugRendererSettings* debug_settings) {}

SkiaOutputSurfaceImpl::SkiaOutputSurfaceImpl(
    base::PassKey<SkiaOutputSurfaceImpl> /* pass_key */,
    DisplayCompositorMemoryAndTaskController* display_controller,
    const RendererSettings& renderer_settings,
    const DebugRendererSettings* debug_settings)
    :{}

SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() {}

gpu::SurfaceHandle SkiaOutputSurfaceImpl::GetSurfaceHandle() const {}

void SkiaOutputSurfaceImpl::BindToClient(OutputSurfaceClient* client) {}

void SkiaOutputSurfaceImpl::EnsureBackbuffer() {}

void SkiaOutputSurfaceImpl::DiscardBackbuffer() {}

void SkiaOutputSurfaceImpl::RecreateRootDDLRecorder() {}

void SkiaOutputSurfaceImpl::Reshape(const ReshapeParams& params) {}

void SkiaOutputSurfaceImpl::SetUpdateVSyncParametersCallback(
    UpdateVSyncParametersCallback callback) {}

void SkiaOutputSurfaceImpl::SetVSyncDisplayID(int64_t display_id) {}

void SkiaOutputSurfaceImpl::SetDisplayTransformHint(
    gfx::OverlayTransform transform) {}

gfx::OverlayTransform SkiaOutputSurfaceImpl::GetDisplayTransform() {}

SkCanvas* SkiaOutputSurfaceImpl::BeginPaintCurrentFrame() {}

void SkiaOutputSurfaceImpl::MakePromiseSkImage(
    ImageContext* image_context,
    const gfx::ColorSpace& color_space,
    bool force_rgbx) {}

sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV(
    const std::vector<ImageContext*>& contexts,
    sk_sp<SkColorSpace> image_color_space,
    SkYUVAInfo::PlaneConfig plane_config,
    SkYUVAInfo::Subsampling subsampling) {}

void SkiaOutputSurfaceImpl::MakePromiseSkImageSinglePlane(
    ImageContextImpl* image_context,
    bool mipmap,
    const gfx::ColorSpace& color_space,
    bool force_rgbx) {}

void SkiaOutputSurfaceImpl::MakePromiseSkImageMultiPlane(
    ImageContextImpl* image_context,
    const gfx::ColorSpace& color_space) {}

gpu::SyncToken SkiaOutputSurfaceImpl::ReleaseImageContexts(
    std::vector<std::unique_ptr<ImageContext>> image_contexts) {}

std::unique_ptr<ExternalUseClient::ImageContext>
SkiaOutputSurfaceImpl::CreateImageContext(
    const gpu::MailboxHolder& holder,
    const gfx::Size& size,
    SharedImageFormat format,
    bool maybe_concurrent_reads,
    const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
    sk_sp<SkColorSpace> color_space,
    bool raw_draw_if_possible) {}

DBG_FLAG_FBOOL("skia_gpu.swap_buffers.force_disable_makecurrent",
               force_disable_makecurrent)

void SkiaOutputSurfaceImpl::SwapBuffers(OutputSurfaceFrame frame) {}

void SkiaOutputSurfaceImpl::SwapBuffersSkipped(
    const gfx::Rect root_pass_damage_rect) {}

SkCanvas* SkiaOutputSurfaceImpl::BeginPaintRenderPass(
    const AggregatedRenderPassId& id,
    const gfx::Size& surface_size,
    SharedImageFormat format,
    RenderPassAlphaType alpha_type,
    skgpu::Mipmapped mipmap,
    bool scanout_dcomp_surface,
    sk_sp<SkColorSpace> color_space,
    bool is_overlay,
    const gpu::Mailbox& mailbox) {}

SkCanvas* SkiaOutputSurfaceImpl::RecordOverdrawForCurrentPaint() {}

void SkiaOutputSurfaceImpl::EndPaint(
    base::OnceClosure on_finished,
    base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb,
    const gfx::Rect& update_rect,
    bool is_overlay) {}

sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromRenderPass(
    const AggregatedRenderPassId& id,
    const gfx::Size& size,
    SharedImageFormat format,
    bool mipmap,
    sk_sp<SkColorSpace> color_space,
    const gpu::Mailbox& mailbox) {}

void SkiaOutputSurfaceImpl::RemoveRenderPassResource(
    std::vector<AggregatedRenderPassId> ids) {}

void SkiaOutputSurfaceImpl::CopyOutput(
    const copy_output::RenderPassGeometry& geometry,
    const gfx::ColorSpace& color_space,
    std::unique_ptr<CopyOutputRequest> request,
    const gpu::Mailbox& mailbox) {}

void SkiaOutputSurfaceImpl::ScheduleOverlays(
    OverlayList overlays,
    std::vector<gpu::SyncToken> sync_tokens) {}

void SkiaOutputSurfaceImpl::SetFrameRate(float frame_rate) {}

void SkiaOutputSurfaceImpl::SetCapabilitiesForTesting(
    gfx::SurfaceOrigin output_surface_origin) {}

bool SkiaOutputSurfaceImpl::Initialize() {}

void SkiaOutputSurfaceImpl::InitializeOnGpuThread(bool* result) {}

GrSurfaceCharacterization
SkiaOutputSurfaceImpl::CreateGrSurfaceCharacterizationRenderPass(
    const gfx::Size& surface_size,
    SkColorType color_type,
    SkAlphaType alpha_type,
    skgpu::Mipmapped mipmap,
    sk_sp<SkColorSpace> color_space,
    bool is_overlay,
    bool scanout_dcomp_surface) const {}

GrSurfaceCharacterization
SkiaOutputSurfaceImpl::CreateGrSurfaceCharacterizationCurrentFrame(
    const gfx::Size& surface_size,
    SkColorType color_type,
    SkAlphaType alpha_type,
    skgpu::Mipmapped mipmap,
    sk_sp<SkColorSpace> color_space) const {}

void SkiaOutputSurfaceImpl::DidSwapBuffersComplete(
    gpu::SwapBuffersCompleteParams params,
    const gfx::Size& pixel_size,
    gfx::GpuFenceHandle release_fence) {}

void SkiaOutputSurfaceImpl::ReleaseOverlays(
    std::vector<gpu::Mailbox> released_overlays) {}

void SkiaOutputSurfaceImpl::BufferPresented(
    const gfx::PresentationFeedback& feedback) {}

void SkiaOutputSurfaceImpl::AddChildWindowToBrowser(
    gpu::SurfaceHandle child_window) {}

void SkiaOutputSurfaceImpl::ScheduleGpuTaskForTesting(
    base::OnceClosure callback,
    std::vector<gpu::SyncToken> sync_tokens) {}

void SkiaOutputSurfaceImpl::CheckAsyncWorkCompletionForTesting() {}

void SkiaOutputSurfaceImpl::EnqueueGpuTask(
    GpuTask task,
    std::vector<gpu::SyncToken> sync_tokens,
    bool make_current,
    bool need_framebuffer) {}

void SkiaOutputSurfaceImpl::FlushGpuTasks(SyncMode sync_mode) {}

void SkiaOutputSurfaceImpl::FlushGpuTasksWithImpl(
    SyncMode sync_mode,
    SkiaOutputSurfaceImplOnGpu* impl_on_gpu) {}

GrBackendFormat SkiaOutputSurfaceImpl::GetGrBackendFormatForTexture(
    SharedImageFormat si_format,
    int plane_index,
    uint32_t gl_texture_target,
    const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
    const gfx::ColorSpace& yuv_color_space) {}

void SkiaOutputSurfaceImpl::SetNeedsSwapSizeNotifications(
    bool needs_swap_size_notifications) {}

#if BUILDFLAG(IS_ANDROID)
base::ScopedClosureRunner SkiaOutputSurfaceImpl::GetCacheBackBufferCb() {
  // Note, that we call it directly on viz thread to get the callback.
  return impl_on_gpu_->GetCacheBackBufferCb();
}
#endif

void SkiaOutputSurfaceImpl::AddContextLostObserver(
    ContextLostObserver* observer) {}

void SkiaOutputSurfaceImpl::RemoveContextLostObserver(
    ContextLostObserver* observer) {}

gpu::SyncToken SkiaOutputSurfaceImpl::Flush() {}

void SkiaOutputSurfaceImpl::ContextLost() {}

void SkiaOutputSurfaceImpl::ScheduleOrRetainGpuTask(
    base::OnceClosure callback,
    std::vector<gpu::SyncToken> tokens) {}

gfx::Rect SkiaOutputSurfaceImpl::GetCurrentFramebufferDamage() const {}

void SkiaOutputSurfaceImpl::SetNeedsMeasureNextDrawLatency() {}

void SkiaOutputSurfaceImpl::PreserveChildSurfaceControls() {}

void SkiaOutputSurfaceImpl::InitDelegatedInkPointRendererReceiver(
    mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
        pending_receiver) {}

gpu::Mailbox SkiaOutputSurfaceImpl::CreateSharedImage(
    SharedImageFormat format,
    const gfx::Size& size,
    const gfx::ColorSpace& color_space,
    RenderPassAlphaType alpha_type,
    gpu::SharedImageUsageSet usage,
    std::string_view debug_label,
    gpu::SurfaceHandle surface_handle) {}

gpu::Mailbox SkiaOutputSurfaceImpl::CreateSolidColorSharedImage(
    const SkColor4f& color,
    const gfx::ColorSpace& color_space) {}

void SkiaOutputSurfaceImpl::DestroySharedImage(const gpu::Mailbox& mailbox) {}

void SkiaOutputSurfaceImpl::SetSharedImagePurgeable(const gpu::Mailbox& mailbox,
                                                    bool purgeable) {}

bool SkiaOutputSurfaceImpl::SupportsBGRA() const {}

#if BUILDFLAG(ENABLE_VULKAN) && BUILDFLAG(IS_CHROMEOS) && \
    BUILDFLAG(USE_V4L2_CODEC)
void SkiaOutputSurfaceImpl::DetileOverlay(gpu::Mailbox input,
                                          const gfx::Size& input_visible_size,
                                          gpu::SyncToken input_sync_token,
                                          gpu::Mailbox output,
                                          const gfx::RectF& display_rect,
                                          const gfx::RectF& crop_rect,
                                          gfx::OverlayTransform transform,
                                          bool is_10bit) {
  auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::DetileOverlay,
                             base::Unretained(impl_on_gpu_.get()), input,
                             input_visible_size, output, display_rect,
                             crop_rect, transform, is_10bit);
  EnqueueGpuTask(std::move(task), {input_sync_token}, /*make_current=*/false,
                 /*need_framebuffer=*/false);
}

void SkiaOutputSurfaceImpl::CleanupImageProcessor() {
  auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::CleanupImageProcessor,
                             base::Unretained(impl_on_gpu_.get()));
  EnqueueGpuTask(std::move(task), {}, /*make_current=*/false,
                 /*need_framebuffer=*/false);
}
#endif

}  // namespace viz