summaryrefslogtreecommitdiff
path: root/chromium/components/viz/service/display/skia_renderer.h
blob: 8d86c0630a960254b480c1d08c150c53eb3917ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// Copyright 2012 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_SKIA_RENDERER_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_RENDERER_H_

#include <map>
#include <memory>
#include <tuple>
#include <vector>

#include "base/macros.h"
#include "cc/cc_export.h"
#include "components/viz/service/display/direct_renderer.h"
#include "components/viz/service/display/sync_query_collection.h"
#include "components/viz/service/viz_service_export.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/latency/latency_info.h"

class SkColorFilter;
class SkNWayCanvas;
class SkPictureRecorder;

namespace gpu {
struct Capabilities;
}

namespace viz {
class DebugBorderDrawQuad;
class PictureDrawQuad;
class SkiaOutputSurface;
class SolidColorDrawQuad;
class TextureDrawQuad;
class TileDrawQuad;
class YUVVideoDrawQuad;

// TODO(795132): SkColorSpace is only a subset comparing to gfx::ColorSpace.
// Need to figure out support for color space that is not covered by
// SkColorSpace.
class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
 public:
  // Different draw modes that are supported by SkiaRenderer right now.
  enum DrawMode { DDL, SKPRECORD };

  // TODO(penghuang): Remove skia_output_surface when DDL is used everywhere.
  SkiaRenderer(const RendererSettings* settings,
               OutputSurface* output_surface,
               DisplayResourceProvider* resource_provider,
               SkiaOutputSurface* skia_output_surface,
               DrawMode mode);
  ~SkiaRenderer() override;

  void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) override;

  void SetDisablePictureQuadImageFiltering(bool disable) {
    disable_picture_quad_image_filtering_ = disable;
  }

 protected:
  bool CanPartialSwap() override;
  void UpdateRenderPassTextures(
      const RenderPassList& render_passes_in_draw_order,
      const base::flat_map<RenderPassId, RenderPassRequirements>&
          render_passes_in_frame) override;
  void AllocateRenderPassResourceIfNeeded(
      const RenderPassId& render_pass_id,
      const RenderPassRequirements& requirements) override;
  bool IsRenderPassResourceAllocated(
      const RenderPassId& render_pass_id) const override;
  gfx::Size GetRenderPassBackingPixelSize(
      const RenderPassId& render_pass_id) override;
  void BindFramebufferToOutputSurface() override;
  void BindFramebufferToTexture(const RenderPassId render_pass_id) override;
  void SetScissorTestRect(const gfx::Rect& scissor_rect) override;
  void PrepareSurfaceForPass(SurfaceInitializationMode initialization_mode,
                             const gfx::Rect& render_pass_scissor) override;
  void DoDrawQuad(const DrawQuad* quad, const gfx::QuadF* draw_region) override;
  void BeginDrawingFrame() override;
  void FinishDrawingFrame() override;
  bool FlippedFramebuffer() const override;
  void EnsureScissorTestEnabled() override;
  void EnsureScissorTestDisabled() override;
  void CopyDrawnRenderPass(const copy_output::RenderPassGeometry& geometry,
                           std::unique_ptr<CopyOutputRequest> request) override;
  void SetEnableDCLayers(bool enable) override;
  void DidChangeVisibility() override;
  void FinishDrawingQuadList() override;
  void GenerateMipmap() override;

 private:
  struct DrawQuadParams;
  struct DrawRPDQParams;
  class ScopedSkImageBuilder;
  class ScopedYUVSkImageBuilder;

  void ClearCanvas(SkColor color);
  void ClearFramebuffer();

  // Callers should init an SkAutoCanvasRestore before calling this function.
  // |scissor_rect| and |rounded_corner_bounds| should be in device space,
  // i.e. same space that |cdt| will transform subsequent draws into.
  void PrepareCanvas(const base::Optional<gfx::Rect>& scissor_rect,
                     const base::Optional<gfx::RRectF>& rounded_corner_bounds,
                     const gfx::Transform* cdt);

  // The returned DrawQuadParams can be modified by the DrawX calls that accept
  // params so that they can apply explicit data transforms before sending to
  // Skia in a consistent manner.
  DrawQuadParams CalculateDrawQuadParams(const DrawQuad* quad,
                                         const gfx::QuadF* draw_region);
  DrawRPDQParams CalculateRPDQParams(const SkImage* src_image,
                                     const RenderPassDrawQuad* quad,
                                     DrawQuadParams* params);

  SkCanvas::ImageSetEntry MakeEntry(const SkImage* image,
                                    int matrix_index,
                                    const DrawQuadParams& params);
  // Returns overall constraint to pass to Skia, and modifies |params| to
  // emulate content area clamping different from the provided texture coords.
  SkCanvas::SrcRectConstraint ResolveTextureConstraints(
      const SkImage* image,
      const gfx::RectF& valid_texel_bounds,
      DrawQuadParams* params);

  // True or false if the DrawQuad can have the scissor rect applied by
  // modifying the quad's visible_rect instead of as a separate clip operation.
  bool CanExplicitlyScissor(
      const DrawQuad* quad,
      const gfx::QuadF* draw_region,
      const gfx::Transform& contents_device_transform) const;

  bool MustFlushBatchedQuads(const DrawQuad* new_quad,
                             const DrawQuadParams& params);
  void AddQuadToBatch(const SkImage* image,
                      const gfx::RectF& valid_texel_bounds,
                      DrawQuadParams* params);
  void FlushBatchedQuads();

  // Utility to draw a single quad as a filled color
  void DrawColoredQuad(SkColor color, DrawQuadParams* params);
  // Utility to make a single ImageSetEntry and draw it with the complex paint.
  void DrawSingleImage(const SkImage* image,
                       const gfx::RectF& valid_texel_bounds,
                       const SkPaint& paint,
                       DrawQuadParams* params);

  // DebugBorder, Picture, RPDQ, and SolidColor quads cannot be batched. They
  // either are not textures (debug, picture, solid color), or it's very likely
  // the texture will have advanced paint effects (rpdq)
  void DrawDebugBorderQuad(const DebugBorderDrawQuad* quad,
                           DrawQuadParams* params);
  void DrawPictureQuad(const PictureDrawQuad* quad, DrawQuadParams* params);
  void DrawRenderPassQuad(const RenderPassDrawQuad* quad,
                          DrawQuadParams* params);
  void DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
                                  const SkImage* content_image,
                                  DrawQuadParams* params);
  void DrawSolidColorQuad(const SolidColorDrawQuad* quad,
                          DrawQuadParams* params);

  void DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
                           DrawQuadParams* params);
  void DrawTextureQuad(const TextureDrawQuad* quad, DrawQuadParams* params);
  void DrawTileDrawQuad(const TileDrawQuad* quad, DrawQuadParams* params);
  void DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, DrawQuadParams* params);
  void DrawUnsupportedQuad(const DrawQuad* quad, DrawQuadParams* params);

  const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;

  // Get corresponding GrContext. Returns nullptr when there is no GrContext.
  // TODO(weiliangc): This currently only returns nullptr. If SKPRecord isn't
  // going to use this later, it should be removed.
  GrContext* GetGrContext();
  bool is_using_ddl() const { return draw_mode_ == DrawMode::DDL; }

  sk_sp<SkColorFilter> GetColorFilter(const gfx::ColorSpace& src,
                                      const gfx::ColorSpace& dst,
                                      float resource_offset,
                                      float resource_multiplier);
  // A map from RenderPass id to the texture used to draw the RenderPass from.
  struct RenderPassBacking {
    sk_sp<SkSurface> render_pass_surface;
    gfx::Size size;
    bool generate_mipmap;
    gfx::ColorSpace color_space;
    ResourceFormat format;

    // Specific for SkPictureRecorder.
    std::unique_ptr<SkPictureRecorder> recorder;
    sk_sp<SkPicture> picture;

    RenderPassBacking(GrContext* gr_context,
                      const gpu::Capabilities& caps,
                      const gfx::Size& size,
                      bool generate_mipmap,
                      const gfx::ColorSpace& color_space);
    RenderPassBacking(const gfx::Size& size,
                      bool generate_mipmap,
                      const gfx::ColorSpace& color_space);
    ~RenderPassBacking();
    RenderPassBacking(RenderPassBacking&&);
    RenderPassBacking& operator=(RenderPassBacking&&);
  };
  base::flat_map<RenderPassId, RenderPassBacking> render_pass_backings_;

  const DrawMode draw_mode_;

  // Interface used for drawing. Common among different draw modes.
  sk_sp<SkSurface> root_surface_;
  SkCanvas* root_canvas_ = nullptr;
  SkCanvas* current_canvas_ = nullptr;
  SkSurface* current_surface_ = nullptr;
  scoped_refptr<ResourceFence> current_frame_resource_fence_;

  bool disable_picture_quad_image_filtering_ = false;
  bool is_scissor_enabled_ = false;
  gfx::Rect scissor_rect_;

  // Specific for overdraw.
  sk_sp<SkSurface> overdraw_surface_;
  std::unique_ptr<SkCanvas> overdraw_canvas_;
  std::unique_ptr<SkNWayCanvas> nway_canvas_;

  // TODO(crbug.com/920344): Use partial swap for SkDDL.
  bool use_swap_with_bounds_ = false;
  gfx::Rect swap_buffer_rect_;
  std::vector<gfx::Rect> swap_content_bounds_;

  // State common to all quads in a batch. Draws that require an SkPaint not
  // captured by this state cannot be batched.
  struct BatchedQuadState {
    base::Optional<gfx::Rect> scissor_rect;
    base::Optional<gfx::RRectF> rounded_corner_bounds;
    SkBlendMode blend_mode;
    SkFilterQuality filter_quality;
    SkCanvas::SrcRectConstraint constraint;

    BatchedQuadState();
  };
  BatchedQuadState batched_quad_state_;
  std::vector<SkCanvas::ImageSetEntry> batched_quads_;
  // Same order as batched_quads_, but only includes draw regions for the
  // entries that have fHasClip == true. Each draw region is 4 consecutive pts
  std::vector<SkPoint> batched_draw_regions_;
  // Each entry of batched_quads_ will have an index into this vector; multiple
  // entries may point to the same matrix.
  std::vector<SkMatrix> batched_cdt_matrices_;

  // Specific for SkDDL.
  SkiaOutputSurface* const skia_output_surface_ = nullptr;

  // Lock set for resources that are used for the current frame. All resources
  // in this set will be unlocked with a sync token when the frame is done in
  // the compositor thread. And the sync token will be released when the DDL
  // for the current frame is replayed on the GPU thread.
  // It is only used with DDL.
  base::Optional<DisplayResourceProvider::LockSetForExternalUse>
      lock_set_for_external_use_;

  // Promise images created from resources used in the current frame. This map
  // will be cleared when the frame is done and before all resources in
  // |lock_set_for_external_use_| are unlocked on the compositor thread.
  // It is only used with DDL.
  base::flat_map<ResourceId, sk_sp<SkImage>> promise_images_;
  using YUVIds = std::tuple<ResourceId, ResourceId, ResourceId, ResourceId>;
  base::flat_map<YUVIds, sk_sp<SkImage>> yuv_promise_images_;

  // Specific for SkPRecord.
  std::unique_ptr<SkPictureRecorder> root_recorder_;
  sk_sp<SkPicture> root_picture_;
  sk_sp<SkPicture>* current_picture_;
  SkPictureRecorder* current_recorder_;
  ContextProvider* context_provider_ = nullptr;
  base::Optional<SyncQueryCollection> sync_queries_;

  std::map<gfx::ColorSpace, std::map<gfx::ColorSpace, sk_sp<SkColorFilter>>>
      color_filter_cache_;

  DISALLOW_COPY_AND_ASSIGN(SkiaRenderer);
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_RENDERER_H_