Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: src/gpu/GrContext.cpp

Issue 608883003: GrResourceCache2 manages scratch texture. (Closed) Base URL: https://skia.googlesource.com/skia.git@surfimpl
Patch Set: remove todo Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrClipMaskCache.h ('k') | src/gpu/GrDrawState.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "GrContext.h" 10 #include "GrContext.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 static const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMI T * 1024 * 1024; 63 static const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMI T * 1024 * 1024;
64 64
65 static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15; 65 static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
66 static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4; 66 static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
67 67
68 static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11; 68 static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
69 static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4; 69 static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
70 70
71 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) 71 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
72 72
73 GrTexture* GrAutoScratchTexture::detach() {
74 if (NULL == fTexture) {
75 return NULL;
76 }
77 GrTexture* texture = fTexture;
78 fTexture = NULL;
79
80 // This GrAutoScratchTexture has a ref from lockAndRefScratchTexture, which we give up now.
81 // The cache also has a ref which we are lending to the caller of detach(). When the caller
82 // lets go of the ref and the ref count goes to 0 internal_dispose will see this flag is
83 // set and re-ref the texture, thereby restoring the cache's ref.
84 SkASSERT(!texture->unique());
85 texture->texturePriv().setFlag((GrTextureFlags) GrTexture::kReturnToCache_Fl agBit);
86 texture->unref();
87 SkASSERT(texture->getCacheEntry());
88
89 return texture;
90 }
91
92 // Glorified typedef to avoid including GrDrawState.h in GrContext.h 73 // Glorified typedef to avoid including GrDrawState.h in GrContext.h
93 class GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {}; 74 class GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
94 75
95 class GrContext::AutoCheckFlush { 76 class GrContext::AutoCheckFlush {
96 public: 77 public:
97 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); } 78 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
98 79
99 ~AutoCheckFlush() { 80 ~AutoCheckFlush() {
100 if (fContext->fFlushToReduceCacheSize) { 81 if (fContext->fFlushToReduceCacheSize) {
101 fContext->flush(); 82 fContext->flush();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 SkASSERT(NULL == fGpu); 127 SkASSERT(NULL == fGpu);
147 128
148 fGpu = GrGpu::Create(backend, backendContext, this); 129 fGpu = GrGpu::Create(backend, backendContext, this);
149 if (NULL == fGpu) { 130 if (NULL == fGpu) {
150 return false; 131 return false;
151 } 132 }
152 133
153 fDrawState = SkNEW(GrDrawState); 134 fDrawState = SkNEW(GrDrawState);
154 fGpu->setDrawState(fDrawState); 135 fGpu->setDrawState(fDrawState);
155 136
156 fResourceCache = SkNEW_ARGS(GrResourceCache, (MAX_RESOURCE_CACHE_COUNT, 137 fResourceCache = SkNEW_ARGS(GrResourceCache, (fGpu->caps(),
138 MAX_RESOURCE_CACHE_COUNT,
157 MAX_RESOURCE_CACHE_BYTES)); 139 MAX_RESOURCE_CACHE_BYTES));
158 fResourceCache->setOverbudgetCallback(OverbudgetCB, this); 140 fResourceCache->setOverbudgetCallback(OverbudgetCB, this);
159 fResourceCache2 = SkNEW(GrResourceCache2); 141 fResourceCache2 = SkNEW(GrResourceCache2);
160 142
161 fFontCache = SkNEW_ARGS(GrFontCache, (fGpu)); 143 fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
162 144
163 fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this))); 145 fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
164 146
165 fLastDrawWasBuffered = kNo_BufferedDraw; 147 fLastDrawWasBuffered = kNo_BufferedDraw;
166 148
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); 421 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
440 422
441 texture = this->createResizedTexture(desc, cacheID, 423 texture = this->createResizedTexture(desc, cacheID,
442 srcData, rowBytes, 424 srcData, rowBytes,
443 GrTexturePriv::NeedsBilerp(resource Key)); 425 GrTexturePriv::NeedsBilerp(resource Key));
444 } else { 426 } else {
445 texture = fGpu->createTexture(desc, srcData, rowBytes); 427 texture = fGpu->createTexture(desc, srcData, rowBytes);
446 } 428 }
447 429
448 if (texture) { 430 if (texture) {
449 // Adding a resource could put us overbudget. Try to free up the
450 // necessary space before adding it.
451 fResourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
452 fResourceCache->addResource(resourceKey, texture); 431 fResourceCache->addResource(resourceKey, texture);
453 432
454 if (cacheKey) { 433 if (cacheKey) {
455 *cacheKey = resourceKey; 434 *cacheKey = resourceKey;
456 } 435 }
457 } 436 }
458 437
459 return texture; 438 return texture;
460 } 439 }
461 440
462 static GrTexture* create_scratch_texture(GrGpu* gpu, 441 GrTexture* GrContext::createNewScratchTexture(const GrTextureDesc& desc) {
463 GrResourceCache* resourceCache, 442 GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
464 const GrTextureDesc& desc) { 443 if (!texture) {
465 GrTexture* texture = gpu->createTexture(desc, NULL, 0); 444 return NULL;
466 if (texture) {
467 GrResourceKey key = GrTexturePriv::ComputeScratchKey(texture->desc());
468 // Adding a resource could put us overbudget. Try to free up the
469 // necessary space before adding it.
470 resourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
471 // Make the resource exclusive so future 'find' calls don't return it
472 resourceCache->addResource(key, texture, GrResourceCache::kHide_Ownershi pFlag);
473 } 445 }
446 fResourceCache->addResource(texture->getScratchKey(), texture);
447 texture->fIsScratch = GrGpuResource::kYes_IsScratch;
474 return texture; 448 return texture;
475 } 449 }
476 450
477 GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra tchTexMatch match) { 451 GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra tchTexMatch match,
452 bool calledDuringFlush) {
478 453
454 // kNoStencil has no meaning if kRT isn't set.
479 SkASSERT((inDesc.fFlags & kRenderTarget_GrTextureFlagBit) || 455 SkASSERT((inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
480 !(inDesc.fFlags & kNoStencil_GrTextureFlagBit)); 456 !(inDesc.fFlags & kNoStencil_GrTextureFlagBit));
481 457
482 // Renderable A8 targets are not universally supported (e.g., not on ANGLE) 458 // Make sure caller has checked for renderability if kRT is set.
483 SkASSERT(this->isConfigRenderable(kAlpha_8_GrPixelConfig, inDesc.fSampleCnt > 0) || 459 SkASSERT(!(inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
484 !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit) || 460 this->isConfigRenderable(inDesc.fConfig, inDesc.fSampleCnt > 0));
485 (inDesc.fConfig != kAlpha_8_GrPixelConfig));
486 461
487 if (!fGpu->caps()->reuseScratchTextures() && 462 SkTCopyOnFirstWrite<GrTextureDesc> desc(inDesc);
488 !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit)) { 463
489 // If we're never recycling this texture we can always make it the right size 464 if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_Gr TextureFlagBit)) {
490 return create_scratch_texture(fGpu, fResourceCache, inDesc); 465 GrTextureFlags origFlags = desc->fFlags;
466 if (kApprox_ScratchTexMatch == match) {
467 // bin by pow2 with a reasonable min
468 static const int MIN_SIZE = 16;
469 GrTextureDesc* wdesc = desc.writable();
470 wdesc->fWidth = SkTMax(MIN_SIZE, GrNextPow2(desc->fWidth));
471 wdesc->fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc->fHeight));
472 }
473
474 do {
475 GrResourceKey key = GrTexturePriv::ComputeScratchKey(*desc);
476 GrGpuResource* resource = fResourceCache2->findAndRefScratchResource (key,
477 calledDuringFlush);
478 if (resource) {
479 fResourceCache->makeResourceMRU(resource);
480 return static_cast<GrTexture*>(resource);
481 }
482
483 if (kExact_ScratchTexMatch == match) {
484 break;
485 }
486 // We had a cache miss and we are in approx mode, relax the fit of t he flags.
487
488 // We no longer try to reuse textures that were previously used as r ender targets in
489 // situations where no RT is needed; doing otherwise can confuse the video driver and
490 // cause significant performance problems in some cases.
491 if (desc->fFlags & kNoStencil_GrTextureFlagBit) {
492 desc.writable()->fFlags = desc->fFlags & ~kNoStencil_GrTextureFl agBit;
493 } else {
494 break;
495 }
496
497 } while (true);
498
499 desc.writable()->fFlags = origFlags;
491 } 500 }
492 501
493 GrTextureDesc desc = inDesc; 502 GrTexture* texture = this->createNewScratchTexture(*desc);
494 503 SkASSERT(NULL == texture ||
495 if (kApprox_ScratchTexMatch == match) { 504 texture->getScratchKey() == GrTexturePriv::ComputeScratchKey(*desc) );
496 // bin by pow2 with a reasonable min 505 return texture;
497 static const int MIN_SIZE = 16;
498 desc.fWidth = SkTMax(MIN_SIZE, GrNextPow2(desc.fWidth));
499 desc.fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc.fHeight));
500 }
501
502 GrGpuResource* resource = NULL;
503 int origWidth = desc.fWidth;
504 int origHeight = desc.fHeight;
505
506 do {
507 GrResourceKey key = GrTexturePriv::ComputeScratchKey(desc);
508 // Ensure we have exclusive access to the texture so future 'find' calls don't return it
509 resource = fResourceCache->find(key, GrResourceCache::kHide_OwnershipFla g);
510 if (resource) {
511 resource->ref();
512 break;
513 }
514 if (kExact_ScratchTexMatch == match) {
515 break;
516 }
517 // We had a cache miss and we are in approx mode, relax the fit of the f lags.
518
519 // We no longer try to reuse textures that were previously used as rende r targets in
520 // situations where no RT is needed; doing otherwise can confuse the vid eo driver and
521 // cause significant performance problems in some cases.
522 if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
523 desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
524 } else {
525 break;
526 }
527
528 } while (true);
529
530 if (NULL == resource) {
531 desc.fFlags = inDesc.fFlags;
532 desc.fWidth = origWidth;
533 desc.fHeight = origHeight;
534 resource = create_scratch_texture(fGpu, fResourceCache, desc);
535 }
536
537 return static_cast<GrTexture*>(resource);
538 }
539
540 void GrContext::addExistingTextureToCache(GrTexture* texture) {
541
542 if (NULL == texture) {
543 return;
544 }
545
546 // This texture should already have a cache entry since it was once
547 // attached
548 SkASSERT(texture->getCacheEntry());
549
550 // Conceptually, the cache entry is going to assume responsibility
551 // for the creation ref. Assert refcnt == 1.
552 // Except that this also gets called when the texture is prematurely
553 // abandoned. In that case the ref count may be > 1.
554 // SkASSERT(texture->unique());
555
556 if (fGpu->caps()->reuseScratchTextures() || texture->asRenderTarget()) {
557 // Since this texture came from an AutoScratchTexture it should
558 // still be in the exclusive pile. Recycle it.
559 fResourceCache->makeNonExclusive(texture->getCacheEntry());
560 this->purgeCache();
561 } else {
562 // When we aren't reusing textures we know this scratch texture
563 // will never be reused and would be just wasting time in the cache
564 fResourceCache->makeNonExclusive(texture->getCacheEntry());
565 fResourceCache->deleteResource(texture->getCacheEntry());
566 }
567 }
568
569 void GrContext::unlockScratchTexture(GrTexture* texture) {
570 if (texture->wasDestroyed()) {
571 if (texture->getCacheEntry()->key().isScratch()) {
572 // This texture was detached from the cache but the cache still had a ref to it but
573 // not a pointer to it. This will unref the texture and delete its r esource cache
574 // entry.
575 delete texture->getCacheEntry();
576 }
577 return;
578 }
579
580 ASSERT_OWNED_RESOURCE(texture);
581 SkASSERT(texture->getCacheEntry());
582
583 // If this is a scratch texture we detached it from the cache
584 // while it was locked (to avoid two callers simultaneously getting
585 // the same texture).
586 if (texture->getCacheEntry()->key().isScratch()) {
587 if (fGpu->caps()->reuseScratchTextures() || texture->asRenderTarget()) {
588 fResourceCache->makeNonExclusive(texture->getCacheEntry());
589 this->purgeCache();
590 } else if (texture->unique()) {
591 // Only the cache now knows about this texture. Since we're never
592 // reusing scratch textures (in this code path) it would just be
593 // wasting time sitting in the cache.
594 fResourceCache->makeNonExclusive(texture->getCacheEntry());
595 fResourceCache->deleteResource(texture->getCacheEntry());
596 } else {
597 // In this case (there is still a non-cache ref) but we don't really
598 // want to readd it to the cache (since it will never be reused).
599 // Instead, give up the cache's ref and leave the decision up to
600 // addExistingTextureToCache once its ref count reaches 0. For
601 // this to work we need to leave it in the exclusive list.
602 texture->texturePriv().setFlag((GrTextureFlags) GrTexture::kReturnTo Cache_FlagBit);
603 // Give up the cache's ref to the texture
604 texture->unref();
605 }
606 }
607 }
608
609 void GrContext::purgeCache() {
610 if (fResourceCache) {
611 fResourceCache->purgeAsNeeded();
612 }
613 } 506 }
614 507
615 bool GrContext::OverbudgetCB(void* data) { 508 bool GrContext::OverbudgetCB(void* data) {
616 SkASSERT(data); 509 SkASSERT(data);
617 510
618 GrContext* context = reinterpret_cast<GrContext*>(data); 511 GrContext* context = reinterpret_cast<GrContext*>(data);
619 512
620 // Flush the InOrderDrawBuffer to possibly free up some textures 513 // Flush the InOrderDrawBuffer to possibly free up some textures
621 context->fFlushToReduceCacheSize = true; 514 context->fFlushToReduceCacheSize = true;
622 515
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 void GrContext::flush(int flagsBitfield) { 1235 void GrContext::flush(int flagsBitfield) {
1343 if (NULL == fDrawBuffer) { 1236 if (NULL == fDrawBuffer) {
1344 return; 1237 return;
1345 } 1238 }
1346 1239
1347 if (kDiscard_FlushBit & flagsBitfield) { 1240 if (kDiscard_FlushBit & flagsBitfield) {
1348 fDrawBuffer->reset(); 1241 fDrawBuffer->reset();
1349 } else { 1242 } else {
1350 fDrawBuffer->flush(); 1243 fDrawBuffer->flush();
1351 } 1244 }
1245 fResourceCache->purgeAsNeeded();
1352 fFlushToReduceCacheSize = false; 1246 fFlushToReduceCacheSize = false;
1353 } 1247 }
1354 1248
1355 bool GrContext::writeTexturePixels(GrTexture* texture, 1249 bool GrContext::writeTexturePixels(GrTexture* texture,
1356 int left, int top, int width, int height, 1250 int left, int top, int width, int height,
1357 GrPixelConfig config, const void* buffer, siz e_t rowBytes, 1251 GrPixelConfig config, const void* buffer, siz e_t rowBytes,
1358 uint32_t flags) { 1252 uint32_t flags) {
1359 ASSERT_OWNED_RESOURCE(texture); 1253 ASSERT_OWNED_RESOURCE(texture);
1360 1254
1361 if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture , config)) { 1255 if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture , config)) {
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
1934 GrConfigConversionEffect::PMConversion upmToPM = 1828 GrConfigConversionEffect::PMConversion upmToPM =
1935 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); 1829 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
1936 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { 1830 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
1937 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat rix); 1831 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat rix);
1938 } else { 1832 } else {
1939 return NULL; 1833 return NULL;
1940 } 1834 }
1941 } 1835 }
1942 1836
1943 void GrContext::addResourceToCache(const GrResourceKey& resourceKey, GrGpuResour ce* resource) { 1837 void GrContext::addResourceToCache(const GrResourceKey& resourceKey, GrGpuResour ce* resource) {
1944 fResourceCache->purgeAsNeeded(1, resource->gpuMemorySize());
1945 fResourceCache->addResource(resourceKey, resource); 1838 fResourceCache->addResource(resourceKey, resource);
1946 } 1839 }
1947 1840
1948 GrGpuResource* GrContext::findAndRefCachedResource(const GrResourceKey& resource Key) { 1841 GrGpuResource* GrContext::findAndRefCachedResource(const GrResourceKey& resource Key) {
1949 GrGpuResource* resource = fResourceCache->find(resourceKey); 1842 GrGpuResource* resource = fResourceCache->find(resourceKey);
1950 SkSafeRef(resource); 1843 SkSafeRef(resource);
1951 return resource; 1844 return resource;
1952 } 1845 }
1953 1846
1954 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 1847 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
(...skipping 16 matching lines...) Expand all
1971 fResourceCache->printStats(); 1864 fResourceCache->printStats();
1972 } 1865 }
1973 #endif 1866 #endif
1974 1867
1975 #if GR_GPU_STATS 1868 #if GR_GPU_STATS
1976 const GrContext::GPUStats* GrContext::gpuStats() const { 1869 const GrContext::GPUStats* GrContext::gpuStats() const {
1977 return fGpu->gpuStats(); 1870 return fGpu->gpuStats();
1978 } 1871 }
1979 #endif 1872 #endif
1980 1873
OLDNEW
« no previous file with comments | « src/gpu/GrClipMaskCache.h ('k') | src/gpu/GrDrawState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698