#ifdef UNSAFE_BUFFERS_BUILD
#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
#if BUILDFLAG(IS_WIN)
#include "components/viz/service/display/dc_layer_overlay.h"
#endif
namespace viz {
namespace {
class GraphiteVizMemoryAssistant
: public base::trace_event::MemoryDumpProvider { … };
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) { … }
}
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() { … }
std::unique_ptr<SkiaOutputSurface> SkiaOutputSurfaceImpl::Create(
DisplayCompositorMemoryAndTaskController* display_controller,
const RendererSettings& renderer_settings,
const DebugRendererSettings* debug_settings) { … }
SkiaOutputSurfaceImpl::SkiaOutputSurfaceImpl(
base::PassKey<SkiaOutputSurfaceImpl> ,
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() {
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}, false,
false);
}
void SkiaOutputSurfaceImpl::CleanupImageProcessor() {
auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::CleanupImageProcessor,
base::Unretained(impl_on_gpu_.get()));
EnqueueGpuTask(std::move(task), {}, false,
false);
}
#endif
}