1 /* 2 * Copyright 2013 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 "GrBackendSurface.h" 9 #include "GrClip.h" 10 #include "GrContextOptions.h" 11 #include "GrContextPriv.h" 12 #include "GrDrawOpAtlas.h" 13 #include "GrDrawingManager.h" 14 #include "GrGpu.h" 15 #include "GrGpuResourceCacheAccess.h" 16 #include "GrMemoryPool.h" 17 #include "GrRenderTargetContext.h" 18 #include "GrRenderTargetContextPriv.h" 19 #include "GrRenderTargetProxy.h" 20 #include "GrResourceCache.h" 21 #include "GrSemaphore.h" 22 #include "GrSurfaceContextPriv.h" 23 #include "GrTexture.h" 24 #include "SkGr.h" 25 #include "SkImage_Gpu.h" 26 #include "SkMathPriv.h" 27 #include "SkString.h" 28 #include "SkTo.h" 29 #include "ccpr/GrCoverageCountingPathRenderer.h" 30 #include "ccpr/GrCCPathCache.h" 31 #include "ops/GrMeshDrawOp.h" 32 #include "text/GrStrikeCache.h" 33 #include "text/GrTextBlobCache.h" 34 35 #include <algorithm> 36 37 bool GrSurfaceProxy::isWrapped_ForTesting() const { 38 return SkToBool(fTarget); 39 } 40 41 bool GrRenderTargetContext::isWrapped_ForTesting() const { 42 return fRenderTargetProxy->isWrapped_ForTesting(); 43 } 44 45 void GrContextPriv::setTextBlobCacheLimit_ForTesting(size_t bytes) { 46 fContext->fTextBlobCache->setBudget(bytes); 47 } 48 49 /////////////////////////////////////////////////////////////////////////////// 50 51 void GrContextPriv::purgeAllUnlockedResources_ForTesting() { 52 fContext->fResourceCache->purgeAllUnlocked(); 53 } 54 55 void GrContextPriv::resetGpuStats() const { 56 #if GR_GPU_STATS 57 fContext->fGpu->stats()->reset(); 58 #endif 59 } 60 61 void GrContextPriv::dumpCacheStats(SkString* out) const { 62 #if GR_CACHE_STATS 63 fContext->fResourceCache->dumpStats(out); 64 #endif 65 } 66 67 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys, 68 SkTArray<double>* values) const { 69 #if GR_CACHE_STATS 70 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values); 71 #endif 72 } 73 74 void GrContextPriv::printCacheStats() const { 75 SkString out; 76 this->dumpCacheStats(&out); 77 SkDebugf("%s", out.c_str()); 78 } 79 80 void GrContextPriv::dumpGpuStats(SkString* out) const { 81 #if GR_GPU_STATS 82 return fContext->fGpu->stats()->dump(out); 83 #endif 84 } 85 86 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, 87 SkTArray<double>* values) const { 88 #if GR_GPU_STATS 89 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values); 90 #endif 91 } 92 93 void GrContextPriv::printGpuStats() const { 94 SkString out; 95 this->dumpGpuStats(&out); 96 SkDebugf("%s", out.c_str()); 97 } 98 99 sk_sp<SkImage> GrContextPriv::getFontAtlasImage_ForTesting(GrMaskFormat format, unsigned int index) { 100 auto atlasManager = this->getAtlasManager(); 101 if (!atlasManager) { 102 return nullptr; 103 } 104 105 unsigned int numActiveProxies; 106 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies); 107 if (index >= numActiveProxies || !proxies || !proxies[index]) { 108 return nullptr; 109 } 110 111 SkASSERT(proxies[index]->priv().isExact()); 112 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID, 113 kPremul_SkAlphaType, proxies[index], nullptr)); 114 return image; 115 } 116 117 #if GR_GPU_STATS 118 void GrGpu::Stats::dump(SkString* out) { 119 out->appendf("Render Target Binds: %d\n", fRenderTargetBinds); 120 out->appendf("Shader Compilations: %d\n", fShaderCompilations); 121 out->appendf("Textures Created: %d\n", fTextureCreates); 122 out->appendf("Texture Uploads: %d\n", fTextureUploads); 123 out->appendf("Transfers to Texture: %d\n", fTransfersToTexture); 124 out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates); 125 out->appendf("Number of draws: %d\n", fNumDraws); 126 } 127 128 void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) { 129 keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds); 130 keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations); 131 keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads); 132 keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws); 133 keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws); 134 } 135 136 #endif 137 138 #if GR_CACHE_STATS 139 void GrResourceCache::getStats(Stats* stats) const { 140 stats->reset(); 141 142 stats->fTotal = this->getResourceCount(); 143 stats->fNumNonPurgeable = fNonpurgeableResources.count(); 144 stats->fNumPurgeable = fPurgeableQueue.count(); 145 146 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { 147 stats->update(fNonpurgeableResources[i]); 148 } 149 for (int i = 0; i < fPurgeableQueue.count(); ++i) { 150 stats->update(fPurgeableQueue.at(i)); 151 } 152 } 153 154 void GrResourceCache::dumpStats(SkString* out) const { 155 this->validate(); 156 157 Stats stats; 158 159 this->getStats(&stats); 160 161 float countUtilization = (100.f * fBudgetedCount) / fMaxCount; 162 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes; 163 164 out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes); 165 out->appendf("\t\tEntry Count: current %d" 166 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n", 167 stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable, 168 stats.fScratch, countUtilization, fHighWaterCount); 169 out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n", 170 SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization, 171 SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes)); 172 } 173 174 void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys, 175 SkTArray<double>* values) const { 176 this->validate(); 177 178 Stats stats; 179 this->getStats(&stats); 180 181 keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable); 182 } 183 184 #endif 185 186 /////////////////////////////////////////////////////////////////////////////// 187 188 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; } 189 190 #ifdef SK_DEBUG 191 int GrResourceCache::countUniqueKeysWithTag(const char* tag) const { 192 int count = 0; 193 UniqueHash::ConstIter iter(&fUniqueHash); 194 while (!iter.done()) { 195 if (0 == strcmp(tag, (*iter).getUniqueKey().tag())) { 196 ++count; 197 } 198 ++iter; 199 } 200 return count; 201 } 202 #endif 203 204 /////////////////////////////////////////////////////////////////////////////// 205 206 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy( 207 const GrSurfaceDesc& desc, GrSurfaceOrigin origin, SkBackingFit fit, SkBudgeted budgeted) { 208 sk_sp<GrTexture> tex; 209 210 if (SkBackingFit::kApprox == fit) { 211 tex = fResourceProvider->createApproxTexture(desc, GrResourceProvider::Flags::kNone); 212 } else { 213 tex = fResourceProvider->createTexture(desc, budgeted, GrResourceProvider::Flags::kNone); 214 } 215 if (!tex) { 216 return nullptr; 217 } 218 219 return this->createWrapped(std::move(tex), origin); 220 } 221 222 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex, 223 GrSurfaceOrigin origin) { 224 return this->createWrapped(std::move(tex), origin); 225 } 226 227 /////////////////////////////////////////////////////////////////////////////// 228 229 #define ASSERT_SINGLE_OWNER \ 230 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());) 231 232 233 uint32_t GrRenderTargetContextPriv::testingOnly_getOpListID() { 234 return fRenderTargetContext->getOpList()->uniqueID(); 235 } 236 237 void GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) { 238 this->testingOnly_addDrawOp(GrNoClip(), std::move(op)); 239 } 240 241 void GrRenderTargetContextPriv::testingOnly_addDrawOp( 242 const GrClip& clip, 243 std::unique_ptr<GrDrawOp> op, 244 const std::function<GrRenderTargetContext::WillAddOpFn>& willAddFn) { 245 ASSERT_SINGLE_OWNER 246 if (fRenderTargetContext->drawingManager()->wasAbandoned()) { 247 fRenderTargetContext->fContext->contextPriv().opMemoryPool()->release(std::move(op)); 248 return; 249 } 250 SkDEBUGCODE(fRenderTargetContext->validate()); 251 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 252 "GrRenderTargetContext::testingOnly_addDrawOp"); 253 fRenderTargetContext->addDrawOp(clip, std::move(op), willAddFn); 254 } 255 256 #undef ASSERT_SINGLE_OWNER 257 258 /////////////////////////////////////////////////////////////////////////////// 259 260 GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const { 261 return fSurfaceFlags; 262 } 263 264 ////////////////////////////////////////////////////////////////////////////// 265 266 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) { 267 fContext->flush(); 268 fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb); 269 } 270 271 void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) { 272 int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) - 273 fOnFlushCBObjects.begin(); 274 SkASSERT(n < fOnFlushCBObjects.count()); 275 fOnFlushCBObjects.removeShuffle(n); 276 } 277 278 ////////////////////////////////////////////////////////////////////////////// 279 280 void GrCoverageCountingPathRenderer::testingOnly_drawPathDirectly(const DrawPathArgs& args) { 281 // Call onDrawPath() directly: We want to test paths that might fail onCanDrawPath() simply for 282 // performance reasons, and GrPathRenderer::drawPath() assert that this call returns true. 283 // The test is responsible to not draw any paths that CCPR is not actually capable of. 284 this->onDrawPath(args); 285 } 286 287 const GrCCPerFlushResources* 288 GrCoverageCountingPathRenderer::testingOnly_getCurrentFlushResources() { 289 SkASSERT(fFlushing); 290 if (fFlushingPaths.empty()) { 291 return nullptr; 292 } 293 // All pending paths should share the same resources. 294 const GrCCPerFlushResources* resources = fFlushingPaths.front()->fFlushResources.get(); 295 #ifdef SK_DEBUG 296 for (const auto& flushingPaths : fFlushingPaths) { 297 SkASSERT(flushingPaths->fFlushResources.get() == resources); 298 } 299 #endif 300 return resources; 301 } 302 303 const GrCCPathCache* GrCoverageCountingPathRenderer::testingOnly_getPathCache() const { 304 return fPathCache.get(); 305 } 306 307 const GrTexture* GrCCPerFlushResources::testingOnly_frontCopyAtlasTexture() const { 308 if (fCopyAtlasStack.empty()) { 309 return nullptr; 310 } 311 const GrTextureProxy* proxy = fCopyAtlasStack.front().textureProxy(); 312 return (proxy) ? proxy->peekTexture() : nullptr; 313 } 314 315 const GrTexture* GrCCPerFlushResources::testingOnly_frontRenderedAtlasTexture() const { 316 if (fRenderedAtlasStack.empty()) { 317 return nullptr; 318 } 319 const GrTextureProxy* proxy = fRenderedAtlasStack.front().textureProxy(); 320 return (proxy) ? proxy->peekTexture() : nullptr; 321 } 322 323 const SkTHashTable<GrCCPathCache::HashNode, const GrCCPathCache::Key&>& 324 GrCCPathCache::testingOnly_getHashTable() const { 325 return fHashTable; 326 } 327 328 const SkTInternalLList<GrCCPathCacheEntry>& GrCCPathCache::testingOnly_getLRU() const { 329 return fLRU; 330 } 331 332 int GrCCPathCacheEntry::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; } 333 334 int GrCCCachedAtlas::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; } 335 336 ////////////////////////////////////////////////////////////////////////////// 337 338 #define DRAW_OP_TEST_EXTERN(Op) \ 339 extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, GrContext*, GrFSAAType) 340 #define DRAW_OP_TEST_ENTRY(Op) Op##__Test 341 342 DRAW_OP_TEST_EXTERN(AAConvexPathOp); 343 DRAW_OP_TEST_EXTERN(AAFlatteningConvexPathOp); 344 DRAW_OP_TEST_EXTERN(AAHairlineOp); 345 DRAW_OP_TEST_EXTERN(AAStrokeRectOp); 346 DRAW_OP_TEST_EXTERN(CircleOp); 347 DRAW_OP_TEST_EXTERN(DashOp); 348 DRAW_OP_TEST_EXTERN(DefaultPathOp); 349 DRAW_OP_TEST_EXTERN(DIEllipseOp); 350 DRAW_OP_TEST_EXTERN(EllipseOp); 351 DRAW_OP_TEST_EXTERN(FillRectOp); 352 DRAW_OP_TEST_EXTERN(GrAtlasTextOp); 353 DRAW_OP_TEST_EXTERN(GrDrawAtlasOp); 354 DRAW_OP_TEST_EXTERN(GrDrawVerticesOp); 355 DRAW_OP_TEST_EXTERN(NonAALatticeOp); 356 DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp); 357 DRAW_OP_TEST_EXTERN(ShadowRRectOp); 358 DRAW_OP_TEST_EXTERN(SmallPathOp); 359 DRAW_OP_TEST_EXTERN(RegionOp); 360 DRAW_OP_TEST_EXTERN(RRectOp); 361 DRAW_OP_TEST_EXTERN(TesselatingPathOp); 362 DRAW_OP_TEST_EXTERN(TextureOp); 363 364 void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext, GrPaint&& paint) { 365 GrContext* context = renderTargetContext->surfPriv().getContext(); 366 using MakeDrawOpFn = std::unique_ptr<GrDrawOp>(GrPaint&&, SkRandom*, GrContext*, GrFSAAType); 367 static constexpr MakeDrawOpFn* gFactories[] = { 368 DRAW_OP_TEST_ENTRY(AAConvexPathOp), 369 DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp), 370 DRAW_OP_TEST_ENTRY(AAHairlineOp), 371 DRAW_OP_TEST_ENTRY(AAStrokeRectOp), 372 DRAW_OP_TEST_ENTRY(CircleOp), 373 DRAW_OP_TEST_ENTRY(DashOp), 374 DRAW_OP_TEST_ENTRY(DefaultPathOp), 375 DRAW_OP_TEST_ENTRY(DIEllipseOp), 376 DRAW_OP_TEST_ENTRY(EllipseOp), 377 DRAW_OP_TEST_ENTRY(FillRectOp), 378 DRAW_OP_TEST_ENTRY(GrAtlasTextOp), 379 DRAW_OP_TEST_ENTRY(GrDrawAtlasOp), 380 DRAW_OP_TEST_ENTRY(GrDrawVerticesOp), 381 DRAW_OP_TEST_ENTRY(NonAALatticeOp), 382 DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp), 383 DRAW_OP_TEST_ENTRY(ShadowRRectOp), 384 DRAW_OP_TEST_ENTRY(SmallPathOp), 385 DRAW_OP_TEST_ENTRY(RegionOp), 386 DRAW_OP_TEST_ENTRY(RRectOp), 387 DRAW_OP_TEST_ENTRY(TesselatingPathOp), 388 DRAW_OP_TEST_ENTRY(TextureOp), 389 }; 390 391 static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories); 392 uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal)); 393 auto op = gFactories[index]( 394 std::move(paint), random, context, renderTargetContext->fsaaType()); 395 SkASSERT(op); 396 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op)); 397 } 398