Reland "Move GrGeometryProcessor's textures out of classes and into"
This reverts commit fdf05f4ff4e96e28a31e210cb471d149d736f528.
Reason for revert: Android fixed after removing multitexture support from TextureOp.
Original change's description:
> Revert "Move GrGeometryProcessor's textures out of classes and into"
>
> This reverts commit af87483873f0b370b90ebe956301a13cc8662cbe.
>
> Revert "GrGeometryProcessor derives from GrNonAtomicRef not GrProgramElement."
>
> This reverts commit 607be37e3d4ddbe2163c200d6e13bcee981f6bf7.
>
> Revert "Store GrMeshDrawOps' meshes in GrOpFlushState's arena."
>
> This reverts commit b948572c7862214fe2e1fa6cdfcab4fc7b1666ac.
>
> Revert "Remove multitexturing support from GrTextureOp."
>
> This reverts commit 986f64c601f3ed99f84f0c392d1a42e298f6d618.
>
> Revert "Make result of GrOp::combineIfPossible be an enum."
>
> This reverts commit 641ac7daa81cbfca06b310803fb1a607d0fc2b32.
>
> Bug: b/112244393
> Change-Id: I579491a3f2f2f2093f1e2a6141fa1e4cc7b760a4
> Reviewed-on: https://skia-review.googlesource.com/145646
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
TBR=bsalomon@google.com
Change-Id: I1d41c2ecf7862e31fb025a7a00bb07bae9d83a47
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: b/112244393
Reviewed-on: https://skia-review.googlesource.com/145780
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/atlastext/SkAtlasTextTarget.cpp b/src/atlastext/SkAtlasTextTarget.cpp
index 8a382c7..3d9cf95 100644
--- a/src/atlastext/SkAtlasTextTarget.cpp
+++ b/src/atlastext/SkAtlasTextTarget.cpp
@@ -181,7 +181,7 @@
int n = SkTMin(kMaxBatchLookBack, fOps.count());
for (int i = 0; i < n; ++i) {
GrAtlasTextOp* other = fOps.fromBack(i).get();
- if (other->combineIfPossible(op.get(), caps)) {
+ if (other->combineIfPossible(op.get(), caps) == GrOp::CombineResult::kMerged) {
fOpMemoryPool->release(std::move(op));
return;
}
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp
index 42e00f3..d66f24c 100644
--- a/src/gpu/GrGpuCommandBuffer.cpp
+++ b/src/gpu/GrGpuCommandBuffer.cpp
@@ -44,9 +44,14 @@
auto resourceProvider = this->gpu()->getContext()->contextPriv().resourceProvider();
- if (pipeline.isBad() || !primProc.instantiate(resourceProvider)) {
+ if (pipeline.isBad()) {
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/GrMesh.h b/src/gpu/GrMesh.h
index fb7b525..e8a3f5c 100644
--- a/src/gpu/GrMesh.h
+++ b/src/gpu/GrMesh.h
@@ -21,12 +21,12 @@
*/
class GrMesh {
public:
- GrMesh(GrPrimitiveType primitiveType)
- : fPrimitiveType(primitiveType)
- , fBaseVertex(0) {
+ GrMesh(GrPrimitiveType primitiveType = GrPrimitiveType::kTriangles)
+ : fPrimitiveType(primitiveType), fBaseVertex(0) {
SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
}
+ void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index 8d8b7bb..6385c9f 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -45,8 +45,7 @@
SkASSERT(fCurrDraw->fPipeline->proxy() == this->drawOpArgs().fProxy);
this->rtCommandBuffer()->draw(*fCurrDraw->fGeometryProcessor, *fCurrDraw->fPipeline,
fCurrDraw->fFixedDynamicState, fCurrDraw->fDynamicStateArrays,
- fMeshes.begin() + fCurrMesh, fCurrDraw->fMeshCnt, opBounds);
- fCurrMesh += fCurrDraw->fMeshCnt;
+ fCurrDraw->fMeshes, fCurrDraw->fMeshCnt, opBounds);
fTokenTracker->flushToken();
++fCurrDraw;
}
@@ -61,7 +60,6 @@
// Setup execution iterators.
fCurrDraw = fDraws.begin();
fCurrUpload = fInlineUploads.begin();
- fCurrMesh = 0;
}
void GrOpFlushState::reset() {
@@ -73,8 +71,6 @@
fASAPUploads.reset();
fInlineUploads.reset();
fDraws.reset();
- fMeshes.reset();
- fCurrMesh = 0;
fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
}
@@ -104,36 +100,23 @@
return fTokenTracker->nextTokenToFlush();
}
-void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline,
+void GrOpFlushState::draw(sk_sp<const GrGeometryProcessor> gp, const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState,
- const GrMesh& mesh) {
+ const GrMesh meshes[], int meshCnt) {
SkASSERT(fOpArgs);
SkASSERT(fOpArgs->fOp);
- fMeshes.push_back(mesh);
bool firstDraw = fDraws.begin() == fDraws.end();
- if (!firstDraw) {
- Draw& lastDraw = *fDraws.begin();
- // If the last draw shares a geometry processor and pipeline and there are no intervening
- // uploads, add this mesh to it.
- // Note, we could attempt to convert fixed dynamic states into dynamic state arrays here
- // if everything else is equal. Maybe it's better to rely on Ops to do that?
- if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline &&
- lastDraw.fFixedDynamicState == fixedDynamicState) {
- if (fInlineUploads.begin() == fInlineUploads.end() ||
- fInlineUploads.tail()->fUploadBeforeToken != fTokenTracker->nextDrawToken()) {
- ++lastDraw.fMeshCnt;
- return;
- }
- }
- }
auto& draw = fDraws.append(&fArena);
GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
-
- draw.fGeometryProcessor.reset(gp);
+ for (int i = 0; i < gp->numTextureSamplers(); ++i) {
+ fixedDynamicState->fPrimitiveProcessorTextures[i]->addPendingRead();
+ }
+ draw.fGeometryProcessor = std::move(gp);
draw.fPipeline = pipeline;
draw.fFixedDynamicState = fixedDynamicState;
draw.fDynamicStateArrays = nullptr;
- draw.fMeshCnt = 1;
+ draw.fMeshes = meshes;
+ draw.fMeshCnt = meshCnt;
draw.fOpID = fOpArgs->fOp->uniqueID();
if (firstDraw) {
fBaseDrawToken = token;
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 66ac34c..0a46ed2 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -73,9 +73,11 @@
GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&&) final;
/** Overrides of GrMeshDrawOp::Target. */
-
- void draw(const GrGeometryProcessor*, const GrPipeline*, const GrPipeline::FixedDynamicState*,
- const GrMesh&) final;
+ void draw(sk_sp<const GrGeometryProcessor>,
+ const GrPipeline*,
+ const GrPipeline::FixedDynamicState*,
+ const GrMesh[],
+ int meshCount) final;
void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**,
int* startVertex) final;
uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) final;
@@ -118,12 +120,18 @@
// 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 {
- int fMeshCnt = 0;
- GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
- const GrPipeline* fPipeline;
+ ~Draw() {
+ for (int i = 0; i < fGeometryProcessor->numTextureSamplers(); ++i) {
+ fFixedDynamicState->fPrimitiveProcessorTextures[i]->completedRead();
+ }
+ }
+ sk_sp<const GrGeometryProcessor> fGeometryProcessor;
+ const GrPipeline* fPipeline = nullptr;
const GrPipeline::FixedDynamicState* fFixedDynamicState;
const GrPipeline::DynamicStateArrays* fDynamicStateArrays;
- uint32_t fOpID;
+ const GrMesh* fMeshes = nullptr;
+ int fMeshCnt = 0;
+ uint32_t fOpID = SK_InvalidUniqueID;
};
// Storage for ops' pipelines, draws, and inline uploads.
@@ -137,9 +145,6 @@
SkArenaAllocList<GrDeferredTextureUploadFn> fASAPUploads;
SkArenaAllocList<InlineUpload> fInlineUploads;
SkArenaAllocList<Draw> fDraws;
- // TODO: These should go in the arena. However, GrGpuCommandBuffer and other classes currently
- // accept contiguous arrays of meshes.
- SkSTArray<16, GrMesh> fMeshes;
// All draws we store have an implicit draw token. This is the draw token for the first draw
// in fDraws.
@@ -156,7 +161,6 @@
// Variables that are used to track where we are in lists as ops are executed
SkArenaAllocList<Draw>::Iter fCurrDraw;
- int fCurrMesh;
SkArenaAllocList<InlineUpload>::Iter fCurrUpload;
// Used to track the proxies that need to be uninstantiated after we finish a flush
diff --git a/src/gpu/GrPendingProgramElement.h b/src/gpu/GrPendingProgramElement.h
deleted file mode 100644
index ab1f437..0000000
--- a/src/gpu/GrPendingProgramElement.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrPendingProgramElement_DEFINED
-#define GrPendingProgramElement_DEFINED
-
-#include "SkRefCnt.h"
-#include "GrTypes.h"
-
-/**
- * Helper for owning a pending execution on a GrProgramElement. Using this rather than ref allows
- * resources that are owned by the program element to be correctly tracked as having pending reads
- * and writes rather than refs.
- */
-template <typename T> class GrPendingProgramElement : SkNoncopyable {
-public:
- GrPendingProgramElement() : fObj(nullptr) { }
-
- // Adds a pending execution on obj.
- explicit GrPendingProgramElement(T* obj) : fObj(obj) {
- if (obj) {
- obj->addPendingExecution();
- }
- }
-
- void reset(T* obj) {
- if (obj) {
- obj->addPendingExecution();
- }
- if (fObj) {
- fObj->completedExecution();
- }
- fObj = obj;
- }
-
- T* get() const { return fObj; }
- operator T*() { return fObj; }
-
- T *operator->() const { return fObj; }
-
- ~GrPendingProgramElement() {
- if (fObj) {
- fObj->completedExecution();
- }
- }
-
-private:
- T* fObj;
-
- typedef SkNoncopyable INHERITED;
-};
-#endif
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 24dd9f8..b2f6711 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -12,7 +12,6 @@
#include "GrFragmentProcessor.h"
#include "GrNonAtomicRef.h"
#include "GrPendingIOResource.h"
-#include "GrPendingProgramElement.h"
#include "GrProcessorSet.h"
#include "GrProgramDesc.h"
#include "GrRect.h"
@@ -76,8 +75,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..4becb54 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -9,6 +9,7 @@
#define GrPrimitiveProcessor_DEFINED
#include "GrColor.h"
+#include "GrNonAtomicRef.h"
#include "GrProcessor.h"
#include "GrProxyRef.h"
#include "GrShaderVar.h"
@@ -36,12 +37,15 @@
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: This class does not really need to be ref counted. Instances should be allocated using
+ * GrOpFlushState's arena and destroyed when the arena is torn down.
*/
-class GrPrimitiveProcessor : public GrProcessor, public GrProgramElement {
+class GrPrimitiveProcessor : public GrProcessor, public GrNonAtomicRef<GrPrimitiveProcessor> {
public:
class TextureSampler;
@@ -136,8 +140,6 @@
virtual float getSampleShading() const { return 0.0; }
- bool instantiate(GrResourceProvider*) const;
-
protected:
void setVertexAttributeCnt(int cnt) {
SkASSERT(cnt >= 0);
@@ -164,11 +166,6 @@
inline static const TextureSampler& IthTextureSampler(int i);
private:
- void addPendingIOs() const final;
- void removeRefs() const final;
- void pendingIOComplete() const final;
- void notifyRefCntIsZero() const final {}
-
virtual const Attribute& onVertexAttribute(int) const = 0;
virtual const Attribute& onInstanceAttribute(int) const = 0;
virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
@@ -190,9 +187,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 +197,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/GrProcessor.h b/src/gpu/GrProcessor.h
index 4afb246..3c6662c 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -12,7 +12,6 @@
#include "GrBuffer.h"
#include "GrColor.h"
#include "GrProcessorUnitTest.h"
-#include "GrProgramElement.h"
#include "GrSamplerState.h"
#include "GrShaderVar.h"
#include "GrSurfaceProxyPriv.h"
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/GrProgramElement.h b/src/gpu/GrProgramElement.h
deleted file mode 100644
index ef96738..0000000
--- a/src/gpu/GrProgramElement.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrProgramElement_DEFINED
-#define GrProgramElement_DEFINED
-
-#include "../private/SkTArray.h"
-#include "SkRefCnt.h"
-
-/**
- * Note: We are converting GrProcessor from ref counting to a single owner model using move
- * semantics. This class will be removed.
- *
- * This is used to track "refs" for two separate types GrProcessor ownership. A regular ref is owned
- * by any client that may continue to issue draws that use the GrProgramElement. A recorded op or
- * GrPipeline uses "pending executions" instead of refs. A pending execution is cleared after the
- * draw is executed (or aborted).
- *
- * While a GrProgramElement is ref'ed any resources it owns are also ref'ed. However, once it gets
- * into the state where it has pending executions AND no refs then it converts its ownership of
- * its GrGpuResources from refs to pending IOs. The pending IOs allow the cache to track when it is
- * safe to recycle a resource even though we still have buffered GrOps that read or write to the
- * the resource.
- *
- * To make this work the subclass GrProcessor implements addPendingIOs, removeRefs, and
- * pendingIOComplete. addPendingIOs adds pending reads/writes to GrGpuResources owned by the
- * processor as appropriate when the processor is recorded in a GrOpList. removeRefs is called when
- * the ref count reaches 0 and the GrProcessor is only owned by "pending executions".
- * pendingIOComplete occurs if the resource is still owned by a ref but all recorded draws have been
- * completed. Whenever pending executions and refs reach zero the processor is deleted.
- *
- * The GrProcessor may also implement notifyRefCntIsZero in order to change its ownership of child
- * processors from ref to pending execution when the processor is first owned exclusively in pending
- * execution mode.
- */
-class GrProgramElement : public SkNoncopyable {
-public:
- virtual ~GrProgramElement() {
- // fRefCnt can be one when an effect is created statically using GR_CREATE_STATIC_EFFECT
- SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions);
- // Set to invalid values.
- SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;)
- }
-
- void ref() const {
- this->validate();
- // Once the ref cnt reaches zero it should never be ref'ed again.
- SkASSERT(fRefCnt > 0);
- ++fRefCnt;
- this->validate();
- }
-
- void unref() const {
- this->validate();
- --fRefCnt;
- if (0 == fRefCnt) {
- this->notifyRefCntIsZero();
- if (0 == fPendingExecutions) {
- delete this;
- return;
- } else {
- this->removeRefs();
- }
- }
- this->validate();
- }
-
- void validate() const {
-#ifdef SK_DEBUG
- SkASSERT(fRefCnt >= 0);
- SkASSERT(fPendingExecutions >= 0);
- SkASSERT(fRefCnt + fPendingExecutions > 0);
-#endif
- }
-
-protected:
- GrProgramElement() : fRefCnt(1), fPendingExecutions(0) {}
-
- void addPendingExecution() const {
- this->validate();
- if (0 == fPendingExecutions) {
- this->addPendingIOs();
- }
- ++fPendingExecutions;
- this->validate();
- }
-
- void completedExecution() const {
- this->validate();
- --fPendingExecutions;
- if (0 == fPendingExecutions) {
- if (0 == fRefCnt) {
- delete this;
- return;
- } else {
- this->pendingIOComplete();
- }
- }
- this->validate();
- }
-
-private:
- virtual void addPendingIOs() const = 0;
- virtual void removeRefs() const = 0;
- virtual void pendingIOComplete() const = 0;
-
- /** This will be called when the ref cnt is zero. The object may or may not have pending
- executions. */
- virtual void notifyRefCntIsZero() const = 0;
-
- mutable int32_t fRefCnt;
- // Count of deferred executions not yet issued to the 3D API.
- mutable int32_t fPendingExecutions;
-
- // Only these classes can access addPendingExecution() and completedExecution().
- template <typename T> friend class GrPendingProgramElement;
- friend class GrProcessorSet;
-
- typedef SkNoncopyable INHERITED;
-};
-
-#endif
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 569b5fa..33836a7 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -339,7 +339,7 @@
} else if (a.fDstProxy.proxy()) {
return false;
}
- return a.fOp->combineIfPossible(b, caps);
+ return a.fOp->combineIfPossible(b, caps) == GrOp::CombineResult::kMerged;
}
uint32_t GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index 9ab5f90..d29fe58 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -64,10 +64,6 @@
fMaxFragmentSamplers = 0;
fMaxCombinedSamplers = 0;
fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
-
- // TODO: Default this to 0 and only enable image multitexturing when a "safe" threshold is
- // known for a GPU class.
- fDisableImageMultitexturingDstRectAreaThreshold = std::numeric_limits<size_t>::max();
}
void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
@@ -123,8 +119,6 @@
writer->appendS32("Max Combined Samplers", fMaxFragmentSamplers);
writer->appendString("Advanced blend equation interaction",
kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]);
- writer->appendU64("Disable image multitexturing dst area threshold",
- fDisableImageMultitexturingDstRectAreaThreshold);
writer->endObject();
}
@@ -145,8 +139,5 @@
}
#if GR_TEST_UTILS
fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;
- if (options.fDisableImageMultitexturing) {
- fDisableImageMultitexturingDstRectAreaThreshold = 0;
- }
#endif
}
diff --git a/src/gpu/GrShaderCaps.h b/src/gpu/GrShaderCaps.h
index a599f1d..d8422c7 100644
--- a/src/gpu/GrShaderCaps.h
+++ b/src/gpu/GrShaderCaps.h
@@ -205,15 +205,6 @@
int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
/**
- * In general using multiple texture units for image rendering seems to be a win at smaller
- * sizes of dst rects and a loss at larger sizes. Dst rects above this pixel area threshold will
- * not use multitexturing.
- */
- size_t disableImageMultitexturingDstRectAreaThreshold() const {
- return fDisableImageMultitexturingDstRectAreaThreshold;
- }
-
- /**
* Given a texture's config, this determines what swizzle must be appended to accesses to the
* texture in generated shader code. Swizzling may be implemented in texture parameters or a
* sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 016756a..aed0672 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -117,7 +117,7 @@
return RequiresDstTexture(analysis.requiresDstTexture());
}
-bool GrCCDrawPathsOp::onCombineIfPossible(GrOp* op, const GrCaps&) {
+GrOp::CombineResult GrCCDrawPathsOp::onCombineIfPossible(GrOp* op, const GrCaps&) {
GrCCDrawPathsOp* that = op->cast<GrCCDrawPathsOp>();
SkASSERT(fOwningPerOpListPaths);
SkASSERT(fNumDraws);
@@ -126,7 +126,7 @@
if (fProcessors != that->fProcessors ||
fViewMatrixIfUsingLocalCoords != that->fViewMatrixIfUsingLocalCoords) {
- return false;
+ return CombineResult::kCannotCombine;
}
fDraws.append(std::move(that->fDraws), &fOwningPerOpListPaths->fAllocator);
@@ -134,7 +134,7 @@
SkDEBUGCODE(fNumDraws += that->fNumDraws);
SkDEBUGCODE(that->fNumDraws = 0);
- return true;
+ return CombineResult::kMerged;
}
void GrCCDrawPathsOp::wasRecorded(GrCCPerOpListPaths* owningPerOpListPaths) {
@@ -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..40d9df4 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -37,7 +37,7 @@
const char* name() const override { return "GrCCDrawPathsOp"; }
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override;
- bool onCombineIfPossible(GrOp*, const GrCaps&) override;
+ CombineResult onCombineIfPossible(GrOp*, const GrCaps&) override;
void visitProxies(const VisitProxyFunc& fn) const override { fProcessors.visitProxies(fn); }
void onPrepare(GrOpFlushState*) override {}
@@ -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..2b246c9 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -27,9 +27,9 @@
RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
return RequiresDstTexture::kNo;
}
- bool onCombineIfPossible(GrOp* other, const GrCaps&) override {
+ CombineResult onCombineIfPossible(GrOp* other, const GrCaps&) override {
SK_ABORT("Only expected one Op per CCPR atlas.");
- return true;
+ return CombineResult::kMerged;
}
void onPrepare(GrOpFlushState*) override {}
@@ -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 b9e5681..099cc7e 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/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index c0549e9..f496044 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -364,30 +364,6 @@
GR_GL_GetIntegerv(gli, GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxSamplers);
shaderCaps->fMaxCombinedSamplers = SkTMin<GrGLint>(kMaxSaneSamplers, maxSamplers);
- // This is all *very* approximate.
- switch (ctxInfo.vendor()) {
- case kNVIDIA_GrGLVendor:
- // We've seen a range from 100 x 100 (TegraK1, GTX660) up to 300 x 300 (GTX 1070)
- // but it doesn't clearly align with Pascal vs Maxwell vs Kepler.
- fShaderCaps->fDisableImageMultitexturingDstRectAreaThreshold = 150 * 150;
- break;
- case kImagination_GrGLVendor:
- // Two PowerVR Rogues, Nexus Player and Chromebook Cb5-312T (PowerVR GX6250), show that
- // it is always a win to use multitexturing.
- if (kPowerVRRogue_GrGLRenderer == ctxInfo.renderer()) {
- fShaderCaps->fDisableImageMultitexturingDstRectAreaThreshold =
- std::numeric_limits<size_t>::max();
- }
- break;
- case kATI_GrGLVendor:
- // So far no AMD GPU shows a performance difference. A tie goes to disabling
- // multitexturing for simplicity's sake.
- fShaderCaps->fDisableImageMultitexturingDstRectAreaThreshold = 0;
- break;
- default:
- break;
- }
-
// SGX and Mali GPUs that are based on a tiled-deferred architecture that have trouble with
// frequently changing VBOs. We've measured a performance increase using non-VBO vertex
// data for dynamic content on these GPUs. Perhaps we should read the renderer string and
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/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index b60088d..ba290ac 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -33,11 +33,7 @@
const GrPipeline& pipeline,
GrProgramDesc* desc,
GrGLGpu* gpu) {
-#ifdef SK_DEBUG
- GrResourceProvider* resourceProvider = gpu->getContext()->contextPriv().resourceProvider();
-
- SkASSERT(!pipeline.isBad() && primProc.instantiate(resourceProvider));
-#endif
+ SkASSERT(!pipeline.isBad());
ATRACE_ANDROID_FRAMEWORK("Shader Compile");
GrAutoLocaleSetter als("C");
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/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 783cac7..e9a612f 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -843,11 +843,11 @@
extract_lines_only_verts(tess, verts, vertexStride, args.fColor, idxs,
fHelper.compatibleWithAlphaAsCoverage());
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexed(indexBuffer, tess.numIndices(), firstIndex, 0, tess.numPts() - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(indexBuffer, tess.numIndices(), firstIndex, 0, tess.numPts() - 1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(vertexBuffer, firstVertex);
+ target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
}
@@ -928,37 +928,38 @@
SkSTArray<kPreallocDrawCnt, Draw, true> draws;
create_vertices(segments, fanPt, args.fColor, &draws, verts, idxs);
- GrMesh mesh(GrPrimitiveType::kTriangles);
-
+ GrMesh* meshes = target->allocMeshes(draws.count());
for (int j = 0; j < draws.count(); ++j) {
const Draw& draw = draws[j];
- mesh.setIndexed(indexBuffer, draw.fIndexCnt, firstIndex, 0, draw.fVertexCnt - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(quadProcessor.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ meshes[j].setPrimitiveType(GrPrimitiveType::kTriangles);
+ meshes[j].setIndexed(indexBuffer, draw.fIndexCnt, firstIndex, 0,
+ draw.fVertexCnt - 1, GrPrimitiveRestart::kNo);
+ meshes[j].setVertexData(vertexBuffer, firstVertex);
firstIndex += draw.fIndexCnt;
firstVertex += draw.fVertexCnt;
}
+ target->draw(quadProcessor, pipe.fPipeline, pipe.fFixedDynamicState, meshes,
+ draws.count());
}
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
AAConvexPathOp* that = t->cast<AAConvexPathOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() &&
!fPaths[0].fViewMatrix.cheapEqualTo(that->fPaths[0].fViewMatrix)) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fLinesOnly != that->fLinesOnly) {
- return false;
+ return CombineResult::kCannotCombine;
}
fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct PathData {
diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp
index 592c0b2..9d66299 100644
--- a/src/gpu/ops/GrAAFillRectOp.cpp
+++ b/src/gpu/ops/GrAAFillRectOp.cpp
@@ -265,10 +265,9 @@
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
sk_sp<const GrBuffer> indexBuffer = get_index_buffer(target->resourceProvider());
- PatternHelper helper(GrPrimitiveType::kTriangles);
- void* vertices =
- helper.init(target, vertexStride, indexBuffer.get(), kVertsPerAAFillRect,
- kIndicesPerAAFillRect, fRectCnt);
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
+ kVertsPerAAFillRect, kIndicesPerAAFillRect, fRectCnt);
+ void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -292,19 +291,19 @@
info = this->next(info);
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
AAFillRectOp* that = t->cast<AAFillRectOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRectData.push_back_n(that->fRectData.count(), that->fRectData.begin());
fRectCnt += that->fRectCnt;
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct RectInfo {
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 05f1fbd..7cff875 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -835,41 +835,41 @@
typedef SkTArray<int, true> IntArray;
typedef SkTArray<float, true> FloatArray;
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
AAHairlineOp* that = t->cast<AAHairlineOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->viewMatrix().hasPerspective() != that->viewMatrix().hasPerspective()) {
- return false;
+ return CombineResult::kCannotCombine;
}
// We go to identity if we don't have perspective
if (this->viewMatrix().hasPerspective() &&
!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
// TODO we can actually combine hairlines if they are the same color in a kind of bulk
// method but we haven't implemented this yet
// TODO investigate going to vertex color and coverage?
if (this->coverage() != that->coverage()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->color() != that->color()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
GrColor color() const { return fColor; }
@@ -975,11 +975,11 @@
add_line(&lines[2*i], toSrc, this->coverage(), &verts);
}
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg, kLineSegNumVertices,
- lineCount, kLineSegsNumInIdxBuffer);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(lineGP.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg, kLineSegNumVertices,
+ lineCount, kLineSegsNumInIdxBuffer);
+ mesh->setVertexData(vertexBuffer, firstVertex);
+ target->draw(std::move(lineGP), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
if (quadCount || conicCount) {
@@ -1030,20 +1030,20 @@
}
if (quadCount > 0) {
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
- quadCount, kQuadsNumInIdxBuffer);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(quadGP.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
+ quadCount, kQuadsNumInIdxBuffer);
+ mesh->setVertexData(vertexBuffer, firstVertex);
+ target->draw(std::move(quadGP), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
firstVertex += quadCount * kQuadNumVertices;
}
if (conicCount > 0) {
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
- conicCount, kQuadsNumInIdxBuffer);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(conicGP.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
+ conicCount, kQuadsNumInIdxBuffer);
+ mesh->setVertexData(vertexBuffer, firstVertex);
+ target->draw(std::move(conicGP), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
}
}
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index 75662d3..c40aa71 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -210,14 +210,13 @@
}
private:
- void draw(Target* target, const GrGeometryProcessor* gp, const GrPipeline* pipeline,
+ void draw(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState, int vertexCount,
size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const {
if (vertexCount == 0 || indexCount == 0) {
return;
}
const GrBuffer* vertexBuffer;
- GrMesh mesh(GrPrimitiveType::kTriangles);
int firstVertex;
void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
&firstVertex);
@@ -235,10 +234,11 @@
return;
}
memcpy(idxs, indices, indexCount * sizeof(uint16_t));
- mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(gp, pipeline, fixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(vertexBuffer, firstVertex);
+ target->draw(std::move(gp), pipeline, fixedDynamicState, mesh);
}
void onPrepareDraws(Target* target) override {
@@ -279,7 +279,7 @@
if (vertexCount + currentVertices > static_cast<int>(UINT16_MAX)) {
// if we added the current instance, we would overflow the indices we can store in a
// uint16_t. Draw what we've got so far and reset.
- this->draw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, vertexCount,
+ this->draw(target, gp, pipe.fPipeline, pipe.fFixedDynamicState, vertexCount,
vertexStride, vertices, indexCount, indices);
vertexCount = 0;
indexCount = 0;
@@ -311,22 +311,22 @@
indexCount += currentIndices;
}
if (vertexCount <= SK_MaxS32 && indexCount <= SK_MaxS32) {
- this->draw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, vertexCount,
+ this->draw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, vertexCount,
vertexStride, vertices, indexCount, indices);
}
sk_free(vertices);
sk_free(indices);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; }
diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp
index 92d1c01..0362946 100644
--- a/src/gpu/ops/GrAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrAAStrokeRectOp.cpp
@@ -227,7 +227,7 @@
const SkMatrix& viewMatrix() const { return fViewMatrix; }
bool miterStroke() const { return fMiterStroke; }
- bool onCombineIfPossible(GrOp* t, const GrCaps&) override;
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps&) override;
void generateAAStrokeRectGeometry(void* vertices,
size_t offset,
@@ -282,11 +282,11 @@
int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt;
int instanceCount = fRects.count();
- sk_sp<const GrBuffer> indexBuffer = GetIndexBuffer(target->resourceProvider(), this->miterStroke());
- PatternHelper helper(GrPrimitiveType::kTriangles);
- void* vertices =
- helper.init(target, vertexStride, indexBuffer.get(),
- verticesPerInstance, indicesPerInstance, instanceCount);
+ sk_sp<const GrBuffer> indexBuffer =
+ GetIndexBuffer(target->resourceProvider(), this->miterStroke());
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
+ verticesPerInstance, indicesPerInstance, instanceCount);
+ void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -308,7 +308,7 @@
fHelper.compatibleWithAlphaAsCoverage());
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
sk_sp<const GrBuffer> AAStrokeRectOp::GetIndexBuffer(GrResourceProvider* resourceProvider,
@@ -405,27 +405,27 @@
}
}
-bool AAStrokeRectOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
+GrOp::CombineResult AAStrokeRectOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
AAStrokeRectOp* that = t->cast<AAStrokeRectOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
// TODO combine across miterstroke changes
if (this->miterStroke() != that->miterStroke()) {
- return false;
+ return CombineResult::kCannotCombine;
}
// We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
// local coords then we won't be able to combine. TODO: Upload local coords as an attribute.
if (fHelper.usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRects.push_back_n(that->fRects.count(), that->fRects.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
static void setup_scale(int* scale, SkScalar inset) {
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index cfd0c45..ba39b97 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,62 +425,60 @@
samplerState);
}
}
-
- GrMesh mesh(GrPrimitiveType::kTriangles);
int maxGlyphsPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
- mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph,
- flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
- mesh.setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
- target->draw(flushInfo->fGeometryProcessor.get(), flushInfo->fPipeline,
- flushInfo->fFixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph,
+ flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
+ mesh->setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
+ target->draw(flushInfo->fGeometryProcessor, flushInfo->fPipeline, flushInfo->fFixedDynamicState,
+ mesh);
flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;
flushInfo->fGlyphsToFlush = 0;
}
-bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
+GrOp::CombineResult GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
GrAtlasTextOp* that = t->cast<GrAtlasTextOp>();
if (fProcessors != that->fProcessors) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!fCanCombineOnTouchOrOverlap && GrRectsTouchOrOverlap(this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fMaskType != that->fMaskType) {
- return false;
+ return CombineResult::kCannotCombine;
}
const SkMatrix& thisFirstMatrix = fGeoData[0].fViewMatrix;
const SkMatrix& thatFirstMatrix = that->fGeoData[0].fViewMatrix;
if (this->usesLocalCoords() && !thisFirstMatrix.cheapEqualTo(thatFirstMatrix)) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fNeedsGlyphTransform != that->fNeedsGlyphTransform) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fNeedsGlyphTransform &&
(thisFirstMatrix.hasPerspective() != thatFirstMatrix.hasPerspective())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->usesDistanceFields()) {
if (fDFGPFlags != that->fDFGPFlags) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fLuminanceColor != that->fLuminanceColor) {
- return false;
+ return CombineResult::kCannotCombine;
}
} else {
if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
- return false;
+ return CombineResult::kCannotCombine;
}
-
}
// Keep the batch vertex buffer size below 32K so we don't have to create a special one
@@ -478,7 +486,7 @@
static const int kVertexSize = sizeof(SkPoint) + sizeof(SkColor) + 2 * sizeof(uint16_t);
static const int kMaxGlyphs = 32768 / (kVerticesPerGlyph * kVertexSize);
if (this->fNumGlyphs + that->fNumGlyphs > kMaxGlyphs) {
- return false;
+ return CombineResult::kCannotCombine;
}
fNumGlyphs += that->numGlyphs();
@@ -508,7 +516,7 @@
fGeoCount = newGeoCount;
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
// TODO trying to figure out why lcd is so whack
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 14f7e95..e6e08dc 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;
};
@@ -149,7 +149,7 @@
bool usesLocalCoords() const { return fUsesLocalCoords; }
int numGlyphs() const { return fNumGlyphs; }
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override;
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override;
sk_sp<GrGeometryProcessor> setupDfProcessor(const sk_sp<GrTextureProxy>* proxies,
unsigned int numActiveProxies) const;
diff --git a/src/gpu/ops/GrClearOp.h b/src/gpu/ops/GrClearOp.h
index 6e76191..e62667d 100644
--- a/src/gpu/ops/GrClearOp.h
+++ b/src/gpu/ops/GrClearOp.h
@@ -62,23 +62,23 @@
this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsZeroArea::kNo);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
// This could be much more complicated. Currently we look at cases where the new clear
// contains the old clear, or when the new clear is a subset of the old clear and is the
// same color.
GrClearOp* cb = t->cast<GrClearOp>();
if (fClip.windowRectsState() != cb->fClip.windowRectsState()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (cb->contains(this)) {
fClip = cb->fClip;
this->replaceBounds(*t);
fColor = cb->fColor;
- return true;
+ return CombineResult::kMerged;
} else if (cb->fColor == fColor && this->contains(cb)) {
- return true;
+ return CombineResult::kMerged;
}
- return false;
+ return CombineResult::kCannotCombine;
}
bool contains(const GrClearOp* that) const {
diff --git a/src/gpu/ops/GrClearStencilClipOp.h b/src/gpu/ops/GrClearStencilClipOp.h
index 3e7ad50..5861fca 100644
--- a/src/gpu/ops/GrClearStencilClipOp.h
+++ b/src/gpu/ops/GrClearStencilClipOp.h
@@ -52,8 +52,6 @@
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { return false; }
-
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState* state) override;
diff --git a/src/gpu/ops/GrCopySurfaceOp.h b/src/gpu/ops/GrCopySurfaceOp.h
index bc0e33f..b93cbb7 100644
--- a/src/gpu/ops/GrCopySurfaceOp.h
+++ b/src/gpu/ops/GrCopySurfaceOp.h
@@ -53,8 +53,6 @@
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
}
- bool onCombineIfPossible(GrOp* that, const GrCaps& caps) override { return false; }
-
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState* state) override;
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 43acc5c..075df70 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -625,7 +625,6 @@
return;
}
- QuadHelper helper;
size_t vertexStride;
if (fullDash) {
vertexStride =
@@ -634,7 +633,8 @@
vertexStride = sizeof(SkPoint);
}
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
- void* vertices = helper.init(target, vertexStride, totalRectCount);
+ QuadHelper helper(target, vertexStride, totalRectCount);
+ void* vertices = helper.vertices();
if (!vertices) {
return;
}
@@ -696,43 +696,43 @@
}
auto pipe = target->makePipeline(pipelineFlags, std::move(fProcessorSet),
target->detachAppliedClip());
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
DashOp* that = t->cast<DashOp>();
if (fProcessorSet != that->fProcessorSet) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fDisallowCombineOnTouchOrOverlap &&
GrRectsTouchOrOverlap(this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->aaMode() != that->aaMode()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->fullDash() != that->fullDash()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->cap() != that->cap()) {
- return false;
+ return CombineResult::kCannotCombine;
}
// TODO vertex color
if (this->color() != that->color()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fUsesLocalCoords && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fLines.push_back_n(that->fLines.count(), that->fLines.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
GrColor color() const { return fColor; }
diff --git a/src/gpu/ops/GrDebugMarkerOp.h b/src/gpu/ops/GrDebugMarkerOp.h
index 061f676..96c5477 100644
--- a/src/gpu/ops/GrDebugMarkerOp.h
+++ b/src/gpu/ops/GrDebugMarkerOp.h
@@ -39,8 +39,6 @@
this->makeFullScreen(proxy);
}
- bool onCombineIfPossible(GrOp* that, const GrCaps& caps) override { return false; }
-
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState* state) override;
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 07e40f0..4e038df 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -65,12 +65,12 @@
class PathGeoBuilder {
public:
PathGeoBuilder(GrPrimitiveType primitiveType, GrMeshDrawOp::Target* target,
- GrGeometryProcessor* geometryProcessor, const GrPipeline* pipeline,
+ sk_sp<const GrGeometryProcessor> geometryProcessor, const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState)
- : fMesh(primitiveType)
+ : fPrimitiveType(primitiveType)
, fTarget(target)
, fVertexStride(sizeof(SkPoint))
- , fGeometryProcessor(geometryProcessor)
+ , fGeometryProcessor(std::move(geometryProcessor))
, fPipeline(pipeline)
, fFixedDynamicState(fixedDynamicState)
, fIndexBuffer(nullptr)
@@ -200,15 +200,15 @@
* TODO: Cache some of these for better performance, rather than re-computing?
*/
bool isIndexed() const {
- return GrPrimitiveType::kLines == fMesh.primitiveType() ||
- GrPrimitiveType::kTriangles == fMesh.primitiveType();
+ return GrPrimitiveType::kLines == fPrimitiveType ||
+ GrPrimitiveType::kTriangles == fPrimitiveType;
}
bool isHairline() const {
- return GrPrimitiveType::kLines == fMesh.primitiveType() ||
- GrPrimitiveType::kLineStrip == fMesh.primitiveType();
+ return GrPrimitiveType::kLines == fPrimitiveType ||
+ GrPrimitiveType::kLineStrip == fPrimitiveType;
}
int indexScale() const {
- switch (fMesh.primitiveType()) {
+ switch (fPrimitiveType) {
case GrPrimitiveType::kLines:
return 2;
case GrPrimitiveType::kTriangles:
@@ -271,14 +271,15 @@
SkASSERT(indexCount <= fIndicesInChunk);
if (this->isIndexed() ? SkToBool(indexCount) : SkToBool(vertexCount)) {
+ GrMesh* mesh = fTarget->allocMesh(fPrimitiveType);
if (!this->isIndexed()) {
- fMesh.setNonIndexedNonInstanced(vertexCount);
+ mesh->setNonIndexedNonInstanced(vertexCount);
} else {
- fMesh.setIndexed(fIndexBuffer, indexCount, fFirstIndex, 0, vertexCount - 1,
+ mesh->setIndexed(fIndexBuffer, indexCount, fFirstIndex, 0, vertexCount - 1,
GrPrimitiveRestart::kNo);
}
- fMesh.setVertexData(fVertexBuffer, fFirstVertex);
- fTarget->draw(fGeometryProcessor, fPipeline, fFixedDynamicState, fMesh);
+ mesh->setVertexData(fVertexBuffer, fFirstVertex);
+ fTarget->draw(fGeometryProcessor, fPipeline, fFixedDynamicState, mesh);
}
fTarget->putBackIndices((size_t)(fIndicesInChunk - indexCount));
@@ -311,10 +312,10 @@
}
}
- GrMesh fMesh;
+ GrPrimitiveType fPrimitiveType;
GrMeshDrawOp::Target* fTarget;
size_t fVertexStride;
- GrGeometryProcessor* fGeometryProcessor;
+ sk_sp<const GrGeometryProcessor> fGeometryProcessor;
const GrPipeline* fPipeline;
const GrPipeline::FixedDynamicState* fFixedDynamicState;
@@ -428,7 +429,7 @@
primitiveType = GrPrimitiveType::kTriangles;
}
auto pipe = fHelper.makePipeline(target);
- PathGeoBuilder pathGeoBuilder(primitiveType, target, gp.get(), pipe.fPipeline,
+ PathGeoBuilder pathGeoBuilder(primitiveType, target, std::move(gp), pipe.fPipeline,
pipe.fFixedDynamicState);
// fill buffers
@@ -438,31 +439,31 @@
}
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
DefaultPathOp* that = t->cast<DefaultPathOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->color() != that->color()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->coverage() != that->coverage()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->isHairline() != that->isHairline()) {
- return false;
+ return CombineResult::kCannotCombine;
}
fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
GrColor color() const { return fColor; }
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index d280ad9..107b0be 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -130,9 +130,9 @@
sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0);
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
- QuadHelper helper;
int numQuads = this->quadCount();
- void* verts = helper.init(target, vertexStride, numQuads);
+ QuadHelper helper(target, vertexStride, numQuads);
+ void* verts = helper.vertices();
if (!verts) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -147,34 +147,34 @@
vertPtr += allocSize;
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
-bool GrDrawAtlasOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
+GrOp::CombineResult GrDrawAtlasOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
GrDrawAtlasOp* that = t->cast<GrDrawAtlasOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
// We currently use a uniform viewmatrix for this op.
if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->hasColors() != that->hasColors()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!this->hasColors() && this->color() != that->color()) {
- return false;
+ return CombineResult::kCannotCombine;
}
fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
fQuadCount += that->quadCount();
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
GrDrawOp::FixedFunctionFlags GrDrawAtlasOp::fixedFunctionFlags() const {
diff --git a/src/gpu/ops/GrDrawAtlasOp.h b/src/gpu/ops/GrDrawAtlasOp.h
index 4e894ce..d15bd3c 100644
--- a/src/gpu/ops/GrDrawAtlasOp.h
+++ b/src/gpu/ops/GrDrawAtlasOp.h
@@ -56,7 +56,7 @@
bool hasColors() const { return fHasColors; }
int quadCount() const { return fQuadCount; }
- bool onCombineIfPossible(GrOp* t, const GrCaps&) override;
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps&) override;
struct Geometry {
GrColor fColor;
diff --git a/src/gpu/ops/GrDrawPathOp.h b/src/gpu/ops/GrDrawPathOp.h
index 63986d7..3016fd7 100644
--- a/src/gpu/ops/GrDrawPathOp.h
+++ b/src/gpu/ops/GrDrawPathOp.h
@@ -93,8 +93,6 @@
this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { return false; }
-
void onExecute(GrOpFlushState* state) override;
GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index d227920..dd91452 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -261,7 +261,7 @@
indices);
// Draw the vertices.
- this->drawVertices(target, gp.get(), vertexBuffer, firstVertex, indexBuffer, firstIndex);
+ this->drawVertices(target, std::move(gp), vertexBuffer, firstVertex, indexBuffer, firstIndex);
}
void GrDrawVerticesOp::drawNonVolatile(Target* target) {
@@ -298,7 +298,7 @@
// Draw using the cached buffers if possible.
if (vertexBuffer && (!this->isIndexed() || indexBuffer)) {
- this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0);
+ this->drawVertices(target, std::move(gp), vertexBuffer.get(), 0, indexBuffer.get(), 0);
return;
}
@@ -353,7 +353,7 @@
rp->assignUniqueKeyToResource(indexKey, indexBuffer.get());
// Draw the vertices.
- this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0);
+ this->drawVertices(target, std::move(gp), vertexBuffer.get(), 0, indexBuffer.get(), 0);
}
void GrDrawVerticesOp::fillBuffers(bool hasColorAttribute,
@@ -465,59 +465,58 @@
}
void GrDrawVerticesOp::drawVertices(Target* target,
- GrGeometryProcessor* gp,
+ sk_sp<const GrGeometryProcessor> gp,
const GrBuffer* vertexBuffer,
int firstVertex,
const GrBuffer* indexBuffer,
int firstIndex) {
- GrMesh mesh(this->primitiveType());
+ GrMesh* mesh = target->allocMesh(this->primitiveType());
if (this->isIndexed()) {
- mesh.setIndexed(indexBuffer, fIndexCount,
- firstIndex, 0, fVertexCount - 1,
- GrPrimitiveRestart::kNo);
+ mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1,
+ GrPrimitiveRestart::kNo);
} else {
- mesh.setNonIndexedNonInstanced(fVertexCount);
+ mesh->setNonIndexedNonInstanced(fVertexCount);
}
- mesh.setVertexData(vertexBuffer, firstVertex);
+ mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
-bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
+GrOp::CombineResult GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
GrDrawVerticesOp* that = t->cast<GrDrawVerticesOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
// Meshes with bones cannot be combined because different meshes use different bones, so to
// combine them, the matrices would have to be combined, and the bone indices on each vertex
// would change, thus making the vertices uncacheable.
if (this->hasBones() || that->hasBones()) {
- return false;
+ return CombineResult::kCannotCombine;
}
// Non-volatile meshes cannot batch, because if a non-volatile mesh batches with another mesh,
// then on the next frame, if that non-volatile mesh is drawn, it will draw the other mesh
// that was saved in its vertex buffer, which is not necessarily there anymore.
if (!this->fMeshes[0].fVertices->isVolatile() || !that->fMeshes[0].fVertices->isVolatile()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fMeshes[0].fVertices->hasIndices() != that->fMeshes[0].fVertices->hasIndices()) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fColorArrayType != that->fColorArrayType) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) {
- return false;
+ return CombineResult::kCannotCombine;
}
// NOTE: For SkColor vertex colors, the source color space is always sRGB, and the destination
@@ -542,7 +541,7 @@
fIndexCount += that->fIndexCount;
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index 7695dd9..07227e0 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -80,7 +80,7 @@
uint16_t* indices) const;
void drawVertices(Target*,
- GrGeometryProcessor*,
+ sk_sp<const GrGeometryProcessor>,
const GrBuffer* vertexBuffer,
int firstVertex,
const GrBuffer* indexBuffer,
@@ -98,7 +98,7 @@
GrPrimitiveType::kPoints == fPrimitiveType;
}
- bool onCombineIfPossible(GrOp* t, const GrCaps&) override;
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps&) override;
struct Mesh {
GrColor fColor; // Used if this->hasPerVertexColors() is false.
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 00dbef5..4832ee7 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;
@@ -223,9 +223,9 @@
}
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
- PatternHelper helper(GrPrimitiveType::kTriangles);
- void* vertices = helper.init(target, kVertexStide, indexBuffer.get(), kVertsPerRect,
- kIndicesPerRect, numRects);
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, kVertexStide, indexBuffer.get(),
+ kVertsPerRect, kIndicesPerRect, numRects);
+ void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -281,28 +281,29 @@
kVertsPerRect * patch.fIter->numRectsToDraw());
}
}
- auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ auto pipe = fHelper.makePipeline(target, 1);
+ pipe.fFixedDynamicState->fPrimitiveProcessorTextures[0] = fProxy.get();
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
NonAALatticeOp* that = t->cast<NonAALatticeOp>();
if (fProxy != that->fProxy) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fFilter != that->fFilter) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fPatches.move_back_n(that->fPatches.count(), that->fPatches.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct Patch {
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index 0bac5ef..620ea47 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -14,56 +14,68 @@
void GrMeshDrawOp::onPrepare(GrOpFlushState* state) { this->onPrepareDraws(state); }
-void* GrMeshDrawOp::PatternHelper::init(Target* target, size_t vertexStride,
- const GrBuffer* indexBuffer, int verticesPerRepetition,
- int indicesPerRepetition, int repeatCount) {
- SkASSERT(target);
- if (!indexBuffer) {
- return nullptr;
- }
- const GrBuffer* vertexBuffer;
- int firstVertex;
- int vertexCount = verticesPerRepetition * repeatCount;
- void* vertices =
- target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
- if (!vertices) {
- SkDebugf("Vertices could not be allocated for instanced rendering.");
- return nullptr;
- }
- SkASSERT(vertexBuffer);
- size_t ibSize = indexBuffer->gpuMemorySize();
- int maxRepetitions = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerRepetition));
-
- fMesh.setIndexedPatterned(indexBuffer, indicesPerRepetition, verticesPerRepetition,
- repeatCount, maxRepetitions);
- fMesh.setVertexData(vertexBuffer, firstVertex);
- return vertices;
-}
-
-void GrMeshDrawOp::PatternHelper::recordDraw(
- Target* target, const GrGeometryProcessor* gp, const GrPipeline* pipeline,
- const GrPipeline::FixedDynamicState* fixedDynamicState) {
- target->draw(gp, pipeline, fixedDynamicState, fMesh);
-}
-
-void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int quadsToDraw) {
- sk_sp<const GrBuffer> quadIndexBuffer = target->resourceProvider()->refQuadIndexBuffer();
- if (!quadIndexBuffer) {
- SkDebugf("Could not get quad index buffer.");
- return nullptr;
- }
- return this->INHERITED::init(target, vertexStride, quadIndexBuffer.get(), kVerticesPerQuad,
- kIndicesPerQuad, quadsToDraw);
-}
-
void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
state->executeDrawsAndUploadsForMeshDrawOp(this->uniqueID(), this->bounds());
}
//////////////////////////////////////////////////////////////////////////////
+GrMeshDrawOp::PatternHelper::PatternHelper(Target* target, GrPrimitiveType primitiveType,
+ size_t vertexStride, const GrBuffer* indexBuffer,
+ int verticesPerRepetition, int indicesPerRepetition,
+ int repeatCount) {
+ this->init(target, primitiveType, vertexStride, indexBuffer, verticesPerRepetition,
+ indicesPerRepetition, repeatCount);
+}
+
+void GrMeshDrawOp::PatternHelper::init(Target* target, GrPrimitiveType primitiveType,
+ size_t vertexStride, const GrBuffer* indexBuffer,
+ int verticesPerRepetition, int indicesPerRepetition,
+ int repeatCount) {
+ SkASSERT(target);
+ if (!indexBuffer) {
+ return;
+ }
+ const GrBuffer* vertexBuffer;
+ int firstVertex;
+ int vertexCount = verticesPerRepetition * repeatCount;
+ fVertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
+ if (!fVertices) {
+ SkDebugf("Vertices could not be allocated for patterned rendering.");
+ return;
+ }
+ SkASSERT(vertexBuffer);
+ size_t ibSize = indexBuffer->gpuMemorySize();
+ int maxRepetitions = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerRepetition));
+ fMesh = target->allocMesh(primitiveType);
+ fMesh->setIndexedPatterned(indexBuffer, indicesPerRepetition, verticesPerRepetition,
+ repeatCount, maxRepetitions);
+ fMesh->setVertexData(vertexBuffer, firstVertex);
+}
+
+void GrMeshDrawOp::PatternHelper::recordDraw(
+ Target* target, sk_sp<const GrGeometryProcessor> gp, const GrPipeline* pipeline,
+ const GrPipeline::FixedDynamicState* fixedDynamicState) const {
+ target->draw(std::move(gp), pipeline, fixedDynamicState, fMesh);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrMeshDrawOp::QuadHelper::QuadHelper(Target* target, size_t vertexStride, int quadsToDraw) {
+ sk_sp<const GrBuffer> quadIndexBuffer = target->resourceProvider()->refQuadIndexBuffer();
+ if (!quadIndexBuffer) {
+ SkDebugf("Could not get quad index buffer.");
+ return;
+ }
+ this->init(target, GrPrimitiveType::kTriangles, vertexStride, quadIndexBuffer.get(),
+ kVerticesPerQuad, kIndicesPerQuad, quadsToDraw);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
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 +83,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..a6e7da5 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -12,7 +12,6 @@
#include "GrDrawOp.h"
#include "GrGeometryProcessor.h"
#include "GrMesh.h"
-#include "GrPendingProgramElement.h"
class GrAtlasManager;
class GrCaps;
@@ -34,18 +33,23 @@
space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
class PatternHelper {
public:
- PatternHelper(GrPrimitiveType primitiveType) : fMesh(primitiveType) {}
- /** Returns the allocated storage for the vertices. The caller should populate the vertices
- before calling recordDraws(). */
- void* init(Target*, size_t vertexStride, const GrBuffer*, int verticesPerRepetition,
- int indicesPerRepetition, int repeatCount);
+ PatternHelper(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
+ int verticesPerRepetition, int indicesPerRepetition, int repeatCount);
- /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
- void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*,
- const GrPipeline::FixedDynamicState*);
+ /** Called to issue draws to the GrMeshDrawOp::Target.*/
+ void recordDraw(Target*, sk_sp<const GrGeometryProcessor>, const GrPipeline*,
+ const GrPipeline::FixedDynamicState*) const;
+
+ void* vertices() const { return fVertices; }
+
+ protected:
+ PatternHelper() = default;
+ void init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
+ int verticesPerRepetition, int indicesPerRepetition, int repeatCount);
private:
- GrMesh fMesh;
+ void* fVertices = nullptr;
+ GrMesh* fMesh = nullptr;
};
static const int kVerticesPerQuad = 4;
@@ -54,13 +58,11 @@
/** A specialization of InstanceHelper for quad rendering. */
class QuadHelper : private PatternHelper {
public:
- QuadHelper() : INHERITED(GrPrimitiveType::kTriangles) {}
- /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure
- and on success a pointer to the vertex data that the caller should populate before
- calling recordDraws(). */
- void* init(Target*, size_t vertexStride, int quadsToDraw);
+ QuadHelper() = delete;
+ QuadHelper(Target* target, size_t vertexStride, int quadsToDraw);
using PatternHelper::recordDraw;
+ using PatternHelper::vertices;
private:
typedef PatternHelper INHERITED;
@@ -78,8 +80,19 @@
virtual ~Target() {}
/** Adds a draw of a mesh. */
- virtual void draw(const GrGeometryProcessor*, const GrPipeline*,
- const GrPipeline::FixedDynamicState*, const GrMesh&) = 0;
+ virtual void draw(sk_sp<const GrGeometryProcessor>,
+ const GrPipeline*,
+ const GrPipeline::FixedDynamicState*,
+ const GrMesh[],
+ int meshCount) = 0;
+
+ /** Helper for drawing a single GrMesh. */
+ void draw(sk_sp<const GrGeometryProcessor> gp,
+ const GrPipeline* pipeline,
+ const GrPipeline::FixedDynamicState* fixedDynamicState,
+ const GrMesh* mesh) {
+ this->draw(std::move(gp), pipeline, fixedDynamicState, mesh, 1);
+ }
/**
* Makes space for vertex data. The returned pointer is the location where vertex data
@@ -132,10 +145,25 @@
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)...);
+ GrMesh* allocMesh(GrPrimitiveType primitiveType) {
+ return this->pipelineArena()->make<GrMesh>(primitiveType);
+ }
+
+ GrMesh* allocMeshes(int n) { return this->pipelineArena()->makeArray<GrMesh>(n); }
+
+ 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 +172,7 @@
// std::tie(flushInfo.fPipeline, flushInfo.fFixedState) = target->makePipeline(...);
struct PipelineAndFixedDynamicState {
const GrPipeline* fPipeline;
- const GrPipeline::FixedDynamicState* fFixedDynamicState;
+ GrPipeline::FixedDynamicState* fFixedDynamicState;
};
/**
@@ -152,7 +180,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/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp
index c554232..fd8a9b3 100644
--- a/src/gpu/ops/GrNonAAFillRectOp.cpp
+++ b/src/gpu/ops/GrNonAAFillRectOp.cpp
@@ -192,9 +192,9 @@
int rectCount = fRects.count();
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
- PatternHelper helper(GrPrimitiveType::kTriangles);
- void* vertices = helper.init(target, kVertexStride, indexBuffer.get(), kVertsPerRect,
- kIndicesPerRect, rectCount);
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, kVertexStride, indexBuffer.get(),
+ kVertsPerRect, kIndicesPerRect, rectCount);
+ void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -207,17 +207,17 @@
fRects[i].fRect, &fRects[i].fLocalQuad);
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
NonAAFillRectOp* that = t->cast<NonAAFillRectOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRects.push_back_n(that->fRects.count(), that->fRects.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct RectInfo {
@@ -325,9 +325,9 @@
int rectCount = fRects.count();
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
- PatternHelper helper(GrPrimitiveType::kTriangles);
- void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect,
- kIndicesPerRect, rectCount);
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
+ kVertsPerRect, kIndicesPerRect, rectCount);
+ void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -345,29 +345,29 @@
}
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
NonAAFillRectPerspectiveOp* that = t->cast<NonAAFillRectPerspectiveOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
// We could combine across perspective vm changes if we really wanted to.
if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHasLocalRect != that->fHasLocalRect) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHasLocalMatrix && !fLocalMatrix.cheapEqualTo(that->fLocalMatrix)) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRects.push_back_n(that->fRects.count(), that->fRects.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct RectInfo {
diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
index 21636b2..500b2eb 100644
--- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
@@ -188,18 +188,14 @@
vertex[4].set(fRect.fLeft, fRect.fTop);
}
- GrMesh mesh(primType);
- mesh.setNonIndexedNonInstanced(vertexCount);
- mesh.setVertexData(vertexBuffer, firstVertex);
+ GrMesh* mesh = target->allocMesh(primType);
+ mesh->setNonIndexedNonInstanced(vertexCount);
+ mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps&) override {
- // NonAA stroke rects cannot combine right now
- // TODO make these combinable.
- return false;
- }
+ // TODO: override onCombineIfPossible
Helper fHelper;
GrColor fColor;
diff --git a/src/gpu/ops/GrOp.h b/src/gpu/ops/GrOp.h
index 5c776fc..57e028e 100644
--- a/src/gpu/ops/GrOp.h
+++ b/src/gpu/ops/GrOp.h
@@ -75,9 +75,21 @@
// This default implementation assumes the op has no proxies
}
- bool combineIfPossible(GrOp* that, const GrCaps& caps) {
+ enum class CombineResult {
+ /**
+ * The op that combineIfPossible was called on now represents its own work plus that of
+ * the passed op. The passed op should be destroyed without being flushed.
+ */
+ kMerged,
+ /**
+ * The ops cannot be combined.
+ */
+ kCannotCombine
+ };
+
+ CombineResult combineIfPossible(GrOp* that, const GrCaps& caps) {
if (this->classID() != that->classID()) {
- return false;
+ return CombineResult::kCannotCombine;
}
return this->onCombineIfPossible(that, caps);
@@ -211,7 +223,9 @@
static uint32_t GenOpClassID() { return GenID(&gCurrOpClassID); }
private:
- virtual bool onCombineIfPossible(GrOp*, const GrCaps& caps) = 0;
+ virtual CombineResult onCombineIfPossible(GrOp*, const GrCaps&) {
+ return CombineResult::kCannotCombine;
+ }
virtual void onPrepare(GrOpFlushState*) = 0;
virtual void onExecute(GrOpFlushState*) = 0;
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 54bb37c..c0158ba 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1470,29 +1470,29 @@
vertices += circle_type_to_vert_count(circle.fStroked) * vertexStride;
}
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
CircleOp* that = t->cast<CircleOp>();
// can only represent 65535 unique vertices with 16-bit indices
if (fVertCount + that->fVertCount > 65536) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() &&
!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
- return false;
+ return CombineResult::kCannotCombine;
}
// Because we've set up the ops that don't use the planes with noop values
@@ -1507,7 +1507,7 @@
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
fAllFill = fAllFill && that->fAllFill;
- return true;
+ return CombineResult::kMerged;
}
struct Circle {
@@ -1786,36 +1786,36 @@
vertices += circle_type_to_vert_count(true) * kVertexStride;
}
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
ButtCapDashedCircleOp* that = t->cast<ButtCapDashedCircleOp>();
// can only represent 65535 unique vertices with 16-bit indices
if (fVertCount + that->fVertCount > 65536) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() &&
!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
- return false;
+ return CombineResult::kCannotCombine;
}
fCircles.push_back_n(that->fCircles.count(), that->fCircles.begin());
this->joinBounds(*that);
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
- return true;
+ return CombineResult::kMerged;
}
struct Circle {
@@ -1984,10 +1984,9 @@
// Setup geometry processor
sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix));
- QuadHelper helper;
SkASSERT(sizeof(EllipseVertex) == gp->debugOnly_vertexStride());
- EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
- helper.init(target, sizeof(EllipseVertex), fEllipses.count()));
+ QuadHelper helper(target, sizeof(EllipseVertex), fEllipses.count());
+ EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(helper.vertices());
if (!verts) {
return;
}
@@ -2040,28 +2039,28 @@
verts += kVerticesPerQuad;
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
EllipseOp* that = t->cast<EllipseOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fStroked != that->fStroked) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() &&
!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
- return false;
+ return CombineResult::kCannotCombine;
}
fEllipses.push_back_n(that->fEllipses.count(), that->fEllipses.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct Ellipse {
@@ -2219,9 +2218,8 @@
new DIEllipseGeometryProcessor(this->viewMatrix(), this->style()));
SkASSERT(sizeof(DIEllipseVertex) == gp->debugOnly_vertexStride());
- QuadHelper helper;
- DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(
- helper.init(target, sizeof(DIEllipseVertex), fEllipses.count()));
+ QuadHelper helper(target, sizeof(DIEllipseVertex), fEllipses.count());
+ DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(helper.vertices());
if (!verts) {
return;
}
@@ -2274,27 +2272,27 @@
verts += kVerticesPerQuad;
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
DIEllipseOp* that = t->cast<DIEllipseOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->style() != that->style()) {
- return false;
+ return CombineResult::kCannotCombine;
}
// TODO rewrite to allow positioning on CPU
if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
+ return CombineResult::kCannotCombine;
}
fEllipses.push_back_n(that->fEllipses.count(), that->fEllipses.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
const SkMatrix& viewMatrix() const { return fEllipses[0].fViewMatrix; }
@@ -2725,29 +2723,29 @@
currStartVertex += rrect_type_to_vert_count(rrect.fType);
}
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
CircularRRectOp* that = t->cast<CircularRRectOp>();
// can only represent 65535 unique vertices with 16-bit indices
if (fVertCount + that->fVertCount > 65536) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() &&
!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin());
@@ -2755,7 +2753,7 @@
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
fAllFill = fAllFill && that->fAllFill;
- return true;
+ return CombineResult::kMerged;
}
struct RRect {
@@ -2927,10 +2925,10 @@
sk_sp<const GrBuffer> indexBuffer = get_rrect_index_buffer(
fStroked ? kStroke_RRectType : kFill_RRectType, target->resourceProvider());
- PatternHelper helper(GrPrimitiveType::kTriangles);
- EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
- helper.init(target, sizeof(EllipseVertex), indexBuffer.get(),
- kVertsPerStandardRRect, indicesPerInstance, fRRects.count()));
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, sizeof(EllipseVertex),
+ indexBuffer.get(), kVertsPerStandardRRect, indicesPerInstance,
+ fRRects.count());
+ EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(helper.vertices());
if (!verts || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -2997,28 +2995,28 @@
}
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
EllipticalRRectOp* that = t->cast<EllipticalRRectOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fStroked != that->fStroked) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fHelper.usesLocalCoords() &&
!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct RRect {
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index d0c24e6..b876295 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -129,9 +129,9 @@
return;
}
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
- PatternHelper helper(GrPrimitiveType::kTriangles);
- void* vertices = helper.init(target, kVertexStride, indexBuffer.get(), kVertsPerInstance,
- kIndicesPerInstance, numRects);
+ PatternHelper helper(target, GrPrimitiveType::kTriangles, kVertexStride, indexBuffer.get(),
+ kVertsPerInstance, kIndicesPerInstance, numRects);
+ void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -144,22 +144,22 @@
verts += numRectsInRegion * kVertsPerInstance * kVertexStride;
}
auto pipe = fHelper.makePipeline(target);
- helper.recordDraw(target, gp.get(), pipe.fPipeline, pipe.fFixedDynamicState);
+ helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
RegionOp* that = t->cast<RegionOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (fViewMatrix != that->fViewMatrix) {
- return false;
+ return CombineResult::kCannotCombine;
}
fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
struct RegionInfo {
diff --git a/src/gpu/ops/GrSemaphoreOp.h b/src/gpu/ops/GrSemaphoreOp.h
index 234c76c..53c76c3 100644
--- a/src/gpu/ops/GrSemaphoreOp.h
+++ b/src/gpu/ops/GrSemaphoreOp.h
@@ -34,7 +34,6 @@
sk_sp<GrSemaphore> fSemaphore;
private:
- bool onCombineIfPossible(GrOp* that, const GrCaps& caps) override { return false; }
void onPrepare(GrOpFlushState*) override {}
typedef GrOp INHERITED;
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index 09a2442..69489a2 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -627,20 +627,20 @@
auto pipe = target->makePipeline(kPipelineFlags, GrProcessorSet::MakeEmptySet(),
target->detachAppliedClip());
- GrMesh mesh(GrPrimitiveType::kTriangles);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
- GrPrimitiveRestart::kNo);
- mesh.setVertexData(vertexBuffer, firstVertex);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(vertexBuffer, firstVertex);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
ShadowCircularRRectOp* that = t->cast<ShadowCircularRRectOp>();
fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
this->joinBounds(*that);
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
- return true;
+ return CombineResult::kMerged;
}
SkSTArray<1, Geometry, true> fGeoData;
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..c480bc0 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) {
@@ -820,14 +833,14 @@
}
if (flushInfo->fInstancesToFlush) {
- GrMesh mesh(GrPrimitiveType::kTriangles);
+ GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
int maxInstancesPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
- mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerQuad,
- kVerticesPerQuad, flushInfo->fInstancesToFlush,
- maxInstancesPerDraw);
- mesh.setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
- target->draw(flushInfo->fGeometryProcessor.get(), flushInfo->fPipeline,
+ mesh->setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerQuad,
+ kVerticesPerQuad, flushInfo->fInstancesToFlush,
+ maxInstancesPerDraw);
+ mesh->setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
+ target->draw(flushInfo->fGeometryProcessor, flushInfo->fPipeline,
flushInfo->fFixedDynamicState, mesh);
flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush;
flushInfo->fInstancesToFlush = 0;
@@ -837,41 +850,41 @@
GrColor color() const { return fShapes[0].fColor; }
bool usesDistanceField() const { return fUsesDistanceField; }
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
SmallPathOp* that = t->cast<SmallPathOp>();
if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->usesDistanceField() != that->usesDistanceField()) {
- return false;
+ return CombineResult::kCannotCombine;
}
const SkMatrix& thisCtm = this->fShapes[0].fViewMatrix;
const SkMatrix& thatCtm = that->fShapes[0].fViewMatrix;
if (thisCtm.hasPerspective() != thatCtm.hasPerspective()) {
- return false;
+ return CombineResult::kCannotCombine;
}
// We can position on the cpu unless we're in perspective,
// but also need to make sure local matrices are identical
if ((thisCtm.hasPerspective() || fHelper.usesLocalCoords()) &&
!thisCtm.cheapEqualTo(thatCtm)) {
- return false;
+ return CombineResult::kCannotCombine;
}
// Depending on the ctm we may have a different shader for SDF paths
if (this->usesDistanceField()) {
if (thisCtm.isScaleTranslate() != thatCtm.isScaleTranslate() ||
thisCtm.isSimilarity() != thatCtm.isSimilarity()) {
- return false;
+ return CombineResult::kCannotCombine;
}
}
fShapes.push_back_n(that->fShapes.count(), that->fShapes.begin());
this->joinBounds(*that);
- return true;
+ return CombineResult::kMerged;
}
bool fUsesDistanceField;
diff --git a/src/gpu/ops/GrStencilPathOp.h b/src/gpu/ops/GrStencilPathOp.h
index 563bdc3..edfcaa8 100644
--- a/src/gpu/ops/GrStencilPathOp.h
+++ b/src/gpu/ops/GrStencilPathOp.h
@@ -56,8 +56,6 @@
this->setBounds(path->getBounds(), HasAABloat::kNo, IsZeroArea::kNo);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { return false; }
-
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState* state) override;
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index 2fea9cb..f722868 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -237,7 +237,7 @@
return path;
}
- void draw(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) {
+ void draw(Target* target, sk_sp<const GrGeometryProcessor> gp, size_t vertexStride) {
SkASSERT(!fAntiAlias);
GrResourceProvider* rp = target->resourceProvider();
bool inverseFill = fShape.inverseFilled();
@@ -261,7 +261,7 @@
SkScalar tol = GrPathUtils::kDefaultTolerance;
tol = GrPathUtils::scaleToleranceToSrc(tol, fViewMatrix, fShape.bounds());
if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
- this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCount);
+ this->drawVertices(target, std::move(gp), cachedVertexBuffer.get(), 0, actualCount);
return;
}
@@ -280,7 +280,7 @@
if (count == 0) {
return;
}
- this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count);
+ this->drawVertices(target, std::move(gp), allocator.vertexBuffer(), 0, count);
TessInfo info;
info.fTolerance = isLinear ? 0 : tol;
info.fCount = count;
@@ -289,7 +289,7 @@
fShape.addGenIDChangeListener(sk_make_sp<PathInvalidator>(key, target->contextUniqueID()));
}
- void drawAA(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) {
+ void drawAA(Target* target, sk_sp<const GrGeometryProcessor> gp, size_t vertexStride) {
SkASSERT(fAntiAlias);
SkPath path = getPath();
if (path.isEmpty()) {
@@ -306,7 +306,8 @@
if (count == 0) {
return;
}
- this->drawVertices(target, gp, allocator.vertexBuffer(), allocator.firstVertex(), count);
+ this->drawVertices(target, std::move(gp), allocator.vertexBuffer(), allocator.firstVertex(),
+ count);
}
void onPrepareDraws(Target* target) override {
@@ -349,23 +350,22 @@
}
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
if (fAntiAlias) {
- this->drawAA(target, gp.get(), vertexStride);
+ this->drawAA(target, std::move(gp), vertexStride);
} else {
- this->draw(target, gp.get(), vertexStride);
+ this->draw(target, std::move(gp), vertexStride);
}
}
- void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuffer* vb,
+ void drawVertices(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrBuffer* vb,
int firstVertex, int count) {
- GrMesh mesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines : GrPrimitiveType::kTriangles);
- mesh.setNonIndexedNonInstanced(count);
- mesh.setVertexData(vb, firstVertex);
+ GrMesh* mesh = target->allocMesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines
+ : GrPrimitiveType::kTriangles);
+ mesh->setNonIndexedNonInstanced(count);
+ mesh->setVertexData(vb, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; }
-
Helper fHelper;
GrColor fColor;
GrShape fShape;
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 72900ed..2ba3639 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -37,8 +37,6 @@
namespace {
-enum class MultiTexture : bool { kNo = false, kYes = true };
-
enum class Domain : bool { kNo = false, kYes = true };
/**
@@ -55,79 +53,40 @@
SkPoint fTextureCoords;
};
- template <typename Pos, MultiTexture MT> struct OptionalMultiTextureVertex;
+ template <typename Pos, Domain D> struct OptionalDomainVertex;
template <typename Pos>
- struct OptionalMultiTextureVertex<Pos, MultiTexture::kNo> : VertexCommon<Pos> {
- static constexpr MultiTexture kMultiTexture = MultiTexture::kNo;
- };
- template <typename Pos>
- struct OptionalMultiTextureVertex<Pos, MultiTexture::kYes> : VertexCommon<Pos> {
- static constexpr MultiTexture kMultiTexture = MultiTexture::kYes;
- int fTextureIdx;
- };
-
- template <typename Pos, MultiTexture MT, Domain D> struct OptionalDomainVertex;
- template <typename Pos, MultiTexture MT>
- struct OptionalDomainVertex<Pos, MT, Domain::kNo> : OptionalMultiTextureVertex<Pos, MT> {
+ struct OptionalDomainVertex<Pos, Domain::kNo> : VertexCommon<Pos> {
static constexpr Domain kDomain = Domain::kNo;
};
- template <typename Pos, MultiTexture MT>
- struct OptionalDomainVertex<Pos, MT, Domain::kYes> : OptionalMultiTextureVertex<Pos, MT> {
+ template <typename Pos>
+ struct OptionalDomainVertex<Pos, Domain::kYes> : VertexCommon<Pos> {
static constexpr Domain kDomain = Domain::kYes;
SkRect fTextureDomain;
};
- template <typename Pos, MultiTexture MT, Domain D, GrAA> struct OptionalAAVertex;
- template <typename Pos, MultiTexture MT, Domain D>
- struct OptionalAAVertex<Pos, MT, D, GrAA::kNo> : OptionalDomainVertex<Pos, MT, D> {
+ template <typename Pos, Domain D, GrAA> struct OptionalAAVertex;
+ template <typename Pos, Domain D>
+ struct OptionalAAVertex<Pos, D, GrAA::kNo> : OptionalDomainVertex<Pos, D> {
static constexpr GrAA kAA = GrAA::kNo;
};
- template <typename Pos, MultiTexture MT, Domain D>
- struct OptionalAAVertex<Pos, MT, D, GrAA::kYes> : OptionalDomainVertex<Pos, MT, D> {
+ template <typename Pos, Domain D>
+ struct OptionalAAVertex<Pos, D, GrAA::kYes> : OptionalDomainVertex<Pos, D> {
static constexpr GrAA kAA = GrAA::kYes;
SkPoint3 fEdges[4];
};
- template <typename Pos, MultiTexture MT, Domain D, GrAA AA>
- using Vertex = OptionalAAVertex<Pos, MT, D, AA>;
+ template <typename Pos, Domain D, GrAA AA>
+ using Vertex = OptionalAAVertex<Pos, D, AA>;
- // Maximum number of textures supported by this op. Must also be checked against the caps
- // limit. These numbers were based on some limited experiments on a HP Z840 and Pixel XL 2016
- // and could probably use more tuning.
-#ifdef SK_BUILD_FOR_ANDROID
- static constexpr int kMaxTextures = 4;
-#else
- static constexpr int kMaxTextures = 8;
-#endif
-
- static int SupportsMultitexture(const GrShaderCaps& caps) {
- 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,
+ const GrSamplerState::Filter filter,
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
sk_sp<GrColorSpaceXform> paintColorSpaceXform,
- bool coverageAA,
- bool perspective, Domain domain,
- const GrSamplerState::Filter filters[],
+ bool coverageAA, bool perspective, Domain domain,
const GrShaderCaps& caps) {
- // We use placement new to avoid always allocating space for kMaxTextures TextureSampler
- // instances.
- int samplerCnt = NumSamplersToUse(proxyCnt, 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));
- }
-
- ~TextureGeometryProcessor() override {
- int cnt = this->numTextureSamplers();
- for (int i = 1; i < cnt; ++i) {
- fSamplers[i].~TextureSampler();
- }
+ return sk_sp<TextureGeometryProcessor>(new TextureGeometryProcessor(
+ textureType, textureConfig, filter, std::move(textureColorSpaceXform),
+ std::move(paintColorSpaceXform), coverageAA, perspective, domain, caps));
}
const char* name() const override { return "TextureGeometryProcessor"; }
@@ -197,28 +156,10 @@
args.fFragBuilder->codeAppend(
"texCoord = clamp(texCoord, domain.xy, domain.zw);");
}
- if (textureGP.numTextureSamplers() > 1) {
- // If this changes to float, reconsider Interpolation::kMustBeFlat.
- SkASSERT(kInt_GrVertexAttribType == textureGP.fTextureIdx.type());
- SkASSERT(args.fShaderCaps->integerSupport());
- args.fFragBuilder->codeAppend("int texIdx;");
- args.fVaryingHandler->addPassThroughAttribute(textureGP.fTextureIdx, "texIdx",
- Interpolation::kMustBeFlat);
- args.fFragBuilder->codeAppend("switch (texIdx) {");
- for (int i = 0; i < textureGP.numTextureSamplers(); ++i) {
- args.fFragBuilder->codeAppendf("case %d: %s = ", i, args.fOutputColor);
- args.fFragBuilder->appendTextureLookupAndModulate(
- args.fOutputColor, args.fTexSamplers[i], "texCoord",
- kFloat2_GrSLType, &fTextureColorSpaceXformHelper);
- args.fFragBuilder->codeAppend("; break;");
- }
- args.fFragBuilder->codeAppend("}");
- } else {
- args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor);
- args.fFragBuilder->appendTextureLookupAndModulate(
- args.fOutputColor, args.fTexSamplers[0], "texCoord",
- kFloat2_GrSLType, &fTextureColorSpaceXformHelper);
- }
+ args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor);
+ args.fFragBuilder->appendTextureLookupAndModulate(
+ args.fOutputColor, args.fTexSamplers[0], "texCoord", kFloat2_GrSLType,
+ &fTextureColorSpaceXformHelper);
args.fFragBuilder->codeAppend(";");
if (textureGP.usesCoverageEdgeAA()) {
bool mulByFragCoordW = false;
@@ -271,36 +212,16 @@
bool usesCoverageEdgeAA() const { return SkToBool(fAAEdges[0].isInitialized()); }
private:
- // This exists to reduce the number of shaders generated. It does some rounding of sampler
- // counts.
- static int NumSamplersToUse(int numRealProxies, const GrShaderCaps& caps) {
- SkASSERT(numRealProxies > 0 && numRealProxies <= kMaxTextures &&
- numRealProxies <= caps.maxFragmentSamplers());
- if (1 == numRealProxies) {
- return 1;
- }
- if (numRealProxies <= 4) {
- return 4;
- }
- // Round to the next power of 2 and then clamp to kMaxTextures and the max allowed by caps.
- return SkTMin(SkNextPow2(numRealProxies), SkTMin(kMaxTextures, caps.maxFragmentSamplers()));
- }
-
- TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt,
+ TextureGeometryProcessor(GrTextureType textureType, GrPixelConfig textureConfig,
+ GrSamplerState::Filter filter,
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
- sk_sp<GrColorSpaceXform> paintColorSpaceXform,
- bool coverageAA, bool perspective, Domain domain,
- const GrSamplerState::Filter filters[], const GrShaderCaps& caps)
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform, bool coverageAA,
+ bool perspective, Domain domain, 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) {
- // 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]);
- }
+ , fPaintColorSpaceXform(std::move(paintColorSpaceXform))
+ , fSampler(textureType, textureConfig, filter) {
+ this->setTextureSamplerCnt(1);
if (perspective) {
fPositions = {"position", kFloat3_GrVertexAttribType};
@@ -311,17 +232,6 @@
fTextureCoords = {"textureCoords", kFloat2_GrVertexAttribType};
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]);
- }
- SkASSERT(caps.integerSupport());
- fTextureIdx = {"textureIdx", kInt_GrVertexAttribType};
- ++vertexAttributeCnt;
- }
if (domain == Domain::kYes) {
fDomain = {"domain", kFloat4_GrVertexAttribType};
++vertexAttributeCnt;
@@ -334,25 +244,23 @@
vertexAttributeCnt += 4;
}
this->setVertexAttributeCnt(vertexAttributeCnt);
- this->setTextureSamplerCnt(samplerCnt);
}
const Attribute& onVertexAttribute(int i) const override {
- return IthInitializedAttribute(i, fPositions, fColors, fTextureCoords, fTextureIdx, fDomain,
- fAAEdges[0], fAAEdges[1], fAAEdges[2], fAAEdges[3]);
+ return IthInitializedAttribute(i, fPositions, fColors, fTextureCoords, fDomain, fAAEdges[0],
+ fAAEdges[1], fAAEdges[2], fAAEdges[3]);
}
- const TextureSampler& onTextureSampler(int i) const override { return fSamplers[i]; }
+ const TextureSampler& onTextureSampler(int) const override { return fSampler; }
Attribute fPositions;
Attribute fColors;
Attribute fTextureCoords;
- Attribute fTextureIdx;
Attribute fDomain;
Attribute fAAEdges[4];
sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
sk_sp<GrColorSpaceXform> fPaintColorSpaceXform;
- TextureSampler fSamplers[1];
+ TextureSampler fSampler;
typedef GrGeometryProcessor INHERITED;
};
@@ -527,20 +435,6 @@
}
};
-template <typename V, MultiTexture MT = V::kMultiTexture> struct TexIdAssigner;
-
-template <typename V> struct TexIdAssigner<V, MultiTexture::kYes> {
- static void Assign(V* vertices, int textureIdx) {
- for (int i = 0; i < 4; ++i) {
- vertices[i].fTextureIdx = textureIdx;
- }
- }
-};
-
-template <typename V> struct TexIdAssigner<V, MultiTexture::kNo> {
- static void Assign(V* vertices, int textureIdx) {}
-};
-
template <typename V, Domain D = V::kDomain> struct DomainAssigner;
template <typename V> struct DomainAssigner<V, Domain::kYes> {
@@ -585,7 +479,7 @@
template <typename V>
static void tessellate_quad(const GrPerspQuad& devQuad, const SkRect& srcRect, GrColor color,
GrSurfaceOrigin origin, GrSamplerState::Filter filter, V* vertices,
- SkScalar iw, SkScalar ih, int textureIdx, Domain domain) {
+ SkScalar iw, SkScalar ih, Domain domain) {
SkRect texRect = {
iw * srcRect.fLeft,
ih * srcRect.fTop,
@@ -601,7 +495,6 @@
vertices[1].fColor = color;
vertices[2].fColor = color;
vertices[3].fColor = color;
- TexIdAssigner<V>::Assign(vertices, textureIdx);
DomainAssigner<V>::Assign(vertices, domain, filter, srcRect, origin, iw, ih);
}
@@ -632,42 +525,27 @@
~TextureOp() override {
if (fFinalized) {
- auto proxies = this->proxies();
- for (int i = 0; i < fProxyCnt; ++i) {
- proxies[i]->completedRead();
- }
- if (fProxyCnt > 1) {
- delete[] reinterpret_cast<const char*>(proxies);
- }
+ fProxy->completedRead();
} else {
- SkASSERT(1 == fProxyCnt);
- fProxy0->unref();
+ fProxy->unref();
}
}
const char* name() const override { return "TextureOp"; }
- void visitProxies(const VisitProxyFunc& func) const override {
- auto proxies = this->proxies();
- for (int i = 0; i < fProxyCnt; ++i) {
- func(proxies[i]);
- }
- }
+ void visitProxies(const VisitProxyFunc& func) const override { func(fProxy); }
SkString dumpInfo() const override {
SkString str;
str.appendf("# draws: %d\n", fDraws.count());
- auto proxies = this->proxies();
- for (int i = 0; i < fProxyCnt; ++i) {
- str.appendf("Proxy ID %d: %d, Filter: %d\n", i, proxies[i]->uniqueID().asUInt(),
- static_cast<int>(this->filters()[i]));
- }
+ str.appendf("Proxy ID: %d, Filter: %d\n", fProxy->uniqueID().asUInt(),
+ static_cast<int>(fFilter));
for (int i = 0; i < fDraws.count(); ++i) {
const Draw& draw = fDraws[i];
str.appendf(
- "%d: Color: 0x%08x, ProxyIdx: %d, TexRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f] "
+ "%d: Color: 0x%08x, TexRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f] "
"Quad [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n",
- i, draw.color(), draw.textureIdx(), draw.srcRect().fLeft, draw.srcRect().fTop,
+ i, draw.color(), draw.srcRect().fLeft, draw.srcRect().fTop,
draw.srcRect().fRight, draw.srcRect().fBottom, draw.quad().point(0).fX,
draw.quad().point(0).fY, draw.quad().point(1).fX, draw.quad().point(1).fY,
draw.quad().point(2).fX, draw.quad().point(2).fY, draw.quad().point(3).fX,
@@ -679,10 +557,9 @@
RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
SkASSERT(!fFinalized);
- SkASSERT(1 == fProxyCnt);
fFinalized = true;
- fProxy0->addPendingRead();
- fProxy0->unref();
+ fProxy->addPendingRead();
+ fProxy->unref();
return RequiresDstTexture::kNo;
}
@@ -696,17 +573,6 @@
private:
friend class ::GrOpMemoryPool;
- // This is used in a heursitic for choosing a code path. We don't care what happens with
- // really large rects, infs, nans, etc.
-#if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007
-__attribute__((no_sanitize("float-cast-overflow")))
-#endif
- size_t RectSizeAsSizeT(const SkRect& rect) {;
- return static_cast<size_t>(SkTMax(rect.width(), 1.f) * SkTMax(rect.height(), 1.f));
- }
-
- static constexpr int kMaxTextures = TextureGeometryProcessor::kMaxTextures;
-
TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color,
const SkRect& srcRect, const SkRect& dstRect, GrAAType aaType,
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
@@ -715,9 +581,8 @@
: INHERITED(ClassID())
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
, fPaintColorSpaceXform(std::move(paintColorSpaceXform))
- , fProxy0(proxy.release())
- , fFilter0(filter)
- , fProxyCnt(1)
+ , fProxy(proxy.release())
+ , fFilter(filter)
, fAAType(static_cast<unsigned>(aaType))
, fFinalized(0) {
SkASSERT(aaType != GrAAType::kMixedSamples);
@@ -740,46 +605,39 @@
}
}
#endif
- const auto& draw = fDraws.emplace_back(srcRect, 0, quad, constraint, color);
+ const auto& draw = fDraws.emplace_back(srcRect, quad, constraint, color);
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
fDomain = static_cast<bool>(draw.domain());
- fMaxApproxDstPixelArea = RectSizeAsSizeT(bounds);
}
- template <typename Pos, MultiTexture MT, Domain D, GrAA AA>
- void tess(void* v, const float iw[], const float ih[], const GrGeometryProcessor* gp) {
- using Vertex = TextureGeometryProcessor::Vertex<Pos, MT, D, AA>;
+ template <typename Pos, Domain D, GrAA AA>
+ void tess(void* v, const GrGeometryProcessor* gp) {
+ using Vertex = TextureGeometryProcessor::Vertex<Pos, D, AA>;
SkASSERT(gp->debugOnly_vertexStride() == sizeof(Vertex));
auto vertices = static_cast<Vertex*>(v);
- auto proxies = this->proxies();
- auto filters = this->filters();
+ auto origin = fProxy->origin();
+ const auto* texture = fProxy->peekTexture();
+ float iw = 1.f / texture->width();
+ float ih = 1.f / texture->height();
+
for (const auto& draw : fDraws) {
- auto textureIdx = draw.textureIdx();
- auto origin = proxies[textureIdx]->origin();
- tessellate_quad<Vertex>(draw.quad(), draw.srcRect(), draw.color(), origin,
- filters[textureIdx], vertices, iw[textureIdx], ih[textureIdx],
- textureIdx, draw.domain());
+ tessellate_quad<Vertex>(draw.quad(), draw.srcRect(), draw.color(), origin, fFilter,
+ vertices, iw, ih, draw.domain());
vertices += 4;
}
}
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]);
+ if (!fProxy->instantiate(target->resourceProvider())) {
+ return;
}
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());
+ fProxy->textureType(), fProxy->config(), fFilter,
+ std::move(fTextureColorSpaceXform), std::move(fPaintColorSpaceXform), coverageAA,
+ fPerspective, domain, *target->caps().shaderCaps());
GrPipeline::InitArgs args;
args.fProxy = target->proxy();
args.fCaps = &target->caps();
@@ -790,43 +648,34 @@
}
auto clip = target->detachAppliedClip();
- const auto* fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect());
+ auto* fixedDynamicState = target->allocFixedDynamicState(clip.scissorState().rect(), 1);
+ fixedDynamicState->fPrimitiveProcessorTextures[0] = fProxy;
const auto* pipeline =
target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), std::move(clip));
- using TessFn =
- decltype(&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kNo>);
-#define TESS_FN_AND_VERTEX_SIZE(Point, MT, Domain, AA) \
- { \
- &TextureOp::tess<Point, MT, Domain, AA>, \
- sizeof(TextureGeometryProcessor::Vertex<Point, MT, Domain, AA>) \
+ using TessFn = decltype(&TextureOp::tess<SkPoint, Domain::kNo, GrAA::kNo>);
+#define TESS_FN_AND_VERTEX_SIZE(Point, Domain, AA) \
+ { \
+ &TextureOp::tess<Point, Domain, AA>, \
+ sizeof(TextureGeometryProcessor::Vertex<Point, Domain, AA>) \
}
static constexpr struct {
TessFn fTessFn;
size_t fVertexSize;
} kTessFnsAndVertexSizes[] = {
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kYes, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kNo, Domain::kYes, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kNo, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kNo, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kYes, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint, MultiTexture::kYes, Domain::kYes, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kNo, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kNo, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kYes, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kNo, Domain::kYes, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kNo, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kNo, GrAA::kYes),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kYes, GrAA::kNo),
- TESS_FN_AND_VERTEX_SIZE(SkPoint3, MultiTexture::kYes, Domain::kYes, GrAA::kYes),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint, Domain::kNo, GrAA::kNo),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint, Domain::kNo, GrAA::kYes),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint, Domain::kYes, GrAA::kNo),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint, Domain::kYes, GrAA::kYes),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint3, Domain::kNo, GrAA::kNo),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint3, Domain::kNo, GrAA::kYes),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint3, Domain::kYes, GrAA::kNo),
+ TESS_FN_AND_VERTEX_SIZE(SkPoint3, Domain::kYes, GrAA::kYes),
};
#undef TESS_FN_AND_VERTEX_SIZE
int tessFnIdx = 0;
- tessFnIdx |= coverageAA ? 0x1 : 0x0;
- tessFnIdx |= fDomain ? 0x2 : 0x0;
- tessFnIdx |= (fProxyCnt > 1) ? 0x4 : 0x0;
- tessFnIdx |= fPerspective ? 0x8 : 0x0;
+ tessFnIdx |= coverageAA ? 0x1 : 0x0;
+ tessFnIdx |= fDomain ? 0x2 : 0x0;
+ tessFnIdx |= fPerspective ? 0x4 : 0x0;
SkASSERT(kTessFnsAndVertexSizes[tessFnIdx].fVertexSize == gp->debugOnly_vertexStride());
@@ -839,212 +688,75 @@
return;
}
- float iw[kMaxTextures];
- float ih[kMaxTextures];
- for (int t = 0; t < fProxyCnt; ++t) {
- const auto* texture = proxies[t]->peekTexture();
- iw[t] = 1.f / texture->width();
- ih[t] = 1.f / texture->height();
- }
-
- (this->*(kTessFnsAndVertexSizes[tessFnIdx].fTessFn))(vdata, iw, ih, gp.get());
+ (this->*(kTessFnsAndVertexSizes[tessFnIdx].fTessFn))(vdata, gp.get());
GrPrimitiveType primitiveType =
fDraws.count() > 1 ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleStrip;
- GrMesh mesh(primitiveType);
+ GrMesh* mesh = target->allocMesh(primitiveType);
if (fDraws.count() > 1) {
sk_sp<const GrBuffer> ibuffer = target->resourceProvider()->refQuadIndexBuffer();
if (!ibuffer) {
SkDebugf("Could not allocate quad indices\n");
return;
}
- mesh.setIndexedPatterned(ibuffer.get(), 6, 4, fDraws.count(),
- GrResourceProvider::QuadCountOfQuadBuffer());
+ mesh->setIndexedPatterned(ibuffer.get(), 6, 4, fDraws.count(),
+ GrResourceProvider::QuadCountOfQuadBuffer());
} else {
- mesh.setNonIndexedNonInstanced(4);
+ mesh->setNonIndexedNonInstanced(4);
}
- mesh.setVertexData(vbuffer, vstart);
- target->draw(gp.get(), pipeline, fixedDynamicState, mesh);
+ mesh->setVertexData(vbuffer, vstart);
+ target->draw(std::move(gp), pipeline, fixedDynamicState, mesh);
}
- bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
+ CombineResult onCombineIfPossible(GrOp* t, const GrCaps&) override {
const auto* that = t->cast<TextureOp>();
- const auto& shaderCaps = *caps.shaderCaps();
if (!GrColorSpaceXform::Equals(fTextureColorSpaceXform.get(),
that->fTextureColorSpaceXform.get())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (!GrColorSpaceXform::Equals(fPaintColorSpaceXform.get(),
that->fPaintColorSpaceXform.get())) {
- return false;
+ return CombineResult::kCannotCombine;
}
if (this->aaType() != that->aaType()) {
- return false;
+ return CombineResult::kCannotCombine;
}
- // Because of an issue where GrColorSpaceXform adds the same function every time it is used
- // in a texture lookup, we only allow multiple textures when there is no transform.
- if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) &&
- !fTextureColorSpaceXform &&
- fMaxApproxDstPixelArea <= shaderCaps.disableImageMultitexturingDstRectAreaThreshold() &&
- that->fMaxApproxDstPixelArea <=
- shaderCaps.disableImageMultitexturingDstRectAreaThreshold()) {
- int map[kMaxTextures];
- int numNewProxies = this->mergeProxies(that, map, shaderCaps);
- if (numNewProxies < 0) {
- return false;
- }
- if (1 == fProxyCnt && numNewProxies) {
- void* mem = new char[(sizeof(GrSamplerState::Filter) + sizeof(GrTextureProxy*)) *
- kMaxTextures];
- auto proxies = reinterpret_cast<GrTextureProxy**>(mem);
- auto filters = reinterpret_cast<GrSamplerState::Filter*>(proxies + kMaxTextures);
- proxies[0] = fProxy0;
- filters[0] = fFilter0;
- fProxyArray = proxies;
- }
- fProxyCnt += numNewProxies;
- auto thisProxies = fProxyArray;
- auto thatProxies = that->proxies();
- auto thatFilters = that->filters();
- auto thisFilters = reinterpret_cast<GrSamplerState::Filter*>(thisProxies +
- kMaxTextures);
- for (int i = 0; i < that->fProxyCnt; ++i) {
- if (map[i] < 0) {
- thatProxies[i]->addPendingRead();
-
- thisProxies[-map[i]] = thatProxies[i];
- thisFilters[-map[i]] = thatFilters[i];
- map[i] = -map[i];
- }
- }
- int firstNewDraw = fDraws.count();
- fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
- for (int i = firstNewDraw; i < fDraws.count(); ++i) {
- fDraws[i].setTextureIdx(map[fDraws[i].textureIdx()]);
- }
- } else {
- // We can get here when one of the ops is already multitextured but the other cannot
- // be because of the dst rect size.
- if (fProxyCnt > 1 || that->fProxyCnt > 1) {
- return false;
- }
- if (fProxy0->uniqueID() != that->fProxy0->uniqueID() || fFilter0 != that->fFilter0) {
- return false;
- }
- fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
+ if (fProxy->uniqueID() != that->fProxy->uniqueID() || fFilter != that->fFilter) {
+ return CombineResult::kCannotCombine;
}
+ fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
this->joinBounds(*that);
- fMaxApproxDstPixelArea = SkTMax(that->fMaxApproxDstPixelArea, fMaxApproxDstPixelArea);
fPerspective |= that->fPerspective;
fDomain |= that->fDomain;
- return true;
- }
-
- /**
- * Determines a mapping of indices from that's proxy array to this's proxy array. A negative map
- * value means that's proxy should be added to this's proxy array at the absolute value of
- * the map entry. If it is determined that the ops shouldn't combine their proxies then a
- * negative value is returned. Otherwise, return value indicates the number of proxies that have
- * to be added to this op or, equivalently, the number of negative entries in map.
- */
- int mergeProxies(const TextureOp* that, int map[kMaxTextures], const GrShaderCaps& caps) const {
- std::fill_n(map, kMaxTextures, -kMaxTextures);
- int sharedProxyCnt = 0;
- auto thisProxies = this->proxies();
- auto thisFilters = this->filters();
- auto thatProxies = that->proxies();
- auto thatFilters = that->filters();
- for (int i = 0; i < fProxyCnt; ++i) {
- for (int j = 0; j < that->fProxyCnt; ++j) {
- if (thisProxies[i]->uniqueID() == thatProxies[j]->uniqueID()) {
- if (thisFilters[i] != thatFilters[j]) {
- // In GL we don't currently support using the same texture with different
- // samplers. If we added support for sampler objects and a cap bit to know
- // it's ok to use different filter modes then we could support this.
- // Otherwise, we could also only allow a single filter mode for each op
- // instance.
- return -1;
- }
- map[j] = i;
- ++sharedProxyCnt;
- break;
- }
- }
- }
- int actualMaxTextures = SkTMin(caps.maxFragmentSamplers(), kMaxTextures);
- int newProxyCnt = that->fProxyCnt - sharedProxyCnt;
- if (newProxyCnt + fProxyCnt > actualMaxTextures) {
- return -1;
- }
- GrPixelConfig config = thisProxies[0]->config();
- int nextSlot = fProxyCnt;
- for (int j = 0; j < that->fProxyCnt; ++j) {
- // We want to avoid making many shaders because of different permutations of shader
- // based swizzle and sampler types. The approach taken here is to require the configs to
- // be the same and to only allow already instantiated proxies that have the most
- // common sampler type. Otherwise we don't merge.
- if (thatProxies[j]->config() != config) {
- return -1;
- }
- if (GrTexture* tex = thatProxies[j]->peekTexture()) {
- if (tex->texturePriv().textureType() != GrTextureType::k2D) {
- return -1;
- }
- }
- if (map[j] < 0) {
- map[j] = -(nextSlot++);
- }
- }
- return newProxyCnt;
+ return CombineResult::kMerged;
}
GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
- GrTextureProxy* const* proxies() const { return fProxyCnt > 1 ? fProxyArray : &fProxy0; }
-
- const GrSamplerState::Filter* filters() const {
- if (fProxyCnt > 1) {
- return reinterpret_cast<const GrSamplerState::Filter*>(fProxyArray + kMaxTextures);
- }
- return &fFilter0;
- }
-
class Draw {
public:
- Draw(const SkRect& srcRect, int textureIdx, const GrPerspQuad& quad,
- SkCanvas::SrcRectConstraint constraint, GrColor color)
+ Draw(const SkRect& srcRect, const GrPerspQuad& quad, SkCanvas::SrcRectConstraint constraint,
+ GrColor color)
: fSrcRect(srcRect)
- , fHasDomain(constraint == SkCanvas::kStrict_SrcRectConstraint)
- , fTextureIdx(SkToUInt(textureIdx))
, fQuad(quad)
- , fColor(color) {}
+ , fColor(color)
+ , fHasDomain(constraint == SkCanvas::kStrict_SrcRectConstraint) {}
const GrPerspQuad& quad() const { return fQuad; }
- int textureIdx() const { return SkToInt(fTextureIdx); }
const SkRect& srcRect() const { return fSrcRect; }
GrColor color() const { return fColor; }
Domain domain() const { return Domain(fHasDomain); }
- void setTextureIdx(int i) { fTextureIdx = SkToUInt(i); }
private:
SkRect fSrcRect;
- unsigned fHasDomain : 1;
- unsigned fTextureIdx : 31;
GrPerspQuad fQuad;
GrColor fColor;
+ bool fHasDomain;
};
SkSTArray<1, Draw, true> fDraws;
sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
sk_sp<GrColorSpaceXform> fPaintColorSpaceXform;
- // Initially we store a single proxy ptr and a single filter. If we grow to have more than
- // one proxy we instead store pointers to dynamically allocated arrays of size kMaxTextures
- // followed by kMaxTextures filters.
- union {
- GrTextureProxy* fProxy0;
- GrTextureProxy** fProxyArray;
- };
- size_t fMaxApproxDstPixelArea;
- GrSamplerState::Filter fFilter0;
- uint8_t fProxyCnt;
+ GrTextureProxy* fProxy;
+ GrSamplerState::Filter fFilter;
unsigned fAAType : 2;
unsigned fPerspective : 1;
unsigned fDomain : 1;
@@ -1054,9 +766,6 @@
typedef GrMeshDrawOp INHERITED;
};
-constexpr int TextureGeometryProcessor::kMaxTextures;
-constexpr int TextureOp::kMaxTextures;
-
} // anonymous namespace
namespace GrTextureOp {
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);