| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 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 | #include "GrResourceProvider.h" | 
 | 9 |  | 
| cdalton | 397536c | 2016-03-25 12:15:03 -0700 | [diff] [blame] | 10 | #include "GrBuffer.h" | 
| robertphillips | 5fa7f30 | 2016-07-21 09:21:04 -0700 | [diff] [blame] | 11 | #include "GrCaps.h" | 
| Robert Phillips | 26c90e0 | 2017-03-14 14:39:29 -0400 | [diff] [blame] | 12 | #include "GrContext.h" | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 13 | #include "GrContextPriv.h" | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 14 | #include "GrGpu.h" | 
| kkinnunen | cabe20c | 2015-06-01 01:37:26 -0700 | [diff] [blame] | 15 | #include "GrPathRendering.h" | 
| egdaniel | ec00d94 | 2015-09-14 12:56:10 -0700 | [diff] [blame] | 16 | #include "GrRenderTarget.h" | 
 | 17 | #include "GrRenderTargetPriv.h" | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 18 | #include "GrResourceCache.h" | 
 | 19 | #include "GrResourceKey.h" | 
| Greg Daniel | d85f97d | 2017-03-07 13:37:21 -0500 | [diff] [blame] | 20 | #include "GrSemaphore.h" | 
| egdaniel | ec00d94 | 2015-09-14 12:56:10 -0700 | [diff] [blame] | 21 | #include "GrStencilAttachment.h" | 
| Robert Phillips | b66b42f | 2017-03-14 08:53:02 -0400 | [diff] [blame] | 22 | #include "GrSurfaceProxyPriv.h" | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 23 | #include "GrTexturePriv.h" | 
 | 24 | #include "../private/GrSingleOwner.h" | 
| Robert Phillips | 45fdae1 | 2017-04-17 12:57:27 -0400 | [diff] [blame] | 25 | #include "SkGr.h" | 
| halcanary | 4dbbd04 | 2016-06-07 17:21:10 -0700 | [diff] [blame] | 26 | #include "SkMathPriv.h" | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 27 |  | 
 | 28 | GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey); | 
 | 29 |  | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 30 | const int GrResourceProvider::kMinScratchTextureSize = 16; | 
 | 31 |  | 
 | 32 | #define ASSERT_SINGLE_OWNER \ | 
 | 33 |     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) | 
 | 34 |  | 
| joshualitt | 6d0872d | 2016-01-11 08:27:48 -0800 | [diff] [blame] | 35 | GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner) | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 36 |         : fCache(cache) | 
 | 37 |         , fGpu(gpu) | 
 | 38 | #ifdef SK_DEBUG | 
 | 39 |         , fSingleOwner(owner) | 
 | 40 | #endif | 
 | 41 |         { | 
| Robert Phillips | 26c90e0 | 2017-03-14 14:39:29 -0400 | [diff] [blame] | 42 |     fCaps = sk_ref_sp(fGpu->caps()); | 
 | 43 |  | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 44 |     GR_DEFINE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey); | 
 | 45 |     fQuadIndexBufferKey = gQuadIndexBufferKey; | 
 | 46 | } | 
 | 47 |  | 
| Robert Phillips | f7a7261 | 2017-03-31 10:03:45 -0400 | [diff] [blame] | 48 | bool GrResourceProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) { | 
| Robert Phillips | b66b42f | 2017-03-14 08:53:02 -0400 | [diff] [blame] | 49 |     return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height())); | 
 | 50 | } | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 51 |  | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 52 | // MDB TODO: this should probably be a factory on GrSurfaceProxy | 
 | 53 | sk_sp<GrTextureProxy> GrResourceProvider::createMipMappedTexture( | 
 | 54 |                                                       const GrSurfaceDesc& desc, | 
 | 55 |                                                       SkBudgeted budgeted, | 
 | 56 |                                                       const GrMipLevel* texels, | 
 | 57 |                                                       int mipLevelCount, | 
| Robert Phillips | a4c41b3 | 2017-03-15 13:02:45 -0400 | [diff] [blame] | 58 |                                                       SkDestinationSurfaceColorMode mipColorMode) { | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 59 |     ASSERT_SINGLE_OWNER | 
 | 60 |  | 
| Robert Phillips | 1119dc3 | 2017-04-11 12:54:57 -0400 | [diff] [blame] | 61 |     if (!mipLevelCount) { | 
 | 62 |         if (texels) { | 
 | 63 |             return nullptr; | 
 | 64 |         } | 
 | 65 |         return GrSurfaceProxy::MakeDeferred(this, desc, budgeted, nullptr, 0); | 
| Robert Phillips | 45fdae1 | 2017-04-17 12:57:27 -0400 | [diff] [blame] | 66 |     } else if (1 == mipLevelCount) { | 
 | 67 |         if (!texels) { | 
 | 68 |             return nullptr; | 
 | 69 |         } | 
 | 70 |         return this->createTextureProxy(desc, budgeted, texels[0]); | 
| Robert Phillips | 1119dc3 | 2017-04-11 12:54:57 -0400 | [diff] [blame] | 71 |     } | 
 | 72 |  | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 73 |     if (this->isAbandoned()) { | 
 | 74 |         return nullptr; | 
 | 75 |     } | 
| Robert Phillips | 1119dc3 | 2017-04-11 12:54:57 -0400 | [diff] [blame] | 76 |  | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 77 |     if (mipLevelCount > 1 && GrPixelConfigIsSint(desc.fConfig)) { | 
 | 78 |         return nullptr; | 
 | 79 |     } | 
 | 80 |     if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) && | 
 | 81 |         !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { | 
 | 82 |         return nullptr; | 
 | 83 |     } | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 84 |  | 
 | 85 |     SkTArray<GrMipLevel> texelsShallowCopy(mipLevelCount); | 
 | 86 |     for (int i = 0; i < mipLevelCount; ++i) { | 
| Robert Phillips | 45fdae1 | 2017-04-17 12:57:27 -0400 | [diff] [blame] | 87 |         if (!texels[i].fPixels) { | 
 | 88 |             return nullptr; | 
 | 89 |         } | 
 | 90 |  | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 91 |         texelsShallowCopy.push_back(texels[i]); | 
 | 92 |     } | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 93 |     sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, texelsShallowCopy)); | 
 | 94 |     if (tex) { | 
 | 95 |         tex->texturePriv().setMipColorMode(mipColorMode); | 
| Robert Phillips | a4c41b3 | 2017-03-15 13:02:45 -0400 | [diff] [blame] | 96 |     } | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 97 |  | 
 | 98 |     return GrSurfaceProxy::MakeWrapped(std::move(tex)); | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 99 | } | 
 | 100 |  | 
| Robert Phillips | 45fdae1 | 2017-04-17 12:57:27 -0400 | [diff] [blame] | 101 | sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc, | 
 | 102 |                                                      SkBudgeted budgeted, uint32_t flags) { | 
 | 103 |  | 
 | 104 |     flags |= kExact_Flag | kNoCreate_Flag; | 
 | 105 |     sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags)); | 
 | 106 |     if (tex && SkBudgeted::kNo == budgeted) { | 
 | 107 |         tex->resourcePriv().makeUnbudgeted(); | 
 | 108 |     } | 
 | 109 |  | 
 | 110 |     return tex; | 
 | 111 | } | 
 | 112 |  | 
 | 113 | static bool make_info(int w, int h, GrPixelConfig config, SkImageInfo* ii) { | 
 | 114 |     SkColorType colorType; | 
 | 115 |     if (!GrPixelConfigToColorType(config, &colorType)) { | 
 | 116 |         return false; | 
 | 117 |     } | 
 | 118 |  | 
 | 119 |     *ii = SkImageInfo::Make(w, h, colorType, kUnknown_SkAlphaType, nullptr); | 
 | 120 |     return true; | 
 | 121 | } | 
 | 122 |  | 
 | 123 | sk_sp<GrTextureProxy> GrResourceProvider::createTextureProxy(const GrSurfaceDesc& desc, | 
 | 124 |                                                              SkBudgeted budgeted, | 
 | 125 |                                                              const GrMipLevel& mipLevel) { | 
| Robert Phillips | 774831a | 2017-04-20 10:19:33 -0400 | [diff] [blame^] | 126 |     ASSERT_SINGLE_OWNER | 
 | 127 |  | 
 | 128 |     if (this->isAbandoned()) { | 
 | 129 |         return nullptr; | 
 | 130 |     } | 
 | 131 |  | 
| Robert Phillips | 45fdae1 | 2017-04-17 12:57:27 -0400 | [diff] [blame] | 132 |     if (!mipLevel.fPixels) { | 
 | 133 |         return nullptr; | 
 | 134 |     } | 
 | 135 |  | 
 | 136 |     GrContext* context = fGpu->getContext(); | 
 | 137 |  | 
 | 138 |     if (!GrPixelConfigIsCompressed(desc.fConfig)) { | 
 | 139 |         SkImageInfo srcInfo; | 
 | 140 |  | 
 | 141 |         if (make_info(desc.fWidth, desc.fHeight, desc.fConfig, &srcInfo)) { | 
 | 142 |             sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, 0); | 
 | 143 |             sk_sp<GrSurfaceContext> sContext = | 
 | 144 |                                 context->contextPriv().makeWrappedSurfaceContext(std::move(tex)); | 
 | 145 |             if (sContext) { | 
 | 146 |                 if (sContext->writePixels(srcInfo, mipLevel.fPixels, mipLevel.fRowBytes, 0, 0)) { | 
 | 147 |                     return sContext->asTextureProxyRef(); | 
 | 148 |                 } | 
 | 149 |             } | 
 | 150 |         } | 
 | 151 |     } | 
 | 152 |  | 
 | 153 |     SkTArray<GrMipLevel> texels(1); | 
 | 154 |     texels.push_back(mipLevel); | 
 | 155 |  | 
 | 156 |     sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, texels)); | 
 | 157 |     return GrSurfaceProxy::MakeWrapped(std::move(tex)); | 
 | 158 | } | 
 | 159 |  | 
 | 160 |  | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 161 | sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, | 
 | 162 |                                                    uint32_t flags) { | 
 | 163 |     ASSERT_SINGLE_OWNER | 
 | 164 |  | 
 | 165 |     if (this->isAbandoned()) { | 
 | 166 |         return nullptr; | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 167 |     } | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 168 |  | 
 | 169 |     if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) && | 
 | 170 |         !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { | 
 | 171 |         return nullptr; | 
 | 172 |     } | 
 | 173 |  | 
 | 174 |     if (!GrPixelConfigIsCompressed(desc.fConfig)) { | 
| Robert Phillips | 45fdae1 | 2017-04-17 12:57:27 -0400 | [diff] [blame] | 175 |         sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, flags); | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 176 |         if (tex) { | 
| Robert Phillips | e78b725 | 2017-04-06 07:59:41 -0400 | [diff] [blame] | 177 |             return tex; | 
 | 178 |         } | 
 | 179 |     } | 
 | 180 |  | 
 | 181 |     sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted)); | 
 | 182 |     return tex; | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 183 | } | 
 | 184 |  | 
 | 185 | GrTexture* GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) { | 
 | 186 |     ASSERT_SINGLE_OWNER | 
 | 187 |     SkASSERT(0 == flags || kNoPendingIO_Flag == flags); | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 188 |  | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 189 |     if (this->isAbandoned()) { | 
 | 190 |         return nullptr; | 
 | 191 |     } | 
| Robert Phillips | 1119dc3 | 2017-04-11 12:54:57 -0400 | [diff] [blame] | 192 |  | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 193 |     // Currently we don't recycle compressed textures as scratch. | 
 | 194 |     if (GrPixelConfigIsCompressed(desc.fConfig)) { | 
 | 195 |         return nullptr; | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 196 |     } | 
| Robert Phillips | 1119dc3 | 2017-04-11 12:54:57 -0400 | [diff] [blame] | 197 |  | 
 | 198 |     return this->refScratchTexture(desc, flags); | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 199 | } | 
 | 200 |  | 
 | 201 | GrTexture* GrResourceProvider::refScratchTexture(const GrSurfaceDesc& inDesc, | 
 | 202 |                                                  uint32_t flags) { | 
 | 203 |     ASSERT_SINGLE_OWNER | 
 | 204 |     SkASSERT(!this->isAbandoned()); | 
 | 205 |     SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig)); | 
 | 206 |  | 
 | 207 |     SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc); | 
 | 208 |  | 
 | 209 |     if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) { | 
 | 210 |         if (!(kExact_Flag & flags)) { | 
 | 211 |             // bin by pow2 with a reasonable min | 
 | 212 |             GrSurfaceDesc* wdesc = desc.writable(); | 
 | 213 |             wdesc->fWidth  = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fWidth)); | 
 | 214 |             wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc->fHeight)); | 
 | 215 |         } | 
 | 216 |  | 
 | 217 |         GrScratchKey key; | 
 | 218 |         GrTexturePriv::ComputeScratchKey(*desc, &key); | 
 | 219 |         uint32_t scratchFlags = 0; | 
 | 220 |         if (kNoPendingIO_Flag & flags) { | 
 | 221 |             scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag; | 
 | 222 |         } else  if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) { | 
 | 223 |             // If it is not a render target then it will most likely be populated by | 
 | 224 |             // writePixels() which will trigger a flush if the texture has pending IO. | 
 | 225 |             scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag; | 
 | 226 |         } | 
 | 227 |         GrGpuResource* resource = fCache->findAndRefScratchResource(key, | 
 | 228 |                                                                    GrSurface::WorstCaseSize(*desc), | 
 | 229 |                                                                    scratchFlags); | 
 | 230 |         if (resource) { | 
 | 231 |             GrSurface* surface = static_cast<GrSurface*>(resource); | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 232 |             return surface->asTexture(); | 
 | 233 |         } | 
 | 234 |     } | 
 | 235 |  | 
 | 236 |     if (!(kNoCreate_Flag & flags)) { | 
 | 237 |         return fGpu->createTexture(*desc, SkBudgeted::kYes); | 
 | 238 |     } | 
 | 239 |  | 
 | 240 |     return nullptr; | 
 | 241 | } | 
 | 242 |  | 
| Stan Iliev | 7fa5c31 | 2017-04-19 00:23:39 +0000 | [diff] [blame] | 243 | sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTextureDesc& desc, | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 244 |                                                         GrWrapOwnership ownership) { | 
 | 245 |     ASSERT_SINGLE_OWNER | 
 | 246 |     if (this->isAbandoned()) { | 
 | 247 |         return nullptr; | 
 | 248 |     } | 
| Stan Iliev | 7fa5c31 | 2017-04-19 00:23:39 +0000 | [diff] [blame] | 249 |     return fGpu->wrapBackendTexture(desc, ownership); | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 250 | } | 
 | 251 |  | 
 | 252 | sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget( | 
 | 253 |         const GrBackendRenderTargetDesc& desc) | 
 | 254 | { | 
 | 255 |     ASSERT_SINGLE_OWNER | 
| Brian Osman | 0b791f5 | 2017-03-10 08:30:22 -0500 | [diff] [blame] | 256 |     return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc); | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 257 | } | 
 | 258 |  | 
 | 259 | void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key, | 
 | 260 |                                                    GrGpuResource* resource) { | 
 | 261 |     ASSERT_SINGLE_OWNER | 
 | 262 |     if (this->isAbandoned() || !resource) { | 
 | 263 |         return; | 
 | 264 |     } | 
 | 265 |     resource->resourcePriv().setUniqueKey(key); | 
 | 266 | } | 
 | 267 |  | 
 | 268 | GrGpuResource* GrResourceProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) { | 
 | 269 |     ASSERT_SINGLE_OWNER | 
 | 270 |     return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key); | 
 | 271 | } | 
 | 272 |  | 
 | 273 | GrTexture* GrResourceProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) { | 
 | 274 |     ASSERT_SINGLE_OWNER | 
 | 275 |     GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key); | 
 | 276 |     if (resource) { | 
 | 277 |         GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture(); | 
 | 278 |         SkASSERT(texture); | 
 | 279 |         return texture; | 
 | 280 |     } | 
 | 281 |     return NULL; | 
 | 282 | } | 
 | 283 |  | 
| Robert Phillips | d374948 | 2017-03-14 09:17:43 -0400 | [diff] [blame] | 284 | // MDB TODO (caching): this side-steps the issue of texture proxies with unique IDs | 
 | 285 | void GrResourceProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) { | 
 | 286 |     ASSERT_SINGLE_OWNER | 
 | 287 |     SkASSERT(key.isValid()); | 
 | 288 |     if (this->isAbandoned() || !proxy) { | 
 | 289 |         return; | 
 | 290 |     } | 
 | 291 |  | 
 | 292 |     GrTexture* texture = proxy->instantiate(this); | 
 | 293 |     if (!texture) { | 
 | 294 |         return; | 
 | 295 |     } | 
 | 296 |  | 
 | 297 |     this->assignUniqueKeyToResource(key, texture); | 
 | 298 | } | 
 | 299 |  | 
 | 300 | // MDB TODO (caching): this side-steps the issue of texture proxies with unique IDs | 
 | 301 | sk_sp<GrTextureProxy> GrResourceProvider::findProxyByUniqueKey(const GrUniqueKey& key) { | 
 | 302 |     ASSERT_SINGLE_OWNER | 
 | 303 |  | 
 | 304 |     sk_sp<GrTexture> texture(this->findAndRefTextureByUniqueKey(key)); | 
 | 305 |     if (!texture) { | 
 | 306 |         return nullptr; | 
 | 307 |     } | 
 | 308 |  | 
 | 309 |     return GrSurfaceProxy::MakeWrapped(std::move(texture)); | 
 | 310 | } | 
 | 311 |  | 
| cdalton | 397536c | 2016-03-25 12:15:03 -0700 | [diff] [blame] | 312 | const GrBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* pattern, | 
 | 313 |                                                                int patternSize, | 
 | 314 |                                                                int reps, | 
 | 315 |                                                                int vertCount, | 
 | 316 |                                                                const GrUniqueKey& key) { | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 317 |     size_t bufferSize = patternSize * reps * sizeof(uint16_t); | 
 | 318 |  | 
| Brian Salomon | 09d994e | 2016-12-21 11:14:46 -0500 | [diff] [blame] | 319 |     // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO. | 
| cdalton | e2e71c2 | 2016-04-07 18:13:29 -0700 | [diff] [blame] | 320 |     GrBuffer* buffer = this->createBuffer(bufferSize, kIndex_GrBufferType, kStatic_GrAccessPattern, | 
| cdalton | 397536c | 2016-03-25 12:15:03 -0700 | [diff] [blame] | 321 |                                           kNoPendingIO_Flag); | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 322 |     if (!buffer) { | 
| halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 323 |         return nullptr; | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 324 |     } | 
 | 325 |     uint16_t* data = (uint16_t*) buffer->map(); | 
| halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 326 |     bool useTempData = (nullptr == data); | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 327 |     if (useTempData) { | 
| halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 328 |         data = new uint16_t[reps * patternSize]; | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 329 |     } | 
 | 330 |     for (int i = 0; i < reps; ++i) { | 
 | 331 |         int baseIdx = i * patternSize; | 
 | 332 |         uint16_t baseVert = (uint16_t)(i * vertCount); | 
 | 333 |         for (int j = 0; j < patternSize; ++j) { | 
 | 334 |             data[baseIdx+j] = baseVert + pattern[j]; | 
 | 335 |         } | 
 | 336 |     } | 
 | 337 |     if (useTempData) { | 
 | 338 |         if (!buffer->updateData(data, bufferSize)) { | 
 | 339 |             buffer->unref(); | 
| halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 340 |             return nullptr; | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 341 |         } | 
| halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 342 |         delete[] data; | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 343 |     } else { | 
 | 344 |         buffer->unmap(); | 
 | 345 |     } | 
 | 346 |     this->assignUniqueKeyToResource(key, buffer); | 
 | 347 |     return buffer; | 
 | 348 | } | 
 | 349 |  | 
| cdalton | 397536c | 2016-03-25 12:15:03 -0700 | [diff] [blame] | 350 | const GrBuffer* GrResourceProvider::createQuadIndexBuffer() { | 
| bsalomon | ed0bcad | 2015-05-04 10:36:42 -0700 | [diff] [blame] | 351 |     static const int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1; | 
 | 352 |     GR_STATIC_ASSERT(4 * kMaxQuads <= 65535); | 
 | 353 |     static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 }; | 
 | 354 |  | 
 | 355 |     return this->createInstancedIndexBuffer(kPattern, 6, kMaxQuads, 4, fQuadIndexBufferKey); | 
 | 356 | } | 
 | 357 |  | 
| bsalomon | 6663acf | 2016-05-10 09:14:17 -0700 | [diff] [blame] | 358 | GrPath* GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) { | 
| bsalomon | 706f08f | 2015-05-22 07:35:58 -0700 | [diff] [blame] | 359 |     SkASSERT(this->gpu()->pathRendering()); | 
| bsalomon | 6663acf | 2016-05-10 09:14:17 -0700 | [diff] [blame] | 360 |     return this->gpu()->pathRendering()->createPath(path, style); | 
| bsalomon | 706f08f | 2015-05-22 07:35:58 -0700 | [diff] [blame] | 361 | } | 
 | 362 |  | 
 | 363 | GrPathRange* GrResourceProvider::createPathRange(GrPathRange::PathGenerator* gen, | 
| bsalomon | 6663acf | 2016-05-10 09:14:17 -0700 | [diff] [blame] | 364 |                                                  const GrStyle& style) { | 
| bsalomon | 706f08f | 2015-05-22 07:35:58 -0700 | [diff] [blame] | 365 |     SkASSERT(this->gpu()->pathRendering()); | 
| bsalomon | 6663acf | 2016-05-10 09:14:17 -0700 | [diff] [blame] | 366 |     return this->gpu()->pathRendering()->createPathRange(gen, style); | 
| bsalomon | 706f08f | 2015-05-22 07:35:58 -0700 | [diff] [blame] | 367 | } | 
 | 368 |  | 
| reed | a9322c2 | 2016-04-12 06:47:05 -0700 | [diff] [blame] | 369 | GrPathRange* GrResourceProvider::createGlyphs(const SkTypeface* tf, | 
 | 370 |                                               const SkScalerContextEffects& effects, | 
 | 371 |                                               const SkDescriptor* desc, | 
| bsalomon | 6663acf | 2016-05-10 09:14:17 -0700 | [diff] [blame] | 372 |                                               const GrStyle& style) { | 
| bsalomon | 706f08f | 2015-05-22 07:35:58 -0700 | [diff] [blame] | 373 |  | 
 | 374 |     SkASSERT(this->gpu()->pathRendering()); | 
| bsalomon | 6663acf | 2016-05-10 09:14:17 -0700 | [diff] [blame] | 375 |     return this->gpu()->pathRendering()->createGlyphs(tf, effects, desc, style); | 
| bsalomon | 706f08f | 2015-05-22 07:35:58 -0700 | [diff] [blame] | 376 | } | 
 | 377 |  | 
| cdalton | e2e71c2 | 2016-04-07 18:13:29 -0700 | [diff] [blame] | 378 | GrBuffer* GrResourceProvider::createBuffer(size_t size, GrBufferType intendedType, | 
| cdalton | 1bf3e71 | 2016-04-19 10:00:02 -0700 | [diff] [blame] | 379 |                                            GrAccessPattern accessPattern, uint32_t flags, | 
 | 380 |                                            const void* data) { | 
| robertphillips | 1b8e1b5 | 2015-06-24 06:54:10 -0700 | [diff] [blame] | 381 |     if (this->isAbandoned()) { | 
| halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 382 |         return nullptr; | 
| robertphillips | 1b8e1b5 | 2015-06-24 06:54:10 -0700 | [diff] [blame] | 383 |     } | 
| cdalton | d37fe76 | 2016-04-21 07:41:50 -0700 | [diff] [blame] | 384 |     if (kDynamic_GrAccessPattern != accessPattern) { | 
 | 385 |         return this->gpu()->createBuffer(size, intendedType, accessPattern, data); | 
 | 386 |     } | 
| csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 387 |     if (!(flags & kRequireGpuMemory_Flag) && | 
 | 388 |         this->gpu()->caps()->preferClientSideDynamicBuffers() && | 
 | 389 |         GrBufferTypeIsVertexOrIndex(intendedType) && | 
 | 390 |         kDynamic_GrAccessPattern == accessPattern) { | 
 | 391 |         return GrBuffer::CreateCPUBacked(this->gpu(), size, intendedType, data); | 
 | 392 |     } | 
| robertphillips | 1b8e1b5 | 2015-06-24 06:54:10 -0700 | [diff] [blame] | 393 |  | 
| cdalton | d37fe76 | 2016-04-21 07:41:50 -0700 | [diff] [blame] | 394 |     // bin by pow2 with a reasonable min | 
| Robert Phillips | 9e38047 | 2016-10-28 12:15:03 -0400 | [diff] [blame] | 395 |     static const size_t MIN_SIZE = 1 << 12; | 
 | 396 |     size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size)); | 
| robertphillips | 1b8e1b5 | 2015-06-24 06:54:10 -0700 | [diff] [blame] | 397 |  | 
| cdalton | d37fe76 | 2016-04-21 07:41:50 -0700 | [diff] [blame] | 398 |     GrScratchKey key; | 
| csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 399 |     GrBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key); | 
| cdalton | d37fe76 | 2016-04-21 07:41:50 -0700 | [diff] [blame] | 400 |     uint32_t scratchFlags = 0; | 
 | 401 |     if (flags & kNoPendingIO_Flag) { | 
 | 402 |         scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag; | 
 | 403 |     } else { | 
 | 404 |         scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag; | 
 | 405 |     } | 
 | 406 |     GrBuffer* buffer = static_cast<GrBuffer*>( | 
 | 407 |         this->cache()->findAndRefScratchResource(key, allocSize, scratchFlags)); | 
 | 408 |     if (!buffer) { | 
 | 409 |         buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern); | 
 | 410 |         if (!buffer) { | 
 | 411 |             return nullptr; | 
| robertphillips | 1b8e1b5 | 2015-06-24 06:54:10 -0700 | [diff] [blame] | 412 |         } | 
 | 413 |     } | 
| cdalton | d37fe76 | 2016-04-21 07:41:50 -0700 | [diff] [blame] | 414 |     if (data) { | 
 | 415 |         buffer->updateData(data, size); | 
 | 416 |     } | 
| csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 417 |     SkASSERT(!buffer->isCPUBacked()); // We should only cache real VBOs. | 
| cdalton | d37fe76 | 2016-04-21 07:41:50 -0700 | [diff] [blame] | 418 |     return buffer; | 
| jvanverth | 17aa047 | 2016-01-05 10:41:27 -0800 | [diff] [blame] | 419 | } | 
 | 420 |  | 
| egdaniel | ec00d94 | 2015-09-14 12:56:10 -0700 | [diff] [blame] | 421 | GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) { | 
 | 422 |     SkASSERT(rt); | 
 | 423 |     if (rt->renderTargetPriv().getStencilAttachment()) { | 
 | 424 |         return rt->renderTargetPriv().getStencilAttachment(); | 
 | 425 |     } | 
 | 426 |  | 
 | 427 |     if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) { | 
 | 428 |         GrUniqueKey sbKey; | 
 | 429 |  | 
 | 430 |         int width = rt->width(); | 
 | 431 |         int height = rt->height(); | 
 | 432 | #if 0 | 
 | 433 |         if (this->caps()->oversizedStencilSupport()) { | 
 | 434 |             width  = SkNextPow2(width); | 
 | 435 |             height = SkNextPow2(height); | 
 | 436 |         } | 
 | 437 | #endif | 
 | 438 |         bool newStencil = false; | 
 | 439 |         GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, | 
 | 440 |                                                                rt->numStencilSamples(), &sbKey); | 
 | 441 |         GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>( | 
 | 442 |             this->findAndRefResourceByUniqueKey(sbKey)); | 
 | 443 |         if (!stencil) { | 
 | 444 |             // Need to try and create a new stencil | 
 | 445 |             stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height); | 
 | 446 |             if (stencil) { | 
| Robert Phillips | f7cf81a | 2017-03-02 10:23:52 -0500 | [diff] [blame] | 447 |                 this->assignUniqueKeyToResource(sbKey, stencil); | 
| egdaniel | ec00d94 | 2015-09-14 12:56:10 -0700 | [diff] [blame] | 448 |                 newStencil = true; | 
 | 449 |             } | 
 | 450 |         } | 
 | 451 |         if (rt->renderTargetPriv().attachStencilAttachment(stencil)) { | 
 | 452 |             if (newStencil) { | 
 | 453 |                 // Right now we're clearing the stencil attachment here after it is | 
| bsalomon | 7ea33f5 | 2015-11-22 14:51:00 -0800 | [diff] [blame] | 454 |                 // attached to a RT for the first time. When we start matching | 
| egdaniel | ec00d94 | 2015-09-14 12:56:10 -0700 | [diff] [blame] | 455 |                 // stencil buffers with smaller color targets this will no longer | 
 | 456 |                 // be correct because it won't be guaranteed to clear the entire | 
 | 457 |                 // sb. | 
 | 458 |                 // We used to clear down in the GL subclass using a special purpose | 
 | 459 |                 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported | 
 | 460 |                 // FBO status. | 
 | 461 |                 this->gpu()->clearStencil(rt); | 
 | 462 |             } | 
 | 463 |         } | 
 | 464 |     } | 
 | 465 |     return rt->renderTargetPriv().getStencilAttachment(); | 
 | 466 | } | 
 | 467 |  | 
| bungeman | 6bd5284 | 2016-10-27 09:30:08 -0700 | [diff] [blame] | 468 | sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget( | 
| Stan Iliev | 7fa5c31 | 2017-04-19 00:23:39 +0000 | [diff] [blame] | 469 |         const GrBackendTextureDesc& desc) | 
| bungeman | 6bd5284 | 2016-10-27 09:30:08 -0700 | [diff] [blame] | 470 | { | 
| ericrk | f7b8b8a | 2016-02-24 14:49:51 -0800 | [diff] [blame] | 471 |     if (this->isAbandoned()) { | 
 | 472 |         return nullptr; | 
 | 473 |     } | 
| Stan Iliev | 7fa5c31 | 2017-04-19 00:23:39 +0000 | [diff] [blame] | 474 |     return this->gpu()->wrapBackendTextureAsRenderTarget(desc); | 
| ericrk | f7b8b8a | 2016-02-24 14:49:51 -0800 | [diff] [blame] | 475 | } | 
| Greg Daniel | d85f97d | 2017-03-07 13:37:21 -0500 | [diff] [blame] | 476 |  | 
 | 477 | sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore() { | 
 | 478 |     return fGpu->makeSemaphore(); | 
 | 479 | } | 
 | 480 |  | 
 | 481 | void GrResourceProvider::takeOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) { | 
 | 482 |     semaphore->resetGpu(fGpu); | 
 | 483 | } | 
 | 484 |  | 
 | 485 | void GrResourceProvider::releaseOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) { | 
 | 486 |     semaphore->resetGpu(nullptr); | 
 | 487 | } |