1 // Copyright 2017 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_PROVIDER_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_PROVIDER_H_ 7 8 #include "cc/paint/skia_paint_canvas.h" 9 #include "cc/raster/playback_image_provider.h" 10 #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" 11 #include "third_party/blink/renderer/platform/graphics/image_orientation.h" 12 #include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h" 13 #include "third_party/skia/include/core/SkSurface.h" 14 15 class GrContext; 16 17 namespace cc { 18 class ImageDecodeCache; 19 class PaintCanvas; 20 } // namespace cc 21 22 namespace gpu { 23 namespace gles2 { 24 25 class GLES2Interface; 26 27 } // namespace gles2 28 29 namespace raster { 30 31 class RasterInterface; 32 33 } // namespace raster 34 } // namespace gpu 35 36 namespace blink { 37 38 class CanvasResourceDispatcher; 39 class WebGraphicsContext3DProviderWrapper; 40 41 // CanvasResourceProvider 42 //============================================================================== 43 // 44 // This is an abstract base class that encapsulates a drawable graphics 45 // resource. Subclasses manage specific resource types (Gpu Textures, 46 // GpuMemoryBuffer, Bitmap in RAM). CanvasResourceProvider serves as an 47 // abstraction layer for these resource types. It is designed to serve 48 // the needs of Canvas2DLayerBridge, but can also be used as a general purpose 49 // provider of drawable surfaces for 2D rendering with skia. 50 // 51 // General usage: 52 // 1) Use the Create() static method to create an instance 53 // 2) use Canvas() to get a drawing interface 54 // 3) Call Snapshot() to acquire a bitmap with the rendered image in it. 55 56 class PLATFORM_EXPORT CanvasResourceProvider 57 : public WebGraphicsContext3DProviderWrapper::DestructionObserver { 58 public: 59 // These values are persisted to logs. Entries should not be renumbered and 60 // numeric values should never be reused. 61 // todo(juanmihd@) ResourceUsage will be removed soon, try avoiding using this 62 enum class ResourceUsage { 63 kSoftwareResourceUsage = 0, // deprecated 64 kSoftwareCompositedResourceUsage = 1, 65 kAcceleratedResourceUsage = 2, 66 kAcceleratedCompositedResourceUsage = 3, 67 kAcceleratedDirect2DResourceUsage = 4, 68 kAcceleratedDirect3DResourceUsage = 5, 69 kSoftwareCompositedDirect2DResourceUsage = 6, // deprecated 70 kMaxValue = kSoftwareCompositedDirect2DResourceUsage, 71 }; 72 73 // Bitmask of allowed presentation modes. 74 enum : uint8_t { 75 // GPU Texture or shared memory bitmap 76 kDefaultPresentationMode = 0, 77 // Allow CHROMIUM_image gl extension 78 kAllowImageChromiumPresentationMode = 1 << 0, 79 // Allow swap chains (only on Windows) 80 kAllowSwapChainPresentationMode = 1 << 1, 81 }; 82 83 // These values are persisted to logs. Entries should not be renumbered and 84 // numeric values should never be reused. 85 enum ResourceProviderType { 86 kTexture = 0, 87 kBitmap = 1, 88 kSharedBitmap = 2, 89 kTextureGpuMemoryBuffer = 3, 90 kBitmapGpuMemoryBuffer = 4, 91 kSharedImage = 5, 92 kDirectGpuMemoryBuffer = 6, 93 kPassThrough = 7, 94 kSwapChain = 8, 95 kMaxValue = kSwapChain, 96 }; 97 98 using RestoreMatrixClipStackCb = 99 base::RepeatingCallback<void(cc::PaintCanvas*)>; 100 101 // todo(juanmihd@) Check whether SkFilterQuality is needed in all of this, or 102 // just call setFilterQuality explicitly 103 static std::unique_ptr<CanvasResourceProvider> CreateBitmapProvider( 104 const IntSize&, 105 SkFilterQuality, 106 const CanvasColorParams&); 107 108 // Specifies whether the provider should rasterize paint commands on the CPU 109 // or GPU. This is used to support software raster with GPU compositing 110 enum class RasterMode { 111 kGPU, 112 kCPU, 113 }; 114 115 static std::unique_ptr<CanvasResourceProvider> CreateSharedImageProvider( 116 const IntSize&, 117 base::WeakPtr<WebGraphicsContext3DProviderWrapper>, 118 SkFilterQuality, 119 const CanvasColorParams&, 120 bool is_origin_top_left, 121 RasterMode raster_mode, 122 uint32_t shared_image_usage_flags); 123 124 // TODO(juanmihd): Clean up creation methods/usage. See crbug.com/1035589. 125 static std::unique_ptr<CanvasResourceProvider> Create( 126 const IntSize&, 127 ResourceUsage, 128 base::WeakPtr<WebGraphicsContext3DProviderWrapper>, 129 unsigned msaa_sample_count, 130 SkFilterQuality, 131 const CanvasColorParams&, 132 uint8_t presentation_mode, 133 base::WeakPtr<CanvasResourceDispatcher>, 134 bool is_origin_top_left = true); 135 136 // Use Snapshot() for capturing a frame that is intended to be displayed via 137 // the compositor. Cases that are destined to be transferred via a 138 // TransferableResource should call ProduceCanvasResource() instead. 139 // The ImageOrientationEnum conveys the desired orientation of the image, and 140 // should be derived from the source of the bitmap data. 141 virtual scoped_refptr<CanvasResource> ProduceCanvasResource() = 0; 142 virtual scoped_refptr<StaticBitmapImage> Snapshot( 143 const ImageOrientation& = kDefaultImageOrientation) = 0; 144 145 // WebGraphicsContext3DProvider::DestructionObserver implementation. 146 void OnContextDestroyed() override; 147 148 cc::PaintCanvas* Canvas(); 149 void ReleaseLockedImages(); 150 sk_sp<cc::PaintRecord> FlushCanvas(); ColorParams()151 const CanvasColorParams& ColorParams() const { return color_params_; } SetFilterQuality(SkFilterQuality quality)152 void SetFilterQuality(SkFilterQuality quality) { filter_quality_ = quality; } Size()153 const IntSize& Size() const { return size_; } IsOriginTopLeft()154 bool IsOriginTopLeft() const { return is_origin_top_left_; } 155 virtual bool IsValid() const = 0; 156 virtual bool IsAccelerated() const = 0; 157 // Returns true if the resource can be used by the display compositor. 158 virtual bool SupportsDirectCompositing() const = 0; SupportsSingleBuffering()159 virtual bool SupportsSingleBuffering() const { return false; } 160 uint32_t ContentUniqueID() const; ResourceDispatcher()161 CanvasResourceDispatcher* ResourceDispatcher() { 162 return resource_dispatcher_.get(); 163 } 164 165 // Indicates that the compositing path is single buffered, meaning that 166 // ProduceCanvasResource() return a reference to the same resource each time, 167 // which implies that Producing an animation frame may overwrite the resource 168 // used by the previous frame. This results in graphics updates skipping the 169 // queue, thus reducing latency, but with the possible side effects of tearing 170 // (in cases where the resource is scanned out directly) and irregular frame 171 // rate. IsSingleBuffered()172 bool IsSingleBuffered() const { return is_single_buffered_; } 173 174 // Attempt to enable single buffering mode on this resource provider. May 175 // fail if the CanvasResourcePRovider subclass does not support this mode of 176 // operation. 177 void TryEnableSingleBuffering(); 178 179 // Only works in single buffering mode. 180 bool ImportResource(scoped_refptr<CanvasResource>); 181 182 void RecycleResource(scoped_refptr<CanvasResource>); 183 void SetResourceRecyclingEnabled(bool); 184 void ClearRecycledResources(); 185 scoped_refptr<CanvasResource> NewOrRecycledResource(); 186 187 SkSurface* GetSkSurface() const; 188 bool IsGpuContextLost() const; 189 bool WritePixels(const SkImageInfo& orig_info, 190 const void* pixels, 191 size_t row_bytes, 192 int x, 193 int y); 194 GetBackingMailboxForOverwrite(MailboxSyncMode sync_mode)195 virtual gpu::Mailbox GetBackingMailboxForOverwrite( 196 MailboxSyncMode sync_mode) { 197 NOTREACHED(); 198 return gpu::Mailbox(); 199 } GetBackingTextureTarget()200 virtual GLenum GetBackingTextureTarget() const { return GL_TEXTURE_2D; } GetPixelBufferAddressForOverwrite()201 virtual void* GetPixelBufferAddressForOverwrite() { 202 NOTREACHED(); 203 return nullptr; 204 } 205 void Clear(); 206 ~CanvasResourceProvider() override; 207 CreateWeakPtr()208 base::WeakPtr<CanvasResourceProvider> CreateWeakPtr() { 209 return weak_ptr_factory_.GetWeakPtr(); 210 } 211 212 // Notifies the provider when the texture params associated with |resource| 213 // are modified externally from the provider's SkSurface. NotifyTexParamsModified(const CanvasResource * resource)214 virtual void NotifyTexParamsModified(const CanvasResource* resource) {} 215 cached_resources_count_for_testing()216 size_t cached_resources_count_for_testing() const { 217 return canvas_resources_.size(); 218 } 219 220 void SkipQueuedDrawCommands(); 221 void SetRestoreClipStackCallback(RestoreMatrixClipStackCb); needs_flush()222 bool needs_flush() const { return needs_flush_; } 223 void RestoreBackBuffer(const cc::PaintImage&); 224 GetType()225 ResourceProviderType GetType() const { return type_; } 226 bool HasRecordedDrawOps() const; 227 228 void OnDestroyResource(); 229 230 protected: 231 class CanvasImageProvider; 232 233 gpu::gles2::GLES2Interface* ContextGL() const; 234 gpu::raster::RasterInterface* RasterInterface() const; 235 GrContext* GetGrContext() const; ContextProviderWrapper()236 base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper() { 237 return context_provider_wrapper_; 238 } GetMSAASampleCount()239 unsigned GetMSAASampleCount() const { return msaa_sample_count_; } GetGrSurfaceOrigin()240 GrSurfaceOrigin GetGrSurfaceOrigin() const { 241 return is_origin_top_left_ ? kTopLeft_GrSurfaceOrigin 242 : kBottomLeft_GrSurfaceOrigin; 243 } FilterQuality()244 SkFilterQuality FilterQuality() const { return filter_quality_; } 245 scoped_refptr<StaticBitmapImage> SnapshotInternal(const ImageOrientation&); 246 scoped_refptr<CanvasResource> GetImportedResource() const; 247 248 CanvasResourceProvider(const ResourceProviderType&, 249 const IntSize&, 250 unsigned msaa_sample_count, 251 SkFilterQuality, 252 const CanvasColorParams&, 253 bool is_origin_top_left, 254 base::WeakPtr<WebGraphicsContext3DProviderWrapper>, 255 base::WeakPtr<CanvasResourceDispatcher>); 256 257 // Its important to use this method for generating PaintImage wrapped canvas 258 // snapshots to get a cache hit from cc's ImageDecodeCache. This method 259 // ensures that the PaintImage ID for the snapshot, used for keying 260 // decodes/uploads in the cache is invalidated only when the canvas contents 261 // change. 262 cc::PaintImage MakeImageSnapshot(); 263 virtual void RasterRecord(sk_sp<cc::PaintRecord>); 264 CanvasImageProvider* GetOrCreateCanvasImageProvider(); 265 266 ResourceProviderType type_; 267 mutable sk_sp<SkSurface> surface_; // mutable for lazy init 268 SkSurface::ContentChangeMode mode_ = SkSurface::kRetain_ContentChangeMode; 269 270 private: 271 virtual sk_sp<SkSurface> CreateSkSurface() const = 0; 272 virtual scoped_refptr<CanvasResource> CreateResource(); use_hardware_decode_cache()273 bool use_hardware_decode_cache() const { 274 return IsAccelerated() && context_provider_wrapper_; 275 } 276 // Notifies before any drawing will be done on the resource used by this 277 // provider. WillDraw()278 virtual void WillDraw() {} 279 280 cc::ImageDecodeCache* ImageDecodeCacheRGBA8(); 281 cc::ImageDecodeCache* ImageDecodeCacheF16(); 282 void EnsureSkiaCanvas(); SetNeedsFlush()283 void SetNeedsFlush() { needs_flush_ = true; } 284 285 base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_; 286 base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher_; 287 const IntSize size_; 288 const unsigned msaa_sample_count_; 289 SkFilterQuality filter_quality_; 290 const CanvasColorParams color_params_; 291 const bool is_origin_top_left_; 292 std::unique_ptr<CanvasImageProvider> canvas_image_provider_; 293 std::unique_ptr<cc::SkiaPaintCanvas> skia_canvas_; 294 std::unique_ptr<PaintRecorder> recorder_; 295 296 bool needs_flush_ = false; 297 298 const cc::PaintImage::Id snapshot_paint_image_id_; 299 cc::PaintImage::ContentId snapshot_paint_image_content_id_ = 300 cc::PaintImage::kInvalidContentId; 301 uint32_t snapshot_sk_image_id_ = 0u; 302 303 // When and if |resource_recycling_enabled_| is false, |canvas_resources_| 304 // will only hold one CanvasResource at most. 305 WTF::Vector<scoped_refptr<CanvasResource>> canvas_resources_; 306 bool resource_recycling_enabled_ = true; 307 bool is_single_buffered_ = false; 308 309 // The maximum number of in-flight resources waiting to be used for recycling. 310 static constexpr int kMaxRecycledCanvasResources = 2; 311 // The maximum number of draw ops executed on the canvas, after which the 312 // underlying GrContext is flushed. 313 static constexpr int kMaxDrawsBeforeContextFlush = 50; 314 315 size_t num_inflight_resources_ = 0; 316 size_t max_inflight_resources_ = 0; 317 318 RestoreMatrixClipStackCb restore_clip_stack_callback_; 319 320 base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_{this}; 321 322 DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider); 323 }; 324 325 } // namespace blink 326 327 #endif 328