blob: a1146d65544ee4e93ed57e30245cbc62719a5394 [file] [log] [blame]
// Copyright 2018 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.
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_
#include <memory>
#include <utility>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/resource_metadata.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/ipc/in_process_command_buffer.h"
#include "gpu/ipc/service/image_transport_surface_delegate.h"
#include "third_party/skia/include/core/SkPromiseImageTexture.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSemaphore.h"
#include "ui/latency/latency_tracker.h"
class SkDeferredDisplayList;
namespace base {
class WaitableEvent;
}
namespace gfx {
class ColorSpace;
}
namespace gl {
class GLApi;
class GLSurface;
}
namespace gpu {
class SyncPointClientState;
}
namespace ui {
#if defined(USE_OZONE)
class PlatformWindowSurface;
#endif
} // namespace ui
namespace viz {
struct ImageContext;
class DirectContextProvider;
class GLRendererCopier;
class SkiaOutputSurfaceDependency;
class TextureDeleter;
class VulkanContextProvider;
namespace copy_output {
struct RenderPassGeometry;
} // namespace copy_output
// The SkiaOutputSurface implementation running on the GPU thread. This class
// should be created, used and destroyed on the GPU thread.
class SkiaOutputSurfaceImplOnGpu {
public:
using DidSwapBufferCompleteCallback =
base::RepeatingCallback<void(gpu::SwapBuffersCompleteParams,
const gfx::Size& pixel_size)>;
using BufferPresentedCallback =
base::RepeatingCallback<void(const gfx::PresentationFeedback& feedback)>;
using ContextLostCallback = base::RepeatingCallback<void()>;
SkiaOutputSurfaceImplOnGpu(
SkiaOutputSurfaceDependency* deps,
const RendererSettings& renderer_settings_,
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
const BufferPresentedCallback& buffer_presented_callback,
const ContextLostCallback& context_lost_callback);
~SkiaOutputSurfaceImplOnGpu();
gpu::CommandBufferId command_buffer_id() const {
return sync_point_client_state_->command_buffer_id();
}
const OutputSurface::Capabilities capabilities() const {
return output_device_->capabilities();
}
const base::WeakPtr<SkiaOutputSurfaceImplOnGpu>& weak_ptr() const {
return weak_ptr_;
}
void Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
bool has_alpha,
bool use_stencil,
SkSurfaceCharacterization* characterization,
base::WaitableEvent* event);
void FinishPaintCurrentFrame(
std::unique_ptr<SkDeferredDisplayList> ddl,
std::unique_ptr<SkDeferredDisplayList> overdraw_ddl,
std::vector<ImageContext*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release,
base::OnceClosure on_finished);
void SwapBuffers(OutputSurfaceFrame frame);
void EnsureBackbuffer() { output_device_->EnsureBackbuffer(); }
void DiscardBackbuffer() { output_device_->DiscardBackbuffer(); }
void FinishPaintRenderPass(RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl,
std::vector<ImageContext*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release);
void RemoveRenderPassResource(
std::vector<std::unique_ptr<ImageContext>> image_contexts);
void CopyOutput(RenderPassId id,
const copy_output::RenderPassGeometry& geometry,
const gfx::ColorSpace& color_space,
std::unique_ptr<CopyOutputRequest> request);
void BeginAccessImages(const std::vector<ImageContext*>& image_contexts,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores);
void EndAccessImages(const std::vector<ImageContext*>& image_contexts);
void SetDrawRectangle(const gfx::Rect& draw_rectangle);
sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy();
const gl::GLVersionInfo* gl_version_info() const { return gl_version_info_; }
size_t max_resource_cache_bytes() const { return max_resource_cache_bytes_; }
void ReleaseImageContexts(
std::vector<std::unique_ptr<ImageContext>> image_contexts);
bool was_context_lost() { return context_state_->context_lost(); }
class ScopedUseContextProvider;
void SetCapabilitiesForTesting(
const OutputSurface::Capabilities& capabilities);
private:
class ScopedPromiseImageAccess;
void InitializeForGL();
void InitializeForVulkan();
// Returns true if |texture_base| is a gles2::Texture and all necessary
// operations completed successfully. In this case, |*size| is the size of
// of level 0.
bool BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base,
gfx::Size* size);
// Make context current for GL, and return false if the context is lost.
// It will do nothing when Vulkan is used.
bool MakeCurrent(bool need_fbo0);
void PullTextureUpdates(std::vector<gpu::SyncToken> sync_token);
void ReleaseFenceSyncAndPushTextureUpdates(uint64_t sync_fence_release);
GrContext* gr_context() { return context_state_->gr_context(); }
gpu::DecoderContext* decoder();
void ScheduleDelayedWork();
void PerformDelayedWork();
bool is_using_vulkan() const { return !!vulkan_context_provider_; }
SkSurface* output_sk_surface() const {
return output_device_->draw_surface();
}
void CreateFallbackImage(ImageContext* context);
SkiaOutputSurfaceDependency* const dependency_;
scoped_refptr<gpu::gles2::FeatureInfo> feature_info_;
scoped_refptr<gpu::SyncPointClientState> sync_point_client_state_;
std::unique_ptr<gpu::SharedImageRepresentationFactory>
shared_image_representation_factory_;
VulkanContextProvider* const vulkan_context_provider_;
const RendererSettings renderer_settings_;
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback_;
BufferPresentedCallback buffer_presented_callback_;
ContextLostCallback context_lost_callback_;
#if defined(USE_OZONE)
// This should outlive gl_surface_ and vulkan_surface_.
std::unique_ptr<ui::PlatformWindowSurface> window_surface_;
#endif
gpu::GpuPreferences gpu_preferences_;
gfx::Size size_;
gfx::ColorSpace color_space_;
scoped_refptr<gl::GLSurface> gl_surface_;
scoped_refptr<gpu::SharedContextState> context_state_;
const gl::GLVersionInfo* gl_version_info_ = nullptr;
size_t max_resource_cache_bytes_ = 0u;
std::unique_ptr<SkiaOutputDevice> output_device_;
// Semaphore for SkiaOutputDevice::SwapBuffers() to wait on.
GrBackendSemaphore swap_buffers_semaphore_;
// Offscreen surfaces for render passes. It can only be accessed on GPU
// thread.
class OffscreenSurface {
public:
OffscreenSurface();
OffscreenSurface(const OffscreenSurface& offscreen_surface) = delete;
OffscreenSurface(OffscreenSurface&& offscreen_surface);
OffscreenSurface& operator=(const OffscreenSurface& offscreen_surface) =
delete;
OffscreenSurface& operator=(OffscreenSurface&& offscreen_surface);
~OffscreenSurface();
SkSurface* surface() const;
sk_sp<SkPromiseImageTexture> fulfill();
void set_surface(sk_sp<SkSurface> surface);
private:
sk_sp<SkSurface> surface_;
sk_sp<SkPromiseImageTexture> promise_texture_;
};
base::flat_map<RenderPassId, OffscreenSurface> offscreen_surfaces_;
ui::LatencyTracker latency_tracker_;
scoped_refptr<base::SingleThreadTaskRunner> context_current_task_runner_;
scoped_refptr<DirectContextProvider> context_provider_;
std::unique_ptr<TextureDeleter> texture_deleter_;
std::unique_ptr<GLRendererCopier> copier_;
bool delayed_work_pending_ = false;
gl::GLApi* api_ = nullptr;
bool supports_alpha_ = false;
THREAD_CHECKER(thread_checker_);
base::WeakPtr<SkiaOutputSurfaceImplOnGpu> weak_ptr_;
base::WeakPtrFactory<SkiaOutputSurfaceImplOnGpu> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceImplOnGpu);
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_