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