1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrResourceProvider_DEFINED 9 #define GrResourceProvider_DEFINED 10 11 #include "include/gpu/GrContextOptions.h" 12 #include "include/private/SkImageInfoPriv.h" 13 #include "src/gpu/GrGpuBuffer.h" 14 #include "src/gpu/GrResourceCache.h" 15 16 class GrAttachment; 17 class GrBackendRenderTarget; 18 class GrBackendSemaphore; 19 class GrBackendTexture; 20 class GrGpu; 21 class GrMSAAAttachment; 22 class GrPath; 23 class GrRenderTarget; 24 class GrResourceProviderPriv; 25 class GrSemaphore; 26 class GrSingleOwner; 27 class GrTexture; 28 struct GrVkDrawableInfo; 29 30 class GrStyle; 31 class SkDescriptor; 32 class SkPath; 33 class SkTypeface; 34 35 namespace skgpu { struct VertexWriter; } 36 37 /** 38 * A factory for arbitrary resource types. 39 */ 40 class GrResourceProvider { 41 public: 42 GrResourceProvider(GrGpu*, GrResourceCache*, GrSingleOwner*); 43 44 /** 45 * Finds a resource in the cache, based on the specified key. Prior to calling this, the caller 46 * must be sure that if a resource of exists in the cache with the given unique key then it is 47 * of type T. 48 */ 49 template <typename T = GrGpuResource> 50 typename std::enable_if<std::is_base_of<GrGpuResource, T>::value, sk_sp<T>>::type findByUniqueKey(const GrUniqueKey & key)51 findByUniqueKey(const GrUniqueKey& key) { 52 return sk_sp<T>(static_cast<T*>(this->findResourceByUniqueKey(key).release())); 53 } 54 55 /////////////////////////////////////////////////////////////////////////// 56 // Textures 57 58 /** 59 * Finds a texture that approximately matches the descriptor. Will be at least as large in width 60 * and height as desc specifies. If renderable is kYes then the GrTexture will also be a 61 * GrRenderTarget. The texture's format and sample count will always match the request. 62 * The contents of the texture are undefined. 63 */ 64 sk_sp<GrTexture> createApproxTexture(SkISize dimensions, 65 const GrBackendFormat& format, 66 GrTextureType textureType, 67 GrRenderable renderable, 68 int renderTargetSampleCnt, 69 GrProtected isProtected); 70 71 /** Create an exact fit texture with no initial data to upload. */ 72 sk_sp<GrTexture> createTexture(SkISize dimensions, 73 const GrBackendFormat& format, 74 GrTextureType textureType, 75 GrRenderable renderable, 76 int renderTargetSampleCnt, 77 GrMipmapped mipMapped, 78 SkBudgeted budgeted, 79 GrProtected isProtected); 80 81 /** 82 * Create an exact fit texture with initial data to upload. The color type must be valid 83 * for the format and also describe the texel data. This will ensure any conversions that 84 * need to get applied to the data before upload are applied. 85 */ 86 sk_sp<GrTexture> createTexture(SkISize dimensions, 87 const GrBackendFormat& format, 88 GrTextureType textureType, 89 GrColorType colorType, 90 GrRenderable renderable, 91 int renderTargetSampleCnt, 92 SkBudgeted budgeted, 93 GrMipMapped mipMapped, 94 GrProtected isProtected, 95 const GrMipLevel texels[]); 96 97 /** 98 * Create a potentially loose fit texture with the provided data. The color type must be valid 99 * for the format and also describe the texel data. This will ensure any conversions that 100 * need to get applied to the data before upload are applied. 101 */ 102 sk_sp<GrTexture> createTexture(SkISize dimensions, 103 const GrBackendFormat&, 104 GrTextureType textureType, 105 GrColorType srcColorType, 106 GrRenderable, 107 int renderTargetSampleCnt, 108 SkBudgeted, 109 SkBackingFit, 110 GrProtected, 111 const GrMipLevel& mipLevel); 112 113 /** 114 * Search the cache for a scratch texture matching the provided arguments. Failing that 115 * it returns null. If non-null, the resulting texture is always budgeted. 116 */ 117 sk_sp<GrTexture> findAndRefScratchTexture(const GrScratchKey&); 118 sk_sp<GrTexture> findAndRefScratchTexture(SkISize dimensions, 119 const GrBackendFormat&, 120 GrTextureType textureType, 121 GrRenderable, 122 int renderTargetSampleCnt, 123 GrMipmapped, 124 GrProtected); 125 126 /** 127 * Creates a compressed texture. The GrGpu must support the SkImageImage::Compression type. 128 * It will not be renderable. 129 */ 130 sk_sp<GrTexture> createCompressedTexture(SkISize dimensions, 131 const GrBackendFormat&, 132 SkBudgeted, 133 GrMipmapped, 134 GrProtected, 135 SkData* data); 136 137 /////////////////////////////////////////////////////////////////////////// 138 // Wrapped Backend Surfaces 139 140 /** 141 * Wraps an existing texture with a GrTexture object. 142 * 143 * GrIOType must either be kRead or kRW. kRead blocks any operations that would modify the 144 * pixels (e.g. dst for a copy, regenerating MIP levels, write pixels). 145 * 146 * OpenGL: if the object is a texture Gr may change its GL texture params 147 * when it is drawn. 148 * 149 * @return GrTexture object or NULL on failure. 150 */ 151 sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture& tex, 152 GrWrapOwnership, 153 GrWrapCacheable, 154 GrIOType); 155 156 sk_sp<GrTexture> wrapCompressedBackendTexture(const GrBackendTexture& tex, 157 GrWrapOwnership, 158 GrWrapCacheable); 159 160 /** 161 * This makes the backend texture be renderable. If sampleCnt is > 1 and the underlying API 162 * uses separate MSAA render buffers then a MSAA render buffer is created that resolves 163 * to the texture. 164 */ 165 sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture& tex, 166 int sampleCnt, 167 GrWrapOwnership, 168 GrWrapCacheable); 169 170 /** 171 * Wraps an existing render target with a GrRenderTarget object. It is 172 * similar to wrapBackendTexture but can be used to draw into surfaces 173 * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that 174 * the client will resolve to a texture). Currently wrapped render targets 175 * always use the kBorrow_GrWrapOwnership and GrWrapCacheable::kNo semantics. 176 * 177 * @return GrRenderTarget object or NULL on failure. 178 */ 179 sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&); 180 181 sk_sp<GrRenderTarget> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&, 182 const GrVkDrawableInfo&); 183 184 static const int kMinScratchTextureSize; 185 186 /** 187 * Either finds and refs a buffer with the given unique key, or creates a new new, fills its 188 * contents with the InitializeBufferDataFn() callback, and assigns it the unique key. 189 * 190 * @param intendedType hint to the graphics subsystem about how the buffer will be used. 191 * @param size minimum size of buffer to return. 192 * @param key Key to be assigned to the buffer. 193 * @param InitializeBufferFn callback with which to initialize the buffer. 194 * 195 * @return The buffer if successful, otherwise nullptr. 196 */ 197 using InitializeBufferFn = void(*)(skgpu::VertexWriter, size_t bufferSize); 198 sk_sp<const GrGpuBuffer> findOrMakeStaticBuffer(GrGpuBufferType intendedType, size_t size, 199 const GrUniqueKey& key, InitializeBufferFn); 200 201 /** 202 * Either finds and refs, or creates a static buffer with the given parameters and contents. 203 * 204 * @param intendedType hint to the graphics subsystem about what the buffer will be used for. 205 * @param size minimum size of buffer to return. 206 * @param data optional data with which to initialize the buffer. 207 * @param key Key to be assigned to the buffer. 208 * 209 * @return The buffer if successful, otherwise nullptr. 210 */ 211 sk_sp<const GrGpuBuffer> findOrMakeStaticBuffer(GrGpuBufferType intendedType, size_t size, 212 const void* staticData, const GrUniqueKey& key); 213 214 /** 215 * Either finds and refs, or creates an index buffer with a repeating pattern for drawing 216 * contiguous vertices of a repeated mesh. If the return is non-null, the caller owns a ref on 217 * the returned GrBuffer. 218 * 219 * @param pattern the pattern of indices to repeat 220 * @param patternSize size in bytes of the pattern 221 * @param reps number of times to repeat the pattern 222 * @param vertCount number of vertices the pattern references 223 * @param key Key to be assigned to the index buffer. 224 * 225 * @return The index buffer if successful, otherwise nullptr. 226 */ findOrCreatePatternedIndexBuffer(const uint16_t * pattern,int patternSize,int reps,int vertCount,const GrUniqueKey & key)227 sk_sp<const GrGpuBuffer> findOrCreatePatternedIndexBuffer(const uint16_t* pattern, 228 int patternSize, 229 int reps, 230 int vertCount, 231 const GrUniqueKey& key) { 232 if (auto buffer = this->findByUniqueKey<const GrGpuBuffer>(key)) { 233 return buffer; 234 } 235 return this->createPatternedIndexBuffer(pattern, patternSize, reps, vertCount, &key); 236 } 237 238 /** 239 * Returns an index buffer that can be used to render non-antialiased quads. 240 * Each quad consumes 6 indices (0, 1, 2, 2, 1, 3) and 4 vertices. 241 * Call MaxNumNonAAQuads to get the max allowed number of non-AA quads. 242 * Draw with GrPrimitiveType::kTriangles 243 * @ return the non-AA quad index buffer 244 */ refNonAAQuadIndexBuffer()245 sk_sp<const GrGpuBuffer> refNonAAQuadIndexBuffer() { 246 if (!fNonAAQuadIndexBuffer) { 247 fNonAAQuadIndexBuffer = this->createNonAAQuadIndexBuffer(); 248 } 249 return fNonAAQuadIndexBuffer; 250 } 251 252 static int MaxNumNonAAQuads(); 253 static int NumVertsPerNonAAQuad(); 254 static int NumIndicesPerNonAAQuad(); 255 256 /** 257 * Returns an index buffer that can be used to render antialiased quads. 258 * Each quad consumes 30 indices and 8 vertices. 259 * Call MaxNumAAQuads to get the max allowed number of AA quads. 260 * Draw with GrPrimitiveType::kTriangles 261 * @ return the AA quad index buffer 262 */ refAAQuadIndexBuffer()263 sk_sp<const GrGpuBuffer> refAAQuadIndexBuffer() { 264 if (!fAAQuadIndexBuffer) { 265 fAAQuadIndexBuffer = this->createAAQuadIndexBuffer(); 266 } 267 return fAAQuadIndexBuffer; 268 } 269 270 static int MaxNumAAQuads(); 271 static int NumVertsPerAAQuad(); 272 static int NumIndicesPerAAQuad(); 273 274 /** 275 * Returns a buffer. 276 * 277 * @param size minimum size of buffer to return. 278 * @param intendedType hint to the graphics subsystem about what the buffer will be used for. 279 * @param GrAccessPattern hint to the graphics subsystem about how the data will be accessed. 280 * @param flags see Flags enum. 281 * @param data optional data with which to initialize the buffer. 282 * 283 * @return the buffer if successful, otherwise nullptr. 284 */ 285 sk_sp<GrGpuBuffer> createBuffer(size_t size, 286 GrGpuBufferType intendedType, 287 GrAccessPattern, 288 const void* data = nullptr); 289 290 /** 291 * If passed in render target already has a stencil buffer on the specified surface, return 292 * true. Otherwise attempt to attach one and return true on success. 293 */ 294 bool attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface); 295 296 sk_sp<GrAttachment> makeMSAAAttachment(SkISize dimensions, 297 const GrBackendFormat& format, 298 int sampleCnt, 299 GrProtected isProtected, 300 GrMemoryless isMemoryless); 301 302 /** 303 * Gets a GrAttachment that can be used for MSAA rendering. This attachment may be shared by 304 * other users. Thus any renderpass that uses the attachment should not assume any specific 305 * data at the start and should not try to save written data at the end. Ideally the render pass 306 * should discard the data at the end. 307 */ 308 sk_sp<GrAttachment> getDiscardableMSAAAttachment(SkISize dimensions, 309 const GrBackendFormat& format, 310 int sampleCnt, 311 GrProtected isProtected, 312 GrMemoryless memoryless); 313 314 /** 315 * Assigns a unique key to a resource. If the key is associated with another resource that 316 * association is removed and replaced by this resource. 317 */ 318 void assignUniqueKeyToResource(const GrUniqueKey&, GrGpuResource*); 319 320 std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true); 321 322 std::unique_ptr<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore&, 323 GrSemaphoreWrapType, 324 GrWrapOwnership = kBorrow_GrWrapOwnership); 325 abandon()326 void abandon() { 327 fCache = nullptr; 328 fGpu = nullptr; 329 } 330 contextUniqueID()331 uint32_t contextUniqueID() const { return fCache->contextUniqueID(); } caps()332 const GrCaps* caps() const { return fCaps.get(); } overBudget()333 bool overBudget() const { return fCache->overBudget(); } 334 335 static SkISize MakeApprox(SkISize); 336 337 inline GrResourceProviderPriv priv(); 338 inline const GrResourceProviderPriv priv() const; // NOLINT(readability-const-return-type) 339 340 private: 341 sk_sp<GrGpuResource> findResourceByUniqueKey(const GrUniqueKey&); 342 343 /* 344 * Try to find an existing scratch texture that exactly matches 'desc'. If successful 345 * update the budgeting accordingly. 346 */ 347 sk_sp<GrTexture> getExactScratch(SkISize dimensions, 348 const GrBackendFormat&, 349 GrTextureType, 350 GrRenderable, 351 int renderTargetSampleCnt, 352 SkBudgeted, 353 GrMipmapped, 354 GrProtected); 355 356 // Attempts to find a resource in the cache that exactly matches the SkISize. Failing that 357 // it returns null. If non-null, the resulting msaa attachment is always budgeted. 358 sk_sp<GrAttachment> refScratchMSAAAttachment(SkISize dimensions, 359 const GrBackendFormat&, 360 int sampleCnt, 361 GrProtected, 362 GrMemoryless memoryless); 363 364 // Used to perform any conversions necessary to texel data before creating a texture with 365 // existing data or uploading to a scratch texture. 366 using TempLevels = SkAutoSTArray<14, GrMipLevel>; 367 using TempLevelDatas = SkAutoSTArray<14, std::unique_ptr<char[]>>; 368 GrColorType prepareLevels(const GrBackendFormat& format, 369 GrColorType, 370 SkISize baseSize, 371 const GrMipLevel texels[], 372 int mipLevelCount, 373 TempLevels*, 374 TempLevelDatas*) const; 375 376 // GrResourceProvider may be asked to "create" a new texture with initial pixel data to populate 377 // it. In implementation it may pull an existing texture from GrResourceCache and then write the 378 // pixel data to the texture. It takes a width/height for the base level because we may be 379 // using an approximate-sized scratch texture. On success the texture is returned and nullptr 380 // on failure. 381 sk_sp<GrTexture> writePixels(sk_sp<GrTexture> texture, 382 GrColorType colorType, 383 SkISize baseSize, 384 const GrMipLevel texels[], 385 int mipLevelCount) const; 386 cache()387 GrResourceCache* cache() { return fCache; } cache()388 const GrResourceCache* cache() const { return fCache; } 389 390 friend class GrResourceProviderPriv; 391 392 // Method made available via GrResourceProviderPriv gpu()393 GrGpu* gpu() { return fGpu; } gpu()394 const GrGpu* gpu() const { return fGpu; } 395 isAbandoned()396 bool isAbandoned() const { 397 SkASSERT(SkToBool(fGpu) == SkToBool(fCache)); 398 return !SkToBool(fCache); 399 } 400 401 sk_sp<const GrGpuBuffer> createPatternedIndexBuffer(const uint16_t* pattern, 402 int patternSize, 403 int reps, 404 int vertCount, 405 const GrUniqueKey* key); 406 407 sk_sp<const GrGpuBuffer> createNonAAQuadIndexBuffer(); 408 sk_sp<const GrGpuBuffer> createAAQuadIndexBuffer(); 409 410 GrResourceCache* fCache; 411 GrGpu* fGpu; 412 sk_sp<const GrCaps> fCaps; 413 sk_sp<const GrGpuBuffer> fNonAAQuadIndexBuffer; 414 sk_sp<const GrGpuBuffer> fAAQuadIndexBuffer; 415 416 // In debug builds we guard against improper thread handling 417 SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;) 418 }; 419 420 #endif 421