1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_
6 #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/macros.h"
12 #include "base/observer_list.h"
13 #include "base/optional.h"
14 #include "base/threading/thread_checker.h"
15 #include "base/util/type_safety/pass_key.h"
16 #include "build/build_config.h"
17 #include "components/viz/common/display/renderer_settings.h"
18 #include "components/viz/common/resources/resource_id.h"
19 #include "components/viz/service/display/skia_output_surface.h"
20 #include "components/viz/service/viz_service_export.h"
21 #include "gpu/command_buffer/common/sync_token.h"
22 #include "gpu/ipc/common/vulkan_ycbcr_info.h"
23 #include "gpu/ipc/in_process_command_buffer.h"
24 #include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h"
25 #include "third_party/skia/include/core/SkOverdrawCanvas.h"
26 #include "third_party/skia/include/core/SkSurfaceCharacterization.h"
27 #include "third_party/skia/include/core/SkYUVAIndex.h"
28 
29 namespace base {
30 class WaitableEvent;
31 }
32 
33 namespace viz {
34 
35 class ImageContextImpl;
36 class SkiaOutputSurfaceDependency;
37 class SkiaOutputSurfaceImplOnGpu;
38 
39 // The SkiaOutputSurface implementation. It is the output surface for
40 // SkiaRenderer. It lives on the compositor thread, but it will post tasks
41 // to the GPU thread for initializing. Currently, SkiaOutputSurfaceImpl
42 // create a SkiaOutputSurfaceImplOnGpu on the GPU thread. It will be used
43 // for creating a SkSurface from the default framebuffer and providing the
44 // SkSurfaceCharacterization for the SkSurface. And then SkiaOutputSurfaceImpl
45 // will create SkDeferredDisplayListRecorder and SkCanvas for SkiaRenderer to
46 // render into. In SwapBuffers, it detaches a SkDeferredDisplayList from the
47 // recorder and plays it back on the framebuffer SkSurface on the GPU thread
48 // through SkiaOutputSurfaceImpleOnGpu.
49 class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
50  public:
51   static std::unique_ptr<SkiaOutputSurface> Create(
52       std::unique_ptr<SkiaOutputSurfaceDependency> deps,
53       const RendererSettings& renderer_settings);
54 
55   SkiaOutputSurfaceImpl(util::PassKey<SkiaOutputSurfaceImpl> pass_key,
56                         std::unique_ptr<SkiaOutputSurfaceDependency> deps,
57                         const RendererSettings& renderer_settings);
58   ~SkiaOutputSurfaceImpl() override;
59 
60   // OutputSurface implementation:
61   gpu::SurfaceHandle GetSurfaceHandle() const override;
62   void BindToClient(OutputSurfaceClient* client) override;
63   void BindFramebuffer() override;
64   void SetDrawRectangle(const gfx::Rect& draw_rectangle) override;
65   void EnsureBackbuffer() override;
66   void DiscardBackbuffer() override;
67   void Reshape(const gfx::Size& size,
68                float device_scale_factor,
69                const gfx::ColorSpace& color_space,
70                gfx::BufferFormat format,
71                bool use_stencil) override;
72   void SetUpdateVSyncParametersCallback(
73       UpdateVSyncParametersCallback callback) override;
74   void SetGpuVSyncEnabled(bool enabled) override;
75   void SetGpuVSyncCallback(GpuVSyncCallback callback) override;
76   void SetDisplayTransformHint(gfx::OverlayTransform transform) override;
77   gfx::OverlayTransform GetDisplayTransform() override;
78   void SwapBuffers(OutputSurfaceFrame frame) override;
79   uint32_t GetFramebufferCopyTextureFormat() override;
80   bool IsDisplayedAsOverlayPlane() const override;
81   unsigned GetOverlayTextureId() const override;
82   bool HasExternalStencilTest() const override;
83   void ApplyExternalStencil() override;
84   unsigned UpdateGpuFence() override;
85   void SetNeedsSwapSizeNotifications(
86       bool needs_swap_size_notifications) override;
87   base::ScopedClosureRunner GetCacheBackBufferCb() override;
88   scoped_refptr<gpu::GpuTaskSchedulerHelper> GetGpuTaskSchedulerHelper()
89       override;
90   gfx::Rect GetCurrentFramebufferDamage() const override;
91 
92   // SkiaOutputSurface implementation:
93   SkCanvas* BeginPaintCurrentFrame() override;
94   sk_sp<SkImage> MakePromiseSkImageFromYUV(
95       const std::vector<ImageContext*>& contexts,
96       sk_sp<SkColorSpace> image_color_space,
97       bool has_alpha) override;
98   void SwapBuffersSkipped() override;
99   void ScheduleOutputSurfaceAsOverlay(
100       OverlayProcessorInterface::OutputSurfaceOverlayPlane output_surface_plane)
101       override;
102 
103   SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
104                                  const gfx::Size& surface_size,
105                                  ResourceFormat format,
106                                  bool mipmap,
107                                  sk_sp<SkColorSpace> color_space) override;
108   gpu::SyncToken SubmitPaint(base::OnceClosure on_finished) override;
109   void MakePromiseSkImage(ImageContext* image_context) override;
110   sk_sp<SkImage> MakePromiseSkImageFromRenderPass(
111       const RenderPassId& id,
112       const gfx::Size& size,
113       ResourceFormat format,
114       bool mipmap,
115       sk_sp<SkColorSpace> color_space) override;
116 
117   void RemoveRenderPassResource(std::vector<RenderPassId> ids) override;
118   void ScheduleOverlays(OverlayList overlays,
119                         std::vector<gpu::SyncToken> sync_tokens) override;
120 
121 #if defined(OS_WIN)
122   void SetEnableDCLayers(bool enable) override;
123 #endif
124   void CopyOutput(RenderPassId id,
125                   const copy_output::RenderPassGeometry& geometry,
126                   const gfx::ColorSpace& color_space,
127                   std::unique_ptr<CopyOutputRequest> request) override;
128   void AddContextLostObserver(ContextLostObserver* observer) override;
129   void RemoveContextLostObserver(ContextLostObserver* observer) override;
130 
131   // ExternalUseClient implementation:
132   void ReleaseImageContexts(
133       std::vector<std::unique_ptr<ImageContext>> image_contexts) override;
134   std::unique_ptr<ExternalUseClient::ImageContext> CreateImageContext(
135       const gpu::MailboxHolder& holder,
136       const gfx::Size& size,
137       ResourceFormat format,
138       const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
139       sk_sp<SkColorSpace> color_space) override;
140 
141   gpu::MemoryTracker* GetMemoryTracker() override;
142 
143   // Set the fields of |capabilities_| and propagates to |impl_on_gpu_|. Should
144   // be called after BindToClient().
145   void SetCapabilitiesForTesting(gfx::SurfaceOrigin output_surface_origin);
146 
147   // Used in unit tests.
148   void ScheduleGpuTaskForTesting(
149       base::OnceClosure callback,
150       std::vector<gpu::SyncToken> sync_tokens) override;
151 
152  private:
153   bool Initialize();
154   void InitializeOnGpuThread(GpuVSyncCallback vsync_callback_runner,
155                              base::WaitableEvent* event,
156                              bool* result);
157   SkSurfaceCharacterization CreateSkSurfaceCharacterization(
158       const gfx::Size& surface_size,
159       ResourceFormat format,
160       bool mipmap,
161       sk_sp<SkColorSpace> color_space,
162       bool is_root_render_pass);
163   void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params,
164                               const gfx::Size& pixel_size);
165   void BufferPresented(const gfx::PresentationFeedback& feedback);
166 
167   // Provided as a callback for the GPU thread.
168   void OnGpuVSync(base::TimeTicks timebase, base::TimeDelta interval);
169 
170   void ScheduleGpuTask(base::OnceClosure callback,
171                        std::vector<gpu::SyncToken> sync_tokens);
172   GrBackendFormat GetGrBackendFormatForTexture(
173       ResourceFormat resource_format,
174       uint32_t gl_texture_target,
175       const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info);
176   void PrepareYUVATextureIndices(const std::vector<ImageContext*>& contexts,
177                                  bool has_alpha,
178                                  SkYUVAIndex indices[4]);
179   void ContextLost();
180 
181   void RecreateRootRecorder();
182 
183   OutputSurfaceClient* client_ = nullptr;
184   bool needs_swap_size_notifications_ = false;
185 
186   // Images for current frame or render pass.
187   std::vector<ImageContextImpl*> images_in_current_paint_;
188 
189   THREAD_CHECKER(thread_checker_);
190 
191   // Observers for context lost.
192   base::ObserverList<ContextLostObserver>::Unchecked observers_;
193 
194   uint64_t sync_fence_release_ = 0;
195   std::unique_ptr<SkiaOutputSurfaceDependency> dependency_;
196   UpdateVSyncParametersCallback update_vsync_parameters_callback_;
197   GpuVSyncCallback gpu_vsync_callback_;
198   bool is_displayed_as_overlay_ = false;
199 
200   gfx::Size size_;
201   gfx::ColorSpace color_space_;
202   bool is_hdr_ = false;
203   SkSurfaceCharacterization characterization_;
204   base::Optional<SkDeferredDisplayListRecorder> root_recorder_;
205 
206   class ScopedPaint {
207    public:
208     explicit ScopedPaint(SkDeferredDisplayListRecorder* root_recorder);
209     ScopedPaint(SkSurfaceCharacterization characterization,
210                 RenderPassId render_pass_id);
211     ~ScopedPaint();
212 
recorder()213     SkDeferredDisplayListRecorder* recorder() { return recorder_; }
render_pass_id()214     RenderPassId render_pass_id() { return render_pass_id_; }
215 
216    private:
217     // This is recorder being used for current paint
218     SkDeferredDisplayListRecorder* recorder_;
219     // If we need new recorder for this Paint (i.e it's not root render pass),
220     // it's stored here
221     base::Optional<SkDeferredDisplayListRecorder> recorder_storage_;
222     const RenderPassId render_pass_id_;
223   };
224 
225   // This holds current paint info
226   base::Optional<ScopedPaint> current_paint_;
227 
228   // The SkDDL recorder is used for overdraw feedback. It is created by
229   // BeginPaintOverdraw, and FinishPaintCurrentFrame will turn it into a SkDDL
230   // and play the SkDDL back on the GPU thread.
231   base::Optional<SkDeferredDisplayListRecorder> overdraw_surface_recorder_;
232 
233   // |overdraw_canvas_| is used to record draw counts.
234   base::Optional<SkOverdrawCanvas> overdraw_canvas_;
235 
236   // |nway_canvas_| contains |overdraw_canvas_| and root canvas.
237   base::Optional<SkNWayCanvas> nway_canvas_;
238 
239   // The cache for promise image created from render passes.
240   base::flat_map<RenderPassId, std::unique_ptr<ImageContextImpl>>
241       render_pass_image_cache_;
242 
243   // Sync tokens for resources which are used for the current frame or render
244   // pass.
245   std::vector<gpu::SyncToken> resource_sync_tokens_;
246 
247   const RendererSettings renderer_settings_;
248 
249   // The display transform relative to the hardware natural orientation,
250   // applied to the frame content. The transform can be rotations in 90 degree
251   // increments or flips.
252   gfx::OverlayTransform pre_transform_ = gfx::OVERLAY_TRANSFORM_NONE;
253 
254   // |gpu_task_scheduler_| holds a gpu::SingleTaskSequence, and helps schedule
255   // tasks on GPU as a single sequence. It is shared with OverlayProcessor so
256   // compositing and overlay processing are in order. A gpu::SingleTaskSequence
257   // in regular Viz is implemented by SchedulerSequence. In Android WebView
258   // gpu::SingleTaskSequence is implemented on top of WebView's task queue.
259   scoped_refptr<gpu::GpuTaskSchedulerHelper> gpu_task_scheduler_;
260 
261   // |impl_on_gpu| is created and destroyed on the GPU thread.
262   std::unique_ptr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_;
263 
264   bool has_set_draw_rectangle_for_frame_ = false;
265   base::Optional<gfx::Rect> draw_rectangle_;
266 
267   // We defer the draw to the framebuffer until SwapBuffers or CopyOutput
268   // to avoid the expense of posting a task and calling MakeCurrent.
269   base::OnceCallback<bool()> deferred_framebuffer_draw_closure_;
270 
271   // Current buffer index.
272   size_t current_buffer_ = 0;
273   // Damage area of the buffer. Differ to the last submit buffer.
274   std::vector<gfx::Rect> damage_of_buffers_;
275   // Track if the current buffer content is changed.
276   bool current_buffer_modified_ = false;
277 
278   base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr_;
279   base::WeakPtrFactory<SkiaOutputSurfaceImpl> weak_ptr_factory_{this};
280 
281   DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceImpl);
282 };
283 
284 }  // namespace viz
285 
286 #endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_
287