Index: src/gpu/GrGpu.cpp |
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp |
index 1397845f42de6d9bcf7d0ef931ee1e3672bae285..4cb96edd880144e69563f10b89485b6b8b88b5d2 100644 |
--- a/src/gpu/GrGpu.cpp |
+++ b/src/gpu/GrGpu.cpp |
@@ -46,8 +46,8 @@ GrMesh& GrMesh::operator =(const GrMesh& di) { |
GrGpu::GrGpu(GrContext* context) |
: fResetTimestamp(kExpiredTimestamp+1) |
, fResetBits(kAll_GrBackendState) |
- , fMultisampleSpecsAllocator(1) |
, fContext(context) { |
+ fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id. |
} |
GrGpu::~GrGpu() {} |
@@ -425,58 +425,63 @@ void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_ |
} |
} |
-inline static uint8_t multisample_specs_id(uint8_t numSamples, GrSurfaceOrigin origin, |
- const GrCaps& caps) { |
- if (!caps.sampleLocationsSupport()) { |
- return numSamples; |
+const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt, |
+ const GrStencilSettings& stencil) { |
+ SkASSERT(rt->desc().fSampleCnt > 1); |
+ |
+#ifndef SK_DEBUG |
+ // In debug mode we query the multisample info every time to verify the caching is correct. |
+ if (uint8_t id = rt->renderTargetPriv().accessMultisampleSpecsID()) { |
+ SkASSERT(id > 0 && id < fMultisampleSpecs.count()); |
+ return fMultisampleSpecs[id]; |
} |
+#endif |
- SkASSERT(numSamples < 128); |
- SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin); |
- return (numSamples << 1) | (origin - 1); |
+ int effectiveSampleCnt; |
+ SkSTArray<16, SkPoint, true> pattern; |
+ this->onGetMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &pattern); |
+ SkASSERT(effectiveSampleCnt >= rt->desc().fSampleCnt); |
+ |
+ uint8_t id; |
+ if (this->caps()->sampleLocationsSupport()) { |
+ SkASSERT(pattern.count() == effectiveSampleCnt); |
+ const auto& insertResult = fMultisampleSpecsIdMap.insert( |
+ MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255))); |
+ id = insertResult.first->second; |
+ if (insertResult.second) { |
+ // This means the insert did not find the pattern in the map already, and therefore an |
+ // actual insertion took place. (We don't expect to see many unique sample patterns.) |
+ const SkPoint* sampleLocations = insertResult.first->first.begin(); |
+ SkASSERT(id == fMultisampleSpecs.count()); |
+ fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations); |
+ } |
+ } else { |
+ id = effectiveSampleCnt; |
+ for (int i = fMultisampleSpecs.count(); i <= id; ++i) { |
+ fMultisampleSpecs.emplace_back(i, i, nullptr); |
+ } |
+ } |
+ SkASSERT(id > 0); |
+ SkASSERT(!rt->renderTargetPriv().accessMultisampleSpecsID() || |
+ rt->renderTargetPriv().accessMultisampleSpecsID() == id); |
- GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin); |
- GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin); |
+ rt->renderTargetPriv().accessMultisampleSpecsID() = id; |
+ return fMultisampleSpecs[id]; |
} |
-const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt, |
- const GrStencilSettings& stencil) { |
- const GrSurfaceDesc& desc = rt->desc(); |
- uint8_t surfDescKey = multisample_specs_id(desc.fSampleCnt, desc.fOrigin, *this->caps()); |
- if (fMultisampleSpecsMap.count() > surfDescKey && fMultisampleSpecsMap[surfDescKey]) { |
-#if !defined(SK_DEBUG) |
- // In debug mode we query the multisample info every time and verify the caching is correct. |
- return *fMultisampleSpecsMap[surfDescKey]; |
-#endif |
+bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a, |
+ const SamplePattern& b) const { |
+ if (a.count() != b.count()) { |
+ return a.count() < b.count(); |
} |
- int effectiveSampleCnt; |
- SkAutoTDeleteArray<SkPoint> locations(nullptr); |
- this->onGetMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &locations); |
- SkASSERT(effectiveSampleCnt && effectiveSampleCnt >= desc.fSampleCnt); |
- uint8_t effectiveKey = multisample_specs_id(effectiveSampleCnt, desc.fOrigin, *this->caps()); |
- if (fMultisampleSpecsMap.count() > effectiveKey && fMultisampleSpecsMap[effectiveKey]) { |
- const MultisampleSpecs& specs = *fMultisampleSpecsMap[effectiveKey]; |
- SkASSERT(effectiveKey == specs.fUniqueID); |
- SkASSERT(effectiveSampleCnt == specs.fEffectiveSampleCnt); |
- SkASSERT(!this->caps()->sampleLocationsSupport() || |
- !memcmp(locations.get(), specs.fSampleLocations.get(), |
- effectiveSampleCnt * sizeof(SkPoint))); |
- SkASSERT(surfDescKey <= effectiveKey); |
- SkASSERT(!fMultisampleSpecsMap[surfDescKey] || fMultisampleSpecsMap[surfDescKey] == &specs); |
- fMultisampleSpecsMap[surfDescKey] = &specs; |
- return specs; |
- } |
- const MultisampleSpecs& specs = *new (&fMultisampleSpecsAllocator) |
- MultisampleSpecs{effectiveKey, effectiveSampleCnt, locations.release()}; |
- if (fMultisampleSpecsMap.count() <= effectiveKey) { |
- int n = 1 + effectiveKey - fMultisampleSpecsMap.count(); |
- fMultisampleSpecsMap.push_back_n(n, (const MultisampleSpecs*) nullptr); |
- } |
- fMultisampleSpecsMap[effectiveKey] = &specs; |
- if (effectiveSampleCnt != desc.fSampleCnt) { |
- SkASSERT(surfDescKey < effectiveKey); |
- fMultisampleSpecsMap[surfDescKey] = &specs; |
- } |
- return specs; |
+ for (int i = 0; i < a.count(); ++i) { |
+ // This doesn't have geometric meaning. We just need to define an ordering for std::map. |
+ if (a[i].x() != b[i].x()) { |
+ return a[i].x() < b[i].x(); |
+ } |
+ if (a[i].y() != b[i].y()) { |
+ return a[i].y() < b[i].y(); |
+ } |
+ } |
+ return false; // Equal. |
} |
- |