OLD | NEW |
---|---|
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 #include "GrContext.h" | 9 #include "GrContext.h" |
10 #include "GrContextOptions.h" | 10 #include "GrContextOptions.h" |
11 #include "GrDrawingManager.h" | 11 #include "GrDrawingManager.h" |
12 #include "GrDrawContext.h" | 12 #include "GrDrawContext.h" |
13 #include "GrLayerCache.h" | 13 #include "GrLayerCache.h" |
14 #include "GrResourceCache.h" | 14 #include "GrResourceCache.h" |
15 #include "GrResourceProvider.h" | 15 #include "GrResourceProvider.h" |
16 #include "GrSoftwarePathRenderer.h" | 16 #include "GrSoftwarePathRenderer.h" |
17 #include "GrSurfacePriv.h" | 17 #include "GrSurfacePriv.h" |
18 | 18 |
19 #include "SkConfig8888.h" | 19 #include "SkConfig8888.h" |
20 #include "SkGrPriv.h" | 20 #include "SkGrPriv.h" |
21 | 21 |
22 #include "effects/GrConfigConversionEffect.h" | 22 #include "effects/GrConfigConversionEffect.h" |
23 #include "text/GrTextBlobCache.h" | 23 #include "text/GrTextBlobCache.h" |
24 | 24 |
25 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) | 25 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) |
26 #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } | 26 #define TAKE_DEBUG_MUTEX \ |
27 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return fal se; } | 27 SkASSERT(1 == fSafetyMutex.fSemaphore.fCount || fSafetyMutex.fOwner == SkGet ThreadID()); \ |
28 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return null ptr; } | 28 SkDEBUGCODE(SkAutoTAcquire<SkRecursiveMutex> debug_SafetyMutex(fSafetyMutex) ;) |
29 #define RETURN_IF_ABANDONED TAKE_DEBUG_MUTEX if (fDrawingManager->abandoned()) { return; } | |
30 #define RETURN_FALSE_IF_ABANDONED \ | |
31 TAKE_DEBUG_MUTEX \ | |
32 if (fDrawingManager->abandoned()) { return false; } | |
33 #define RETURN_NULL_IF_ABANDONED \ | |
34 TAKE_DEBUG_MUTEX \ | |
35 if (fDrawingManager->abandoned()) { return nullptr; } | |
29 | 36 |
30 //////////////////////////////////////////////////////////////////////////////// | 37 //////////////////////////////////////////////////////////////////////////////// |
31 | 38 |
32 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) { | 39 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) { |
33 GrContextOptions defaultOptions; | 40 GrContextOptions defaultOptions; |
34 return Create(backend, backendContext, defaultOptions); | 41 return Create(backend, backendContext, defaultOptions); |
35 } | 42 } |
36 | 43 |
37 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, | 44 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, |
38 const GrContextOptions& options) { | 45 const GrContextOptions& options) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 | 77 |
71 fGpu = GrGpu::Create(backend, backendContext, options, this); | 78 fGpu = GrGpu::Create(backend, backendContext, options, this); |
72 if (!fGpu) { | 79 if (!fGpu) { |
73 return false; | 80 return false; |
74 } | 81 } |
75 this->initCommon(options); | 82 this->initCommon(options); |
76 return true; | 83 return true; |
77 } | 84 } |
78 | 85 |
79 void GrContext::initCommon(const GrContextOptions& options) { | 86 void GrContext::initCommon(const GrContextOptions& options) { |
87 TAKE_DEBUG_MUTEX | |
mtklein
2016/01/05 22:47:50
What is the constraint that you are trying to enfo
joshualitt
2016/01/06 14:03:27
No, but a GrContext may only ever be used from one
mtklein
2016/01/06 14:33:46
So what do we need the reentrant mutex for? We're
| |
88 | |
80 fCaps = SkRef(fGpu->caps()); | 89 fCaps = SkRef(fGpu->caps()); |
81 fResourceCache = new GrResourceCache(fCaps); | 90 fResourceCache = new GrResourceCache(fCaps); |
82 fResourceCache->setOverBudgetCallback(OverBudgetCB, this); | 91 fResourceCache->setOverBudgetCallback(OverBudgetCB, this); |
83 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache); | 92 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache); |
84 | 93 |
85 fLayerCache.reset(new GrLayerCache(this)); | 94 fLayerCache.reset(new GrLayerCache(this)); |
86 | 95 |
87 fDidTestPMConversions = false; | 96 fDidTestPMConversions = false; |
88 | 97 |
89 GrDrawTarget::Options dtOptions; | 98 GrDrawTarget::Options dtOptions; |
90 dtOptions.fClipBatchToBounds = options.fClipBatchToBounds; | 99 dtOptions.fClipBatchToBounds = options.fClipBatchToBounds; |
91 dtOptions.fDrawBatchBounds = options.fDrawBatchBounds; | 100 dtOptions.fDrawBatchBounds = options.fDrawBatchBounds; |
92 dtOptions.fMaxBatchLookback = options.fMaxBatchLookback; | 101 dtOptions.fMaxBatchLookback = options.fMaxBatchLookback; |
93 fDrawingManager.reset(new GrDrawingManager(this, dtOptions)); | 102 fDrawingManager.reset(new GrDrawingManager(this, dtOptions)); |
94 | 103 |
95 // GrBatchFontCache will eventually replace GrFontCache | 104 // GrBatchFontCache will eventually replace GrFontCache |
96 fBatchFontCache = new GrBatchFontCache(this); | 105 fBatchFontCache = new GrBatchFontCache(this); |
97 | 106 |
98 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this)); | 107 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this)); |
99 } | 108 } |
100 | 109 |
101 GrContext::~GrContext() { | 110 GrContext::~GrContext() { |
111 TAKE_DEBUG_MUTEX | |
112 | |
102 if (!fGpu) { | 113 if (!fGpu) { |
103 SkASSERT(!fCaps); | 114 SkASSERT(!fCaps); |
104 return; | 115 return; |
105 } | 116 } |
106 | 117 |
107 this->flush(); | 118 this->flush(); |
108 | 119 |
109 fDrawingManager->cleanup(); | 120 fDrawingManager->cleanup(); |
110 | 121 |
111 for (int i = 0; i < fCleanUpData.count(); ++i) { | 122 for (int i = 0; i < fCleanUpData.count(); ++i) { |
112 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); | 123 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); |
113 } | 124 } |
114 | 125 |
115 delete fResourceProvider; | 126 delete fResourceProvider; |
116 delete fResourceCache; | 127 delete fResourceCache; |
117 delete fBatchFontCache; | 128 delete fBatchFontCache; |
118 | 129 |
119 fGpu->unref(); | 130 fGpu->unref(); |
120 fCaps->unref(); | 131 fCaps->unref(); |
121 } | 132 } |
122 | 133 |
123 void GrContext::abandonContext() { | 134 void GrContext::abandonContext() { |
135 TAKE_DEBUG_MUTEX | |
136 | |
124 fResourceProvider->abandon(); | 137 fResourceProvider->abandon(); |
125 | 138 |
126 // Need to abandon the drawing manager first so all the render targets | 139 // Need to abandon the drawing manager first so all the render targets |
127 // will be released/forgotten before they too are abandoned. | 140 // will be released/forgotten before they too are abandoned. |
128 fDrawingManager->abandon(); | 141 fDrawingManager->abandon(); |
129 | 142 |
130 // abandon first to so destructors | 143 // abandon first to so destructors |
131 // don't try to free the resources in the API. | 144 // don't try to free the resources in the API. |
132 fResourceCache->abandonAll(); | 145 fResourceCache->abandonAll(); |
133 | 146 |
134 fGpu->contextAbandoned(); | 147 fGpu->contextAbandoned(); |
135 | 148 |
136 fBatchFontCache->freeAll(); | 149 fBatchFontCache->freeAll(); |
137 fLayerCache->freeAll(); | 150 fLayerCache->freeAll(); |
138 fTextBlobCache->freeAll(); | 151 fTextBlobCache->freeAll(); |
139 } | 152 } |
140 | 153 |
141 void GrContext::resetContext(uint32_t state) { | 154 void GrContext::resetContext(uint32_t state) { |
155 TAKE_DEBUG_MUTEX | |
156 | |
142 fGpu->markContextDirty(state); | 157 fGpu->markContextDirty(state); |
143 } | 158 } |
144 | 159 |
145 void GrContext::freeGpuResources() { | 160 void GrContext::freeGpuResources() { |
161 TAKE_DEBUG_MUTEX | |
162 | |
146 this->flush(); | 163 this->flush(); |
147 | 164 |
148 fBatchFontCache->freeAll(); | 165 fBatchFontCache->freeAll(); |
149 fLayerCache->freeAll(); | 166 fLayerCache->freeAll(); |
150 | 167 |
151 fDrawingManager->freeGpuResources(); | 168 fDrawingManager->freeGpuResources(); |
152 | 169 |
153 fResourceCache->purgeAllUnlocked(); | 170 fResourceCache->purgeAllUnlocked(); |
154 } | 171 } |
155 | 172 |
156 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const { | 173 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const { |
174 TAKE_DEBUG_MUTEX | |
175 | |
157 if (resourceCount) { | 176 if (resourceCount) { |
158 *resourceCount = fResourceCache->getBudgetedResourceCount(); | 177 *resourceCount = fResourceCache->getBudgetedResourceCount(); |
159 } | 178 } |
160 if (resourceBytes) { | 179 if (resourceBytes) { |
161 *resourceBytes = fResourceCache->getBudgetedResourceBytes(); | 180 *resourceBytes = fResourceCache->getBudgetedResourceBytes(); |
162 } | 181 } |
163 } | 182 } |
164 | 183 |
165 //////////////////////////////////////////////////////////////////////////////// | 184 //////////////////////////////////////////////////////////////////////////////// |
166 | 185 |
(...skipping 12 matching lines...) Expand all Loading... | |
179 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they | 198 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they |
180 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move | 199 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move |
181 // drawText calls to below the GrContext level, but this is not trivial beca use they call | 200 // drawText calls to below the GrContext level, but this is not trivial beca use they call |
182 // drawPath on SkGpuDevice | 201 // drawPath on SkGpuDevice |
183 GrContext* context = reinterpret_cast<GrContext*>(data); | 202 GrContext* context = reinterpret_cast<GrContext*>(data); |
184 context->flush(); | 203 context->flush(); |
185 } | 204 } |
186 | 205 |
187 //////////////////////////////////////////////////////////////////////////////// | 206 //////////////////////////////////////////////////////////////////////////////// |
188 | 207 |
189 void GrContext::flush(int flagsBitfield) { | 208 void GrContext::flush(int flagsBitfield) { |
mtklein
2016/01/05 22:47:50
Why do some methods TAKE_DEBUG_MUTEX and not other
mtklein
2016/01/05 22:55:45
Oh, I see. That's very confusing.
joshualitt
2016/01/06 14:03:27
I can explicitly break it out of the macro if that
mtklein
2016/01/06 14:33:46
I think it would.
| |
190 RETURN_IF_ABANDONED | 209 RETURN_IF_ABANDONED |
191 | 210 |
192 if (kDiscard_FlushBit & flagsBitfield) { | 211 if (kDiscard_FlushBit & flagsBitfield) { |
193 fDrawingManager->reset(); | 212 fDrawingManager->reset(); |
194 } else { | 213 } else { |
195 fDrawingManager->flush(); | 214 fDrawingManager->flush(); |
196 } | 215 } |
197 fResourceCache->notifyFlushOccurred(); | 216 fResourceCache->notifyFlushOccurred(); |
198 fFlushToReduceCacheSize = false; | 217 fFlushToReduceCacheSize = false; |
199 } | 218 } |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
528 void GrContext::flushSurfaceWrites(GrSurface* surface) { | 547 void GrContext::flushSurfaceWrites(GrSurface* surface) { |
529 RETURN_IF_ABANDONED | 548 RETURN_IF_ABANDONED |
530 if (surface->surfacePriv().hasPendingWrite()) { | 549 if (surface->surfacePriv().hasPendingWrite()) { |
531 this->flush(); | 550 this->flush(); |
532 } | 551 } |
533 } | 552 } |
534 | 553 |
535 //////////////////////////////////////////////////////////////////////////////// | 554 //////////////////////////////////////////////////////////////////////////////// |
536 int GrContext::getRecommendedSampleCount(GrPixelConfig config, | 555 int GrContext::getRecommendedSampleCount(GrPixelConfig config, |
537 SkScalar dpi) const { | 556 SkScalar dpi) const { |
557 TAKE_DEBUG_MUTEX | |
558 | |
538 if (!this->caps()->isConfigRenderable(config, true)) { | 559 if (!this->caps()->isConfigRenderable(config, true)) { |
539 return 0; | 560 return 0; |
540 } | 561 } |
541 int chosenSampleCount = 0; | 562 int chosenSampleCount = 0; |
542 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) { | 563 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) { |
543 if (dpi >= 250.0f) { | 564 if (dpi >= 250.0f) { |
544 chosenSampleCount = 4; | 565 chosenSampleCount = 4; |
545 } else { | 566 } else { |
546 chosenSampleCount = 16; | 567 chosenSampleCount = 16; |
547 } | 568 } |
548 } | 569 } |
549 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? | 570 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? |
550 chosenSampleCount : 0; | 571 chosenSampleCount : 0; |
551 } | 572 } |
552 | 573 |
553 | 574 |
554 GrDrawContext* GrContext::drawContext(GrRenderTarget* rt, const SkSurfaceProps* surfaceProps) { | 575 GrDrawContext* GrContext::drawContext(GrRenderTarget* rt, const SkSurfaceProps* surfaceProps) { |
576 TAKE_DEBUG_MUTEX | |
555 return fDrawingManager->drawContext(rt, surfaceProps); | 577 return fDrawingManager->drawContext(rt, surfaceProps); |
556 } | 578 } |
557 | 579 |
558 bool GrContext::abandoned() const { | 580 bool GrContext::abandoned() const { |
581 TAKE_DEBUG_MUTEX | |
559 return fDrawingManager->abandoned(); | 582 return fDrawingManager->abandoned(); |
560 } | 583 } |
561 | 584 |
562 namespace { | 585 namespace { |
563 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { | 586 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { |
564 GrConfigConversionEffect::PMConversion pmToUPM; | 587 GrConfigConversionEffect::PMConversion pmToUPM; |
565 GrConfigConversionEffect::PMConversion upmToPM; | 588 GrConfigConversionEffect::PMConversion upmToPM; |
566 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upm ToPM); | 589 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upm ToPM); |
567 *pmToUPMValue = pmToUPM; | 590 *pmToUPMValue = pmToUPM; |
568 *upmToPMValue = upmToPM; | 591 *upmToPMValue = upmToPM; |
569 } | 592 } |
570 } | 593 } |
571 | 594 |
572 void GrContext::testPMConversionsIfNecessary(uint32_t flags) { | 595 void GrContext::testPMConversionsIfNecessary(uint32_t flags) { |
596 TAKE_DEBUG_MUTEX | |
573 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) { | 597 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) { |
574 SkAutoMutexAcquire ama(fTestPMConversionsMutex); | 598 SkAutoMutexAcquire ama(fTestPMConversionsMutex); |
575 if (!fDidTestPMConversions) { | 599 if (!fDidTestPMConversions) { |
576 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); | 600 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); |
577 fDidTestPMConversions = true; | 601 fDidTestPMConversions = true; |
578 } | 602 } |
579 } | 603 } |
580 } | 604 } |
581 | 605 |
582 const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture, | 606 const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture, |
583 bool swapRAndB, | 607 bool swapRAndB, |
584 const SkMatrix& matrix ) const { | 608 const SkMatrix& matrix ) const { |
609 TAKE_DEBUG_MUTEX | |
585 // We should have already called this->testPMConversionsIfNecessary(). | 610 // We should have already called this->testPMConversionsIfNecessary(). |
586 SkASSERT(fDidTestPMConversions); | 611 SkASSERT(fDidTestPMConversions); |
587 GrConfigConversionEffect::PMConversion pmToUPM = | 612 GrConfigConversionEffect::PMConversion pmToUPM = |
588 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); | 613 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); |
589 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { | 614 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { |
590 return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, mat rix); | 615 return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, mat rix); |
591 } else { | 616 } else { |
592 return nullptr; | 617 return nullptr; |
593 } | 618 } |
594 } | 619 } |
595 | 620 |
596 const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture, | 621 const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture, |
597 bool swapRAndB, | 622 bool swapRAndB, |
598 const SkMatrix& matrix ) const { | 623 const SkMatrix& matrix ) const { |
624 TAKE_DEBUG_MUTEX | |
599 // We should have already called this->testPMConversionsIfNecessary(). | 625 // We should have already called this->testPMConversionsIfNecessary(). |
600 SkASSERT(fDidTestPMConversions); | 626 SkASSERT(fDidTestPMConversions); |
601 GrConfigConversionEffect::PMConversion upmToPM = | 627 GrConfigConversionEffect::PMConversion upmToPM = |
602 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); | 628 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); |
603 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { | 629 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { |
604 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat rix); | 630 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat rix); |
605 } else { | 631 } else { |
606 return nullptr; | 632 return nullptr; |
607 } | 633 } |
608 } | 634 } |
609 | 635 |
610 bool GrContext::didFailPMUPMConversionTest() const { | 636 bool GrContext::didFailPMUPMConversionTest() const { |
637 TAKE_DEBUG_MUTEX | |
611 // We should have already called this->testPMConversionsIfNecessary(). | 638 // We should have already called this->testPMConversionsIfNecessary(). |
612 SkASSERT(fDidTestPMConversions); | 639 SkASSERT(fDidTestPMConversions); |
613 // The PM<->UPM tests fail or succeed together so we only need to check one. | 640 // The PM<->UPM tests fail or succeed together so we only need to check one. |
614 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion; | 641 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion; |
615 } | 642 } |
616 | 643 |
617 ////////////////////////////////////////////////////////////////////////////// | 644 ////////////////////////////////////////////////////////////////////////////// |
618 | 645 |
619 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes ) const { | 646 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes ) const { |
647 TAKE_DEBUG_MUTEX | |
620 if (maxTextures) { | 648 if (maxTextures) { |
621 *maxTextures = fResourceCache->getMaxResourceCount(); | 649 *maxTextures = fResourceCache->getMaxResourceCount(); |
622 } | 650 } |
623 if (maxTextureBytes) { | 651 if (maxTextureBytes) { |
624 *maxTextureBytes = fResourceCache->getMaxResourceBytes(); | 652 *maxTextureBytes = fResourceCache->getMaxResourceBytes(); |
625 } | 653 } |
626 } | 654 } |
627 | 655 |
628 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { | 656 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { |
657 TAKE_DEBUG_MUTEX | |
629 fResourceCache->setLimits(maxTextures, maxTextureBytes); | 658 fResourceCache->setLimits(maxTextures, maxTextureBytes); |
630 } | 659 } |
631 | 660 |
632 ////////////////////////////////////////////////////////////////////////////// | 661 ////////////////////////////////////////////////////////////////////////////// |
633 | 662 |
634 void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { | 663 void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { |
664 TAKE_DEBUG_MUTEX | |
635 fResourceCache->dumpMemoryStatistics(traceMemoryDump); | 665 fResourceCache->dumpMemoryStatistics(traceMemoryDump); |
636 } | 666 } |
OLD | NEW |