Move GrGeometryProcessor's textures out of classes and into
GrPipeline::FixedDynamicState.
This will allow specification of different textures for different
GrMeshes using GrPipeline::DynamicStateArrays in a future change.
Change-Id: I4a7897df33a84e4072151149e5d586dca074393f
Reviewed-on: https://skia-review.googlesource.com/145264
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 5a50314..f18a77d 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -240,6 +240,9 @@
SkASSERT(LazyState::kFully != this->lazyInstantiationState());
return fHeight;
}
+
+ SkISize isize() const { return {fWidth, fHeight}; }
+
int worstCaseWidth() const;
int worstCaseHeight() const;
/**
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp
index 42e00f3..f4de5c6 100644
--- a/src/gpu/GrGpuCommandBuffer.cpp
+++ b/src/gpu/GrGpuCommandBuffer.cpp
@@ -47,6 +47,11 @@
if (pipeline.isBad() || !primProc.instantiate(resourceProvider)) {
return false;
}
+ for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
+ if (!fixedDynamicState->fPrimitiveProcessorTextures[i]->instantiate(resourceProvider)) {
+ return false;
+ }
+ }
if (primProc.numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) {
this->gpu()->stats()->incNumFailedDraws();
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index 8d8b7bb..128a98c 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -129,6 +129,9 @@
auto& draw = fDraws.append(&fArena);
GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
+ for (int i = 0; i < gp->numTextureSamplers(); ++i) {
+ fixedDynamicState->fPrimitiveProcessorTextures[i]->addPendingRead();
+ }
draw.fGeometryProcessor.reset(gp);
draw.fPipeline = pipeline;
draw.fFixedDynamicState = fixedDynamicState;
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 66ac34c..dcdcbeb 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -118,6 +118,11 @@
// that share a geometry processor into a Draw is that it allows the Gpu object to setup
// the shared state once and then issue draws for each mesh.
struct Draw {
+ ~Draw() {
+ for (int i = 0; i < fGeometryProcessor->numTextureSamplers(); ++i) {
+ fFixedDynamicState->fPrimitiveProcessorTextures[i]->completedRead();
+ }
+ }
int fMeshCnt = 0;
GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
const GrPipeline* fPipeline;
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 24dd9f8..aaf36be 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -76,8 +76,11 @@
* 2) DynamicStateArrays - use this to specify per mesh values for dynamic state.
**/
struct FixedDynamicState {
- FixedDynamicState(const SkIRect& scissorRect) : fScissorRect(scissorRect) {}
- SkIRect fScissorRect;
+ explicit FixedDynamicState(const SkIRect& scissorRect) : fScissorRect(scissorRect) {}
+ FixedDynamicState() = default;
+ SkIRect fScissorRect = SkIRect::EmptyIRect();
+ // Must have GrPrimitiveProcessor::numTextureSamplers() entries. Can be null if no samplers.
+ GrTextureProxy** fPrimitiveProcessorTextures = nullptr;
};
/**
diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp
index 84db9ca..6d2b1e9 100644
--- a/src/gpu/GrPrimitiveProcessor.cpp
+++ b/src/gpu/GrPrimitiveProcessor.cpp
@@ -74,33 +74,6 @@
}
#endif
-void GrPrimitiveProcessor::addPendingIOs() const {
- for (int i = 0; i < fTextureSamplerCnt; ++i) {
- this->textureSampler(i).proxyRef()->markPendingIO();
- }
-}
-
-void GrPrimitiveProcessor::removeRefs() const {
- for (int i = 0; i < fTextureSamplerCnt; ++i) {
- this->textureSampler(i).proxyRef()->removeRef();
- }
-}
-
-void GrPrimitiveProcessor::pendingIOComplete() const {
- for (int i = 0; i < fTextureSamplerCnt; ++i) {
- this->textureSampler(i).proxyRef()->pendingIOComplete();
- }
-}
-
-bool GrPrimitiveProcessor::instantiate(GrResourceProvider* resourceProvider) const {
- for (int i = 0; i < fTextureSamplerCnt; ++i) {
- if (!this->textureSampler(i).instantiate(resourceProvider)) {
- return false;
- }
- }
- return true;
-}
-
uint32_t
GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
int numCoords) const {
@@ -122,34 +95,50 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
-GrPrimitiveProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy,
- const GrSamplerState& samplerState,
- GrShaderFlags visibility) {
- this->reset(std::move(proxy), samplerState, visibility);
+static inline GrSamplerState::Filter clamp_filter(GrTextureType type,
+ GrSamplerState::Filter requestedFilter) {
+ if (GrTextureTypeHasRestrictedSampling(type)) {
+ return SkTMin(requestedFilter, GrSamplerState::Filter::kBilerp);
+ }
+ return requestedFilter;
}
-GrPrimitiveProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy,
+GrPrimitiveProcessor::TextureSampler::TextureSampler(GrTextureType textureType,
+ GrPixelConfig config,
+ const GrSamplerState& samplerState,
+ GrShaderFlags visibility) {
+ this->reset(textureType, config, samplerState, visibility);
+}
+
+GrPrimitiveProcessor::TextureSampler::TextureSampler(GrTextureType textureType,
+ GrPixelConfig config,
GrSamplerState::Filter filterMode,
GrSamplerState::WrapMode wrapXAndY,
GrShaderFlags visibility) {
- this->reset(std::move(proxy), filterMode, wrapXAndY, visibility);
+ this->reset(textureType, config, filterMode, wrapXAndY, visibility);
}
-void GrPrimitiveProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> proxy,
+void GrPrimitiveProcessor::TextureSampler::reset(GrTextureType textureType,
+ GrPixelConfig config,
const GrSamplerState& samplerState,
GrShaderFlags visibility) {
- fProxyRef.setProxy(std::move(proxy), kRead_GrIOType);
+ SkASSERT(kUnknown_GrPixelConfig != config);
fSamplerState = samplerState;
- fSamplerState.setFilterMode(SkTMin(samplerState.filter(), this->proxy()->highestFilterMode()));
+ fSamplerState.setFilterMode(clamp_filter(textureType, samplerState.filter()));
+ fTextureType = textureType;
+ fConfig = config;
fVisibility = visibility;
}
-void GrPrimitiveProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> proxy,
+void GrPrimitiveProcessor::TextureSampler::reset(GrTextureType textureType,
+ GrPixelConfig config,
GrSamplerState::Filter filterMode,
GrSamplerState::WrapMode wrapXAndY,
GrShaderFlags visibility) {
- fProxyRef.setProxy(std::move(proxy), kRead_GrIOType);
- filterMode = SkTMin(filterMode, this->proxy()->highestFilterMode());
+ SkASSERT(kUnknown_GrPixelConfig != config);
+ filterMode = clamp_filter(textureType, filterMode);
fSamplerState = GrSamplerState(wrapXAndY, filterMode);
+ fTextureType = textureType;
+ fConfig = config;
fVisibility = visibility;
}
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index ddebd21..8c4d0aa 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -36,10 +36,12 @@
class GrGLSLPrimitiveProcessor;
-/*
+/**
* GrPrimitiveProcessor defines an interface which all subclasses must implement. All
* GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
* pipelines, and they must provide some notion of equality
+ *
+ * TODO: Overrides of GrProgramElement virtuals don't do anything anymore. Remove this base class.
*/
class GrPrimitiveProcessor : public GrProcessor, public GrProgramElement {
public:
@@ -136,7 +138,7 @@
virtual float getSampleShading() const { return 0.0; }
- bool instantiate(GrResourceProvider*) const;
+ bool instantiate(GrResourceProvider*) const { return true; }
protected:
void setVertexAttributeCnt(int cnt) {
@@ -164,9 +166,9 @@
inline static const TextureSampler& IthTextureSampler(int i);
private:
- void addPendingIOs() const final;
- void removeRefs() const final;
- void pendingIOComplete() const final;
+ void addPendingIOs() const final {}
+ void removeRefs() const final {}
+ void pendingIOComplete() const final {}
void notifyRefCntIsZero() const final {}
virtual const Attribute& onVertexAttribute(int) const = 0;
@@ -190,9 +192,9 @@
public:
TextureSampler() = default;
- TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerState&, GrShaderFlags visibility);
+ TextureSampler(GrTextureType, GrPixelConfig, const GrSamplerState&, GrShaderFlags visibility);
- explicit TextureSampler(sk_sp<GrTextureProxy>,
+ explicit TextureSampler(GrTextureType, GrPixelConfig,
GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp,
GrShaderFlags visibility = kFragment_GrShaderFlag);
@@ -200,36 +202,25 @@
TextureSampler(const TextureSampler&) = delete;
TextureSampler& operator=(const TextureSampler&) = delete;
- void reset(sk_sp<GrTextureProxy>, const GrSamplerState&,
+ void reset(GrTextureType, GrPixelConfig, const GrSamplerState&,
GrShaderFlags visibility = kFragment_GrShaderFlag);
- void reset(sk_sp<GrTextureProxy>,
+ void reset(GrTextureType, GrPixelConfig,
GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp,
GrShaderFlags visibility = kFragment_GrShaderFlag);
- bool instantiate(GrResourceProvider* resourceProvider) const {
- return SkToBool(fProxyRef.get()->instantiate(resourceProvider));
- }
+ GrTextureType textureType() const { return fTextureType; }
+ GrPixelConfig config() const { return fConfig; }
- // 'peekTexture' should only ever be called after a successful 'instantiate' call
- GrTexture* peekTexture() const {
- SkASSERT(fProxyRef.get()->peekTexture());
- return fProxyRef.get()->peekTexture();
- }
-
- GrTextureProxy* proxy() const { return fProxyRef.get(); }
GrShaderFlags visibility() const { return fVisibility; }
const GrSamplerState& samplerState() const { return fSamplerState; }
- bool isInitialized() const { return SkToBool(fProxyRef.get()); }
- /**
- * For internal use by GrPrimitiveProcessor.
- */
- const GrTextureProxyRef* proxyRef() const { return &fProxyRef; }
+ bool isInitialized() const { return fConfig != kUnknown_GrPixelConfig; }
private:
- GrTextureProxyRef fProxyRef;
GrSamplerState fSamplerState;
+ GrTextureType fTextureType = GrTextureType::k2D;
+ GrPixelConfig fConfig = kUnknown_GrPixelConfig;
GrShaderFlags fVisibility = kNone_GrShaderFlags;
};
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index e99a947..5c10b9f 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -80,8 +80,7 @@
uint16_t* k16 = reinterpret_cast<uint16_t*>(b->add32n(word32Count));
for (int i = 0; i < numTextureSamplers; ++i) {
const GrPrimitiveProcessor::TextureSampler& sampler = pp.textureSampler(i);
- const GrTexture* tex = sampler.peekTexture();
- k16[i] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps);
+ k16[i] = sampler_key(sampler.textureType(), sampler.config(), caps);
}
// zero the last 16 bits if the number of uniforms for samplers is odd.
if (numTextureSamplers & 0x1) {
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 016756a..a2c0c14 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -312,7 +312,7 @@
}
}
-inline void GrCCDrawPathsOp::recordInstance(const GrTextureProxy* atlasProxy, int instanceIdx) {
+inline void GrCCDrawPathsOp::recordInstance(GrTextureProxy* atlasProxy, int instanceIdx) {
if (fInstanceRanges.empty()) {
fInstanceRanges.push_back({atlasProxy, instanceIdx});
return;
@@ -347,8 +347,9 @@
for (const InstanceRange& range : fInstanceRanges) {
SkASSERT(range.fEndInstanceIdx > baseInstance);
- GrCCPathProcessor pathProc(flushState->resourceProvider(), sk_ref_sp(range.fAtlasProxy),
- fViewMatrixIfUsingLocalCoords);
+ GrCCPathProcessor pathProc(range.fAtlasProxy, fViewMatrixIfUsingLocalCoords);
+ GrTextureProxy* atlasProxy = range.fAtlasProxy;
+ fixedDynamicState.fPrimitiveProcessorTextures = &atlasProxy;
pathProc.drawPaths(flushState, pipeline, &fixedDynamicState, *resources, baseInstance,
range.fEndInstanceIdx, this->bounds());
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index 9ef317f..c877e8b 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -80,7 +80,7 @@
const SkIRect& maskDevIBounds, Visibility maskVisibility,
const SkRect& devBounds, GrPaint&&);
- void recordInstance(const GrTextureProxy* atlasProxy, int instanceIdx);
+ void recordInstance(GrTextureProxy* atlasProxy, int instanceIdx);
const SkMatrix fViewMatrixIfUsingLocalCoords;
@@ -110,7 +110,7 @@
GrProcessorSet fProcessors;
struct InstanceRange {
- const GrTextureProxy* fAtlasProxy;
+ GrTextureProxy* fAtlasProxy;
int fEndInstanceIdx;
};
diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp
index ae3cba3..4a9a8aa 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -79,12 +79,14 @@
}
}
-GrCCPathProcessor::GrCCPathProcessor(GrResourceProvider* resourceProvider,
- sk_sp<GrTextureProxy> atlas,
+GrCCPathProcessor::GrCCPathProcessor(const GrTextureProxy* atlas,
const SkMatrix& viewMatrixIfUsingLocalCoords)
: INHERITED(kGrCCPathProcessor_ClassID)
- , fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest,
- GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) {
+ , fAtlasAccess(atlas->textureType(), atlas->config(), GrSamplerState::Filter::kNearest,
+ GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag)
+ , fAtlasSize(atlas->isize())
+ , fAtlasOrigin(atlas->origin()) {
+ // TODO: Can we just assert that atlas has GrCCAtlas::kTextureOrigin and remove fAtlasOrigin?
this->setInstanceAttributeCnt(kNumInstanceAttribs);
// Check that instance attributes exactly match Instance struct layout.
SkASSERT(!strcmp(this->instanceAttribute(0).name(), "devbounds"));
@@ -98,8 +100,6 @@
SkASSERT(this->debugOnly_instanceStride() == sizeof(Instance));
this->setVertexAttributeCnt(1);
-
- fAtlasAccess.instantiate(resourceProvider);
this->setTextureSamplerCnt(1);
if (!viewMatrixIfUsingLocalCoords.invert(&fLocalMatrix)) {
@@ -115,8 +115,8 @@
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const GrCCPathProcessor& proc = primProc.cast<GrCCPathProcessor>();
- pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.atlas()->width(),
- 1.0f / proc.atlas()->height());
+ pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.atlasSize().fWidth,
+ 1.0f / proc.atlasSize().fHeight);
this->setTransformDataHelper(proc.localMatrix(), pdman, &transformIter);
}
@@ -210,10 +210,10 @@
// Convert to atlas coordinates in order to do our texture lookup.
v->codeAppendf("float2 atlascoord = octocoord + float2(%s);",
proc.getInstanceAttrib(InstanceAttribs::kDevToAtlasOffset).name());
- if (kTopLeft_GrSurfaceOrigin == proc.atlasProxy()->origin()) {
+ if (kTopLeft_GrSurfaceOrigin == proc.atlasOrigin()) {
v->codeAppendf("%s.xy = atlascoord * %s;", texcoord.vsOut(), atlasAdjust);
} else {
- SkASSERT(kBottomLeft_GrSurfaceOrigin == proc.atlasProxy()->origin());
+ SkASSERT(kBottomLeft_GrSurfaceOrigin == proc.atlasOrigin());
v->codeAppendf("%s.xy = float2(atlascoord.x * %s.x, 1 - atlascoord.y * %s.y);",
texcoord.vsOut(), atlasAdjust, atlasAdjust);
}
diff --git a/src/gpu/ccpr/GrCCPathProcessor.h b/src/gpu/ccpr/GrCCPathProcessor.h
index 752083a..394746b 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.h
+++ b/src/gpu/ccpr/GrCCPathProcessor.h
@@ -69,12 +69,12 @@
static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*);
static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*);
- GrCCPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas,
+ GrCCPathProcessor(const GrTextureProxy* atlas,
const SkMatrix& viewMatrixIfUsingLocalCoords = SkMatrix::I());
const char* name() const override { return "GrCCPathProcessor"; }
- const GrSurfaceProxy* atlasProxy() const { return fAtlasAccess.proxy(); }
- const GrTexture* atlas() const { return fAtlasAccess.peekTexture(); }
+ const SkISize& atlasSize() const { return fAtlasSize; }
+ GrSurfaceOrigin atlasOrigin() const { return fAtlasOrigin; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
const Attribute& getInstanceAttrib(InstanceAttribs attribID) const {
int idx = static_cast<int>(attribID);
@@ -96,6 +96,9 @@
const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
const TextureSampler fAtlasAccess;
+ SkISize fAtlasSize;
+ GrSurfaceOrigin fAtlasOrigin;
+
SkMatrix fLocalMatrix;
static constexpr Attribute kInstanceAttribs[kNumInstanceAttribs] = {
{"devbounds", kFloat4_GrVertexAttribType},
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index aed1af7..d709a8b 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -65,14 +65,18 @@
void onExecute(GrOpFlushState* flushState) override {
SkASSERT(fStashedAtlasProxy);
+ GrPipeline::FixedDynamicState dynamicState;
+ auto atlasProxy = fStashedAtlasProxy.get();
+ dynamicState.fPrimitiveProcessorTextures = &atlasProxy;
+
GrPipeline pipeline(flushState->proxy(), GrPipeline::ScissorState::kDisabled,
SkBlendMode::kSrc);
- GrCCPathProcessor pathProc(flushState->resourceProvider(), std::move(fStashedAtlasProxy));
- pathProc.drawPaths(flushState, pipeline, nullptr, *fResources, fBaseInstance, fEndInstance,
- this->bounds());
+ GrCCPathProcessor pathProc(atlasProxy);
+ pathProc.drawPaths(flushState, pipeline, &dynamicState, *fResources, fBaseInstance,
+ fEndInstance, this->bounds());
// Ensure we released the stashed atlas proxy. This allows its underlying texture to be
// reused as the current flush's mainline CCPR atlas if needed.
- SkASSERT(!fStashedAtlasProxy);
+ fStashedAtlasProxy.reset();
}
private:
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 32da45c..ee38f43 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -86,13 +86,12 @@
fColor = btgp.color();
}
- SkASSERT(btgp.numTextureSamplers() >= 1);
- GrTexture* atlas = btgp.textureSampler(0).peekTexture();
- SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
+ const SkISize& atlasSize = btgp.atlasSize();
+ SkASSERT(SkIsPow2(atlasSize.fWidth) && SkIsPow2(atlasSize.fHeight));
- if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
- pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
- fAtlasSize.set(atlas->width(), atlas->height());
+ if (fAtlasSize != atlasSize) {
+ pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlasSize.fWidth, 1.0f / atlasSize.fHeight);
+ fAtlasSize = atlasSize;
}
this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter);
}
@@ -149,9 +148,13 @@
this->setVertexAttributeCnt(cnt);
+ if (numActiveProxies) {
+ fAtlasSize = proxies[0]->isize();
+ }
for (int i = 0; i < numActiveProxies; ++i) {
SkASSERT(proxies[i]);
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
this->setTextureSamplerCnt(numActiveProxies);
}
@@ -165,11 +168,16 @@
const GrSamplerState& params) {
SkASSERT(numActiveProxies <= kMaxTextures);
+ if (!fTextureSamplers[0].isInitialized()) {
+ fAtlasSize = proxies[0]->isize();
+ }
+
for (int i = 0; i < numActiveProxies; ++i) {
SkASSERT(proxies[i]);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
if (!fTextureSamplers[i].isInitialized()) {
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
}
this->setTextureSamplerCnt(numActiveProxies);
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.h b/src/gpu/effects/GrBitmapTextGeoProc.h
index 1bc0620..d2d530e 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.h
+++ b/src/gpu/effects/GrBitmapTextGeoProc.h
@@ -21,6 +21,7 @@
*/
class GrBitmapTextGeoProc : public GrGeometryProcessor {
public:
+ static constexpr int kMaxTextures = 4;
static sk_sp<GrGeometryProcessor> Make(GrColor color,
const sk_sp<GrTextureProxy>* proxies,
@@ -44,6 +45,7 @@
bool hasVertexColor() const { return fInColor.isInitialized(); }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
bool usesW() const { return fUsesW; }
+ const SkISize& atlasSize() const { return fAtlasSize; }
void addNewProxies(const sk_sp<GrTextureProxy>*, int numActiveProxies, const GrSamplerState&);
@@ -52,8 +54,6 @@
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override;
private:
- static constexpr int kMaxTextures = 4;
-
GrBitmapTextGeoProc(GrColor, const sk_sp<GrTextureProxy>* proxies, int numProxies,
const GrSamplerState& params, GrMaskFormat format,
const SkMatrix& localMatrix, bool usesW);
@@ -64,6 +64,7 @@
GrColor fColor;
SkMatrix fLocalMatrix;
bool fUsesW;
+ SkISize fAtlasSize; // size for all textures used with fTextureSamplers[].
TextureSampler fTextureSamplers[kMaxTextures];
Attribute fInPosition;
Attribute fInColor;
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 351e191..59ec5da 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -172,15 +172,13 @@
}
#endif
- SkASSERT(dfa8gp.numTextureSamplers() >= 1);
- GrTexture* atlas = dfa8gp.textureSampler(0).peekTexture();
- SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
+ const SkISize& atlasSize = dfa8gp.atlasSize();
+ SkASSERT(SkIsPow2(atlasSize.fWidth) && SkIsPow2(atlasSize.fHeight));
- if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
- fAtlasSize.set(atlas->width(), atlas->height());
- pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
+ if (fAtlasSize != atlasSize) {
+ pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlasSize.fWidth, 1.0f / atlasSize.fHeight);
+ fAtlasSize = atlasSize;
}
-
this->setTransformDataHelper(dfa8gp.localMatrix(), pdman, &transformIter);
}
@@ -234,9 +232,13 @@
}
this->setVertexAttributeCnt(3);
+ if (numProxies) {
+ fAtlasSize = proxies[0]->isize();
+ }
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]);
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
this->setTextureSamplerCnt(numProxies);
}
@@ -246,10 +248,15 @@
const GrSamplerState& params) {
SkASSERT(numProxies <= kMaxTextures);
+ if (!fTextureSamplers[0].isInitialized()) {
+ fAtlasSize = proxies[0]->isize();
+ }
+
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
if (!fTextureSamplers[i].isInitialized()) {
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
}
this->setTextureSamplerCnt(numProxies);
@@ -460,13 +467,11 @@
pdman.setMatrix3f(fMatrixUniform, matrix);
}
- SkASSERT(dfpgp.numTextureSamplers() >= 1);
- GrTexture* atlas = dfpgp.textureSampler(0).peekTexture();
- SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-
- if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
- fAtlasSize.set(atlas->width(), atlas->height());
- pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
+ const SkISize& atlasSize = dfpgp.atlasSize();
+ SkASSERT(SkIsPow2(atlasSize.fWidth) && SkIsPow2(atlasSize.fHeight));
+ if (fAtlasSize != atlasSize) {
+ pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlasSize.fWidth, 1.0f / atlasSize.fHeight);
+ fAtlasSize = atlasSize;
}
if (dfpgp.matrix().hasPerspective()) {
@@ -515,9 +520,15 @@
SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
this->setVertexAttributeCnt(3);
+
+ if (numProxies) {
+ fAtlasSize = proxies[0]->isize();
+ }
+
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]);
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
this->setTextureSamplerCnt(numProxies);
}
@@ -527,11 +538,16 @@
const GrSamplerState& params) {
SkASSERT(numProxies <= kMaxTextures);
+ if (!fTextureSamplers[0].isInitialized()) {
+ fAtlasSize = proxies[0]->isize();
+ }
+
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
if (!fTextureSamplers[i].isInitialized()) {
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
}
this->setTextureSamplerCnt(numProxies);
@@ -773,13 +789,11 @@
fDistanceAdjust = wa;
}
- SkASSERT(dflcd.numTextureSamplers() >= 1);
- GrTexture* atlas = dflcd.textureSampler(0).peekTexture();
- SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-
- if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
- fAtlasSize.set(atlas->width(), atlas->height());
- pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
+ const SkISize& atlasSize = dflcd.atlasSize();
+ SkASSERT(SkIsPow2(atlasSize.fWidth) && SkIsPow2(atlasSize.fHeight));
+ if (fAtlasSize != atlasSize) {
+ pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlasSize.fWidth, 1.0f / atlasSize.fHeight);
+ fAtlasSize = atlasSize;
}
this->setTransformDataHelper(dflcd.localMatrix(), pdman, &transformIter);
}
@@ -829,9 +843,14 @@
}
this->setVertexAttributeCnt(3);
+ if (numProxies) {
+ fAtlasSize = proxies[0]->isize();
+ }
+
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]);
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
this->setTextureSamplerCnt(numProxies);
}
@@ -841,11 +860,16 @@
const GrSamplerState& params) {
SkASSERT(numProxies <= kMaxTextures);
+ if (!fTextureSamplers[0].isInitialized()) {
+ fAtlasSize = proxies[0]->isize();
+ }
+
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]);
+ SkASSERT(proxies[i]->isize() == fAtlasSize);
if (!fTextureSamplers[i].isInitialized()) {
- fTextureSamplers[i].reset(std::move(proxies[i]), params);
+ fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
}
}
this->setTextureSamplerCnt(numProxies);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h
index a0fb9d7..fcd98aa 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.h
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.h
@@ -53,6 +53,8 @@
*/
class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor {
public:
+ static constexpr int kMaxTextures = 4;
+
/** The local matrix should be identity if local coords are not required by the GrPipeline. */
#ifdef SK_GAMMA_APPLY_TO_A8
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy>* proxies,
@@ -84,6 +86,7 @@
float getDistanceAdjust() const { return fDistanceAdjust; }
#endif
uint32_t getFlags() const { return fFlags; }
+ const SkISize& atlasSize() const { return fAtlasSize; }
void addNewProxies(const sk_sp<GrTextureProxy>* proxies, int numProxies, const GrSamplerState&);
@@ -106,9 +109,8 @@
const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
- static constexpr int kMaxTextures = 4;
-
TextureSampler fTextureSamplers[kMaxTextures];
+ SkISize fAtlasSize; // size for all textures used with fTextureSamplers[].
SkMatrix fLocalMatrix;
Attribute fInPosition;
uint32_t fFlags;
@@ -132,6 +134,7 @@
*/
class GrDistanceFieldPathGeoProc : public GrGeometryProcessor {
public:
+ static constexpr int kMaxTextures = 4;
/** The local matrix should be identity if local coords are not required by the GrPipeline. */
static sk_sp<GrGeometryProcessor> Make(const SkMatrix& matrix,
@@ -151,6 +154,7 @@
const Attribute& inTextureCoords() const { return kInTextureCoords; }
const SkMatrix& matrix() const { return fMatrix; }
uint32_t getFlags() const { return fFlags; }
+ const SkISize& atlasSize() const { return fAtlasSize; }
void addNewProxies(const sk_sp<GrTextureProxy>*, int numActiveProxies, const GrSamplerState&);
@@ -159,8 +163,6 @@
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
private:
- static constexpr int kMaxTextures = 4;
-
GrDistanceFieldPathGeoProc(const SkMatrix& matrix,
const sk_sp<GrTextureProxy>* proxies,
int numActiveProxies,
@@ -169,8 +171,9 @@
const Attribute& onVertexAttribute(int i) const override;
const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
- SkMatrix fMatrix; // view matrix if perspective, local matrix otherwise
+ SkMatrix fMatrix; // view matrix if perspective, local matrix otherwise
TextureSampler fTextureSamplers[kMaxTextures];
+ SkISize fAtlasSize; // size for all textures used with fTextureSamplers[].
uint32_t fFlags;
static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType};
static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
@@ -189,6 +192,8 @@
*/
class GrDistanceFieldLCDTextGeoProc : public GrGeometryProcessor {
public:
+ static constexpr int kMaxTextures = 4;
+
struct DistanceAdjust {
SkScalar fR, fG, fB;
static DistanceAdjust Make(SkScalar r, SkScalar g, SkScalar b) {
@@ -225,6 +230,7 @@
DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; }
uint32_t getFlags() const { return fFlags; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
+ const SkISize& atlasSize() const { return fAtlasSize; }
void addNewProxies(const sk_sp<GrTextureProxy>*, int numActiveProxies, const GrSamplerState&);
@@ -240,9 +246,8 @@
const Attribute& onVertexAttribute(int) const override;
const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
- static constexpr int kMaxTextures = 4;
-
TextureSampler fTextureSamplers[kMaxTextures];
+ SkISize fAtlasSize; // size for all textures used with fTextureSamplers[].
const SkMatrix fLocalMatrix;
DistanceAdjust fDistanceAdjust;
Attribute fInPosition;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index cc858a8..7ef043b 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1675,8 +1675,10 @@
}
void GrGLGpu::generateMipmapsForProcessorTextures(const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline) {
+ const GrPipeline& pipeline,
+ const GrTextureProxy* const primProcTextures[]) {
auto genLevelsIfNeeded = [this](GrTexture* tex, const GrSamplerState& sampler) {
+ SkASSERT(tex);
if (sampler.filter() == GrSamplerState::Filter::kMipMap &&
tex->texturePriv().mipMapped() == GrMipMapped::kYes &&
tex->texturePriv().mipMapsAreDirty()) {
@@ -1686,8 +1688,8 @@
};
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
- const auto& textureSampler = primProc.textureSampler(i);
- genLevelsIfNeeded(textureSampler.peekTexture(), textureSampler.samplerState());
+ GrTexture* tex = primProcTextures[i]->peekTexture();
+ genLevelsIfNeeded(tex, primProc.textureSampler(i).samplerState());
}
GrFragmentProcessor::Iter iter(pipeline);
@@ -1708,8 +1710,11 @@
GrCapsDebugf(this->caps(), "Failed to create program!\n");
return false;
}
-
- this->generateMipmapsForProcessorTextures(primProc, pipeline);
+ const GrTextureProxy* const* primProcProxies = nullptr;
+ if (fixedDynamicState) {
+ primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
+ }
+ this->generateMipmapsForProcessorTextures(primProc, pipeline, primProcProxies);
GrXferProcessor::BlendInfo blendInfo;
pipeline.getXferProcessor().getBlendInfo(&blendInfo);
@@ -1726,7 +1731,7 @@
this->flushBlend(blendInfo, swizzle);
}
- fHWProgram->setData(primProc, pipeline);
+ fHWProgram->updateUniformsAndTextureBindings(primProc, pipeline, primProcProxies);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget());
GrStencilSettings stencil;
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 32b2945..0f1127a 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -247,7 +247,9 @@
void setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]);
- void generateMipmapsForProcessorTextures(const GrPrimitiveProcessor&, const GrPipeline&);
+ void generateMipmapsForProcessorTextures(
+ const GrPrimitiveProcessor&, const GrPipeline&,
+ const GrTextureProxy* const primitiveProcessorTextures[]);
// Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
// willDrawPoints must be true if point primitives will be rendered after setting the GL state.
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index e0eccf2..9e90642 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -72,7 +72,10 @@
///////////////////////////////////////////////////////////////////////////////
-void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) {
+void GrGLProgram::updateUniformsAndTextureBindings(const GrPrimitiveProcessor& primProc,
+ const GrPipeline& pipeline,
+ const GrTextureProxy* const primProcTextures[]) {
+ SkASSERT(primProcTextures || !primProc.numTextureSamplers());
this->setRenderTargetState(primProc, pipeline.proxy());
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
@@ -85,9 +88,8 @@
fPrimitiveProcessor->setData(fProgramDataManager, primProc,
GrFragmentProcessor::CoordTransformIter(pipeline));
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
- const GrPrimitiveProcessor::TextureSampler& sampler = primProc.textureSampler(i);
- fGpu->bindTexture(nextTexSamplerIdx++, sampler.samplerState(),
- static_cast<GrGLTexture*>(sampler.peekTexture()));
+ auto* tex = static_cast<GrGLTexture*>(primProcTextures[i]->peekTexture());
+ fGpu->bindTexture(nextTexSamplerIdx++, primProc.textureSampler(i).samplerState(), tex);
}
this->setFragmentData(pipeline, &nextTexSamplerIdx);
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index b05b536..ca9253c 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -19,6 +19,7 @@
class GrPipeline;
class GrPrimitiveProcessor;
class GrRenderTargetProxy;
+class GrTextureProxy;
/**
* This class manages a GPU program and records per-program information. It also records the vertex
@@ -110,12 +111,13 @@
};
/**
- * This function uploads uniforms, calls each GrGL*Processor's setData, and retrieves the
- * textures that need to be bound on each unit. It is the caller's responsibility to ensure
- * the program is bound before calling, and to bind the outgoing textures to their respective
- * units upon return. (Each index in the array corresponds to its matching GL texture unit.)
+ * This function uploads uniforms, calls each GrGLSL*Processor's setData. It binds all fragment
+ * processor textures. Primitive process textures are also bound here but are passed separately.
+ *
+ * It is the caller's responsibility to ensure the program is bound before calling.
*/
- void setData(const GrPrimitiveProcessor&, const GrPipeline&);
+ void updateUniformsAndTextureBindings(const GrPrimitiveProcessor&, const GrPipeline&,
+ const GrTextureProxy* const primitiveProcessorTextures[]);
int vertexStride() const { return fVertexStride; }
int instanceStride() const { return fInstanceStride; }
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index b0cf816..66e333a 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -101,9 +101,8 @@
SkString name;
name.printf("TextureSampler_%d", i);
const auto& sampler = proc.textureSampler(i);
- GrTextureType textureType = sampler.peekTexture()->texturePriv().textureType();
- texSamplers[i] = this->emitSampler(textureType, sampler.peekTexture()->config(),
- name.c_str(), sampler.visibility());
+ texSamplers[i] = this->emitSampler(sampler.textureType(), sampler.config(), name.c_str(),
+ sampler.visibility());
}
GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index cfd0c45..a6e2bce 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -295,9 +295,16 @@
}
SkASSERT(proxies[0]);
+ static constexpr int kMaxTextures = GrBitmapTextGeoProc::kMaxTextures;
+ GR_STATIC_ASSERT(GrDistanceFieldA8TextGeoProc::kMaxTextures == kMaxTextures);
+ GR_STATIC_ASSERT(GrDistanceFieldLCDTextGeoProc::kMaxTextures == kMaxTextures);
+
static const uint32_t kPipelineFlags = 0;
auto pipe = target->makePipeline(kPipelineFlags, std::move(fProcessors),
- target->detachAppliedClip());
+ target->detachAppliedClip(), kMaxTextures);
+ for (unsigned i = 0; i < numActiveProxies; ++i) {
+ pipe.fFixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i].get();
+ }
FlushInfo flushInfo;
flushInfo.fPipeline = pipe.fPipeline;
@@ -400,6 +407,9 @@
if (gp->numTextureSamplers() != (int) numActiveProxies) {
// During preparation the number of atlas pages has increased.
// Update the proxies used in the GP to match.
+ for (unsigned i = gp->numTextureSamplers(); i < numActiveProxies; ++i) {
+ flushInfo->fFixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i].get();
+ }
if (this->usesDistanceFields()) {
if (this->isLCD()) {
reinterpret_cast<GrDistanceFieldLCDTextGeoProc*>(gp)->addNewProxies(
@@ -415,7 +425,6 @@
samplerState);
}
}
-
GrMesh mesh(GrPrimitiveType::kTriangles);
int maxGlyphsPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 14f7e95..1bf8a8a 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -107,7 +107,7 @@
sk_sp<const GrBuffer> fIndexBuffer;
sk_sp<GrGeometryProcessor> fGeometryProcessor;
const GrPipeline* fPipeline;
- const GrPipeline::FixedDynamicState* fFixedDynamicState;
+ GrPipeline::FixedDynamicState* fFixedDynamicState;
int fGlyphsToFlush;
int fVertexOffset;
};
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 00dbef5..0da289a 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -32,10 +32,10 @@
GrColor fColor;
};
- static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxy,
+ static sk_sp<GrGeometryProcessor> Make(const GrTextureProxy* proxy,
sk_sp<GrColorSpaceXform> csxf,
GrSamplerState::Filter filter) {
- return sk_sp<GrGeometryProcessor>(new LatticeGP(std::move(proxy), std::move(csxf), filter));
+ return sk_sp<GrGeometryProcessor>(new LatticeGP(proxy, std::move(csxf), filter));
}
const char* name() const override { return "LatticeGP"; }
@@ -92,10 +92,10 @@
}
private:
- LatticeGP(sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> csxf,
+ LatticeGP(const GrTextureProxy* proxy, sk_sp<GrColorSpaceXform> csxf,
GrSamplerState::Filter filter)
: INHERITED(kLatticeGP_ClassID), fColorSpaceXform(std::move(csxf)) {
- fSampler.reset(std::move(proxy), filter);
+ fSampler.reset(proxy->textureType(), proxy->config(), filter);
this->setTextureSamplerCnt(1);
this->setVertexAttributeCnt(4);
}
@@ -202,7 +202,7 @@
private:
void onPrepareDraws(Target* target) override {
- auto gp = LatticeGP::Make(fProxy, fColorSpaceXform, fFilter);
+ auto gp = LatticeGP::Make(fProxy.get(), fColorSpaceXform, fFilter);
if (!gp) {
SkDebugf("Couldn't create GrGeometryProcessor\n");
return;
@@ -281,7 +281,8 @@
kVertsPerRect * patch.fIter->numRectsToDraw());
}
}
- auto pipe = fHelper.makePipeline(target);
+ auto pipe = fHelper.makePipeline(target, 1);
+ pipe.fFixedDynamicState->fPrimitiveProcessorTextures[0] = fProxy.get();
helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
}
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index 0bac5ef..5450b11 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -63,7 +63,8 @@
//////////////////////////////////////////////////////////////////////////////
GrMeshDrawOp::Target::PipelineAndFixedDynamicState GrMeshDrawOp::Target::makePipeline(
- uint32_t pipelineFlags, GrProcessorSet&& processorSet, GrAppliedClip&& clip) {
+ uint32_t pipelineFlags, GrProcessorSet&& processorSet, GrAppliedClip&& clip,
+ int numPrimProcTextures) {
GrPipeline::InitArgs pipelineArgs;
pipelineArgs.fFlags = pipelineFlags;
pipelineArgs.fProxy = this->proxy();
@@ -71,8 +72,12 @@
pipelineArgs.fCaps = &this->caps();
pipelineArgs.fResourceProvider = this->resourceProvider();
GrPipeline::FixedDynamicState* fixedDynamicState = nullptr;
- if (clip.scissorState().enabled()) {
+ if (clip.scissorState().enabled() || numPrimProcTextures) {
fixedDynamicState = this->allocFixedDynamicState(clip.scissorState().rect());
+ if (numPrimProcTextures) {
+ fixedDynamicState->fPrimitiveProcessorTextures =
+ this->allocPrimitiveProcessorTextureArray(numPrimProcTextures);
+ }
}
return {this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip)),
fixedDynamicState};
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index e90de47..3cb5ffe 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -132,10 +132,19 @@
return this->pipelineArena()->make<GrPipeline>(std::forward<Args>(args)...);
}
- template <typename... Args>
- GrPipeline::FixedDynamicState* allocFixedDynamicState(Args&... args) {
- return this->pipelineArena()->make<GrPipeline::FixedDynamicState>(
- std::forward<Args>(args)...);
+ GrPipeline::FixedDynamicState* allocFixedDynamicState(const SkIRect& rect,
+ int numPrimitiveProcessorTextures = 0) {
+ auto result = this->pipelineArena()->make<GrPipeline::FixedDynamicState>(rect);
+ if (numPrimitiveProcessorTextures) {
+ result->fPrimitiveProcessorTextures =
+ this->allocPrimitiveProcessorTextureArray(numPrimitiveProcessorTextures);
+ }
+ return result;
+ }
+
+ GrTextureProxy** allocPrimitiveProcessorTextureArray(int n) {
+ SkASSERT(n > 0);
+ return this->pipelineArena()->makeArrayDefault<GrTextureProxy*>(n);
}
// Once we have C++17 structured bindings make this just be a tuple because then we can do:
@@ -144,7 +153,7 @@
// std::tie(flushInfo.fPipeline, flushInfo.fFixedState) = target->makePipeline(...);
struct PipelineAndFixedDynamicState {
const GrPipeline* fPipeline;
- const GrPipeline::FixedDynamicState* fFixedDynamicState;
+ GrPipeline::FixedDynamicState* fFixedDynamicState;
};
/**
@@ -152,7 +161,8 @@
* GrAppliedClip and uses a fixed dynamic state.
*/
PipelineAndFixedDynamicState makePipeline(uint32_t pipelineFlags, GrProcessorSet&&,
- GrAppliedClip&&);
+ GrAppliedClip&&,
+ int numPrimitiveProcessorTextures = 0);
virtual GrRenderTargetProxy* proxy() const = 0;
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
index 7ed74c3..f1692e6 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
@@ -135,7 +135,8 @@
}
auto GrSimpleMeshDrawOpHelper::internalMakePipeline(GrMeshDrawOp::Target* target,
- const GrPipeline::InitArgs& args)
+ const GrPipeline::InitArgs& args,
+ int numPrimitiveProcessorProxies)
-> PipelineAndFixedDynamicState {
// A caller really should only call this once as the processor set and applied clip get
// moved into the GrPipeline.
@@ -143,8 +144,12 @@
SkDEBUGCODE(fMadePipeline = true);
auto clip = target->detachAppliedClip();
GrPipeline::FixedDynamicState* fixedDynamicState = nullptr;
- if (clip.scissorState().enabled()) {
+ if (clip.scissorState().enabled() || numPrimitiveProcessorProxies) {
fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect());
+ if (numPrimitiveProcessorProxies) {
+ fixedDynamicState->fPrimitiveProcessorTextures =
+ target->allocPrimitiveProcessorTextureArray(numPrimitiveProcessorProxies);
+ }
}
if (fProcessors) {
return {target->allocPipeline(args, std::move(*fProcessors), std::move(clip)),
@@ -176,11 +181,12 @@
fStencilSettings == that.fStencilSettings;
}
-auto GrSimpleMeshDrawOpHelperWithStencil::makePipeline(GrMeshDrawOp::Target* target)
+auto GrSimpleMeshDrawOpHelperWithStencil::makePipeline(GrMeshDrawOp::Target* target,
+ int numPrimitiveProcessorTextures)
-> PipelineAndFixedDynamicState {
auto args = INHERITED::pipelineInitArgs(target);
args.fUserStencil = fStencilSettings;
- return this->internalMakePipeline(target, args);
+ return this->internalMakePipeline(target, args, numPrimitiveProcessorTextures);
}
SkString GrSimpleMeshDrawOpHelperWithStencil::dumpInfo() const {
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
index 2bffa09..cd72786 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -88,8 +88,10 @@
using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState;
/** Makes a pipeline that consumes the processor set and the op's applied clip. */
- PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target* target) {
- return this->internalMakePipeline(target, this->pipelineInitArgs(target));
+ PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target* target,
+ int numPrimitiveProcessorTextures = 0) {
+ return this->internalMakePipeline(target, this->pipelineInitArgs(target),
+ numPrimitiveProcessorTextures);
}
struct MakeArgs {
@@ -116,7 +118,8 @@
GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const;
PipelineAndFixedDynamicState internalMakePipeline(GrMeshDrawOp::Target*,
- const GrPipeline::InitArgs&);
+ const GrPipeline::InitArgs&,
+ int numPrimitiveProcessorTextures);
private:
GrProcessorSet* fProcessors;
@@ -162,7 +165,8 @@
bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&,
const SkRect& thisBounds, const SkRect& thatBounds) const;
- PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target*);
+ PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target*,
+ int numPrimitiveProcessorTextures = 0);
SkString dumpInfo() const;
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 286fab7..4bbff1d 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -304,7 +304,7 @@
sk_sp<const GrBuffer> fIndexBuffer;
sk_sp<GrGeometryProcessor> fGeometryProcessor;
const GrPipeline* fPipeline;
- const GrPipeline::FixedDynamicState* fFixedDynamicState;
+ GrPipeline::FixedDynamicState* fFixedDynamicState;
int fVertexOffset;
int fInstancesToFlush;
};
@@ -312,7 +312,15 @@
void onPrepareDraws(Target* target) override {
int instanceCount = fShapes.count();
- auto pipe = fHelper.makePipeline(target);
+ static constexpr int kMaxTextures = GrDistanceFieldPathGeoProc::kMaxTextures;
+ GR_STATIC_ASSERT(GrBitmapTextGeoProc::kMaxTextures == kMaxTextures);
+
+ auto pipe = fHelper.makePipeline(target, kMaxTextures);
+ int numActiveProxies = fAtlas->numActivePages();
+ const auto proxies = fAtlas->getProxies();
+ for (int i = 0; i < numActiveProxies; ++i) {
+ pipe.fFixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i].get();
+ }
FlushInfo flushInfo;
flushInfo.fPipeline = pipe.fPipeline;
@@ -807,7 +815,12 @@
void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get();
- if (gp->numTextureSamplers() != (int)fAtlas->numActivePages()) {
+ int numAtlasTextures = SkToInt(fAtlas->numActivePages());
+ auto proxies = fAtlas->getProxies();
+ if (gp->numTextureSamplers() != numAtlasTextures) {
+ for (int i = gp->numTextureSamplers(); i < numAtlasTextures; ++i) {
+ flushInfo->fFixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i].get();
+ }
// During preparation the number of atlas pages has increased.
// Update the proxies used in the GP to match.
if (fUsesDistanceField) {
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index c69eecc..7ba41c5 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -104,23 +104,22 @@
return caps.integerSupport() && caps.maxFragmentSamplers() > 1;
}
- static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt,
+ static sk_sp<GrGeometryProcessor> Make(GrTextureType textureType, GrPixelConfig textureConfig,
+ int textureCnt,
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
sk_sp<GrColorSpaceXform> paintColorSpaceXform,
- bool coverageAA,
- bool perspective, Domain domain,
+ bool coverageAA, bool perspective, Domain domain,
const GrSamplerState::Filter filters[],
const GrShaderCaps& caps) {
// We use placement new to avoid always allocating space for kMaxTextures TextureSampler
// instances.
- int samplerCnt = NumSamplersToUse(proxyCnt, caps);
+ int samplerCnt = NumSamplersToUse(textureCnt, caps);
size_t size = sizeof(TextureGeometryProcessor) + sizeof(TextureSampler) * (samplerCnt - 1);
void* mem = GrGeometryProcessor::operator new(size);
- return sk_sp<TextureGeometryProcessor>(
- new (mem) TextureGeometryProcessor(proxies, proxyCnt, samplerCnt,
- std::move(textureColorSpaceXform),
- std::move(paintColorSpaceXform),
- coverageAA, perspective, domain, filters, caps));
+ return sk_sp<TextureGeometryProcessor>(new (mem) TextureGeometryProcessor(
+ textureType, textureConfig, textureCnt, samplerCnt,
+ std::move(textureColorSpaceXform), std::move(paintColorSpaceXform), coverageAA,
+ perspective, domain, filters, caps));
}
~TextureGeometryProcessor() override {
@@ -286,20 +285,20 @@
return SkTMin(SkNextPow2(numRealProxies), SkTMin(kMaxTextures, caps.maxFragmentSamplers()));
}
- TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt,
- sk_sp<GrColorSpaceXform> textureColorSpaceXform,
- sk_sp<GrColorSpaceXform> paintColorSpaceXform,
- bool coverageAA, bool perspective, Domain domain,
+ TextureGeometryProcessor(GrTextureType textureType, GrPixelConfig textureConfig, int textureCnt,
+ int samplerCnt, sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform, bool coverageAA,
+ bool perspective, Domain domain,
const GrSamplerState::Filter filters[], const GrShaderCaps& caps)
: INHERITED(kTextureGeometryProcessor_ClassID)
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
, fPaintColorSpaceXform(std::move(paintColorSpaceXform)) {
- SkASSERT(proxyCnt > 0 && samplerCnt >= proxyCnt);
- fSamplers[0].reset(std::move(proxies[0]), filters[0]);
- for (int i = 1; i < proxyCnt; ++i) {
+ SkASSERT(textureCnt > 0 && samplerCnt >= textureCnt);
+ fSamplers[0].reset(textureType, textureConfig, filters[0]);
+ for (int i = 1; i < textureCnt; ++i) {
// This class has one sampler built in, the rest come from memory this processor was
// placement-newed into and so haven't been constructed.
- new (&fSamplers[i]) TextureSampler(std::move(proxies[i]), filters[i]);
+ new (&fSamplers[i]) TextureSampler(textureType, textureConfig, filters[i]);
}
if (perspective) {
@@ -312,11 +311,11 @@
int vertexAttributeCnt = 3;
if (samplerCnt > 1) {
- // Here we initialize any extra samplers by repeating the last one samplerCnt - proxyCnt
- // times.
- GrTextureProxy* dupeProxy = fSamplers[proxyCnt - 1].proxy();
- for (int i = proxyCnt; i < samplerCnt; ++i) {
- new (&fSamplers[i]) TextureSampler(sk_ref_sp(dupeProxy), filters[proxyCnt - 1]);
+ // Here we initialize any extra samplers. We repeat the first filter because our caller
+ // will specify the first texture for all the extra samplers. In GL the filter is
+ // implemented as a texture parameter and the last sampler will win.
+ for (int i = textureCnt; i < samplerCnt; ++i) {
+ new (&fSamplers[i]) TextureSampler(textureType, textureConfig, filters[0]);
}
SkASSERT(caps.integerSupport());
fTextureIdx = {"textureIdx", kInt_GrVertexAttribType};
@@ -764,22 +763,20 @@
}
void onPrepareDraws(Target* target) override {
- sk_sp<GrTextureProxy> proxiesSPs[kMaxTextures];
auto proxies = this->proxies();
auto filters = this->filters();
for (int i = 0; i < fProxyCnt; ++i) {
if (!proxies[i]->instantiate(target->resourceProvider())) {
return;
}
- proxiesSPs[i] = sk_ref_sp(proxies[i]);
}
Domain domain = fDomain ? Domain::kYes : Domain::kNo;
bool coverageAA = GrAAType::kCoverage == this->aaType();
sk_sp<GrGeometryProcessor> gp = TextureGeometryProcessor::Make(
- proxiesSPs, fProxyCnt, std::move(fTextureColorSpaceXform),
- std::move(fPaintColorSpaceXform), coverageAA, fPerspective,
- domain, filters, *target->caps().shaderCaps());
+ proxies[0]->textureType(), proxies[0]->config(), fProxyCnt,
+ std::move(fTextureColorSpaceXform), std::move(fPaintColorSpaceXform), coverageAA,
+ fPerspective, domain, filters, *target->caps().shaderCaps());
GrPipeline::InitArgs args;
args.fProxy = target->proxy();
args.fCaps = &target->caps();
@@ -790,7 +787,17 @@
}
auto clip = target->detachAppliedClip();
- const auto* fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect());
+ auto* fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect(),
+ gp->numTextureSamplers());
+ for (int i = 0; i < fProxyCnt; ++i) {
+ SkASSERT(proxies[i]->textureType() == proxies[0]->textureType());
+ SkASSERT(proxies[i]->config() == proxies[0]->config());
+ fixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i];
+ }
+ // Rebind texture proxy 0 to the extra samplers.
+ for (int i = fProxyCnt; i < gp->numTextureSamplers(); ++i) {
+ fixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[0];
+ }
const auto* pipeline =
target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), std::move(clip));
using TessFn =
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 013c1d7..3cbc6ad 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -585,7 +585,11 @@
}
fLastPipelineState = pipelineState;
- pipelineState->setData(fGpu, primProc, pipeline);
+ const GrTextureProxy* const* primProcProxies = nullptr;
+ if (fixedDynamicState) {
+ primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
+ }
+ pipelineState->setData(fGpu, primProc, pipeline, primProcProxies);
pipelineState->bind(fGpu, cbInfo.currentCmdBuf());
@@ -643,8 +647,8 @@
};
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
- const GrPrimitiveProcessor::TextureSampler& sampler = primProc.textureSampler(i);
- prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter());
+ auto texture = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture();
+ prepareSampledImage(texture, primProc.textureSampler(i).samplerState().filter());
}
GrFragmentProcessor::Iter iter(pipeline);
while (const GrFragmentProcessor* fp = iter.next()) {
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 04a85a4..011db9d 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -167,7 +167,9 @@
void GrVkPipelineState::setData(GrVkGpu* gpu,
const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline) {
+ const GrPipeline& pipeline,
+ const GrTextureProxy* const primProcTextures[]) {
+ SkASSERT(primProcTextures || !primProc.numTextureSamplers());
// This is here to protect against someone calling setData multiple times in a row without
// freeing the tempData between calls.
this->freeTempResources(gpu);
@@ -181,8 +183,8 @@
GrFragmentProcessor::CoordTransformIter(pipeline));
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
const auto& sampler = primProc.textureSampler(i);
- samplerBindings[currTextureBinding++] = {sampler.samplerState(),
- static_cast<GrVkTexture*>(sampler.peekTexture())};
+ auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture());
+ samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture};
}
GrFragmentProcessor::Iter iter(pipeline);
diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h
index 1df4bb5..d61359c 100644
--- a/src/gpu/vk/GrVkPipelineState.h
+++ b/src/gpu/vk/GrVkPipelineState.h
@@ -56,7 +56,8 @@
~GrVkPipelineState();
- void setData(GrVkGpu*, const GrPrimitiveProcessor&, const GrPipeline&);
+ void setData(GrVkGpu*, const GrPrimitiveProcessor&, const GrPipeline&,
+ const GrTextureProxy* const primitiveProcessorTextures[]);
void bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer);