Add a custom GP for GrDrawVerticesOp

That op only used a few features of the default geometry
processor. It was also the only user of SkColor vertex
colors (and the accompanying color space xform).

In GrDrawVerticesOp, this gets rid of flags entirely, and
uses tri-state enums for both local coords and colors.
We used to have a mix of flags, state inferred from other
fields, and explicit fields. I think the new single
representation simplifies the logic.

Change-Id: I9802585d99a71ca50399f5862489d4f2bd8c5052
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/277470
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Brian Osman 2020-03-18 14:25:45 -04:00 committed by Skia Commit-Bot
parent fb27c9a25f
commit 8370fd1267
4 changed files with 255 additions and 155 deletions

View File

@ -10,7 +10,6 @@
#include "include/core/SkRefCnt.h" #include "include/core/SkRefCnt.h"
#include "src/core/SkArenaAlloc.h" #include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrCaps.h" #include "src/gpu/GrCaps.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h" #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h" #include "src/gpu/glsl/GrGLSLUniformHandler.h"
@ -25,11 +24,10 @@
enum GPFlag { enum GPFlag {
kColorAttribute_GPFlag = 0x1, kColorAttribute_GPFlag = 0x1,
kColorAttributeIsSkColor_GPFlag = 0x2, kColorAttributeIsWide_GPFlag = 0x2,
kColorAttributeIsWide_GPFlag = 0x4, kLocalCoordAttribute_GPFlag = 0x4,
kLocalCoordAttribute_GPFlag = 0x8, kCoverageAttribute_GPFlag = 0x8,
kCoverageAttribute_GPFlag = 0x10, kCoverageAttributeTweak_GPFlag = 0x10,
kCoverageAttributeTweak_GPFlag = 0x20,
}; };
class DefaultGeoProc : public GrGeometryProcessor { class DefaultGeoProc : public GrGeometryProcessor {
@ -37,13 +35,11 @@ public:
static GrGeometryProcessor* Make(SkArenaAlloc* arena, static GrGeometryProcessor* Make(SkArenaAlloc* arena,
uint32_t gpTypeFlags, uint32_t gpTypeFlags,
const SkPMColor4f& color, const SkPMColor4f& color,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& viewMatrix, const SkMatrix& viewMatrix,
const SkMatrix& localMatrix, const SkMatrix& localMatrix,
bool localCoordsWillBeRead, bool localCoordsWillBeRead,
uint8_t coverage) { uint8_t coverage) {
return arena->make<DefaultGeoProc>(gpTypeFlags, color, std::move(colorSpaceXform), return arena->make<DefaultGeoProc>(gpTypeFlags, color, viewMatrix, localMatrix, coverage,
viewMatrix, localMatrix, coverage,
localCoordsWillBeRead); localCoordsWillBeRead);
} }
@ -82,8 +78,7 @@ public:
GrGLSLVarying varying(kHalf4_GrSLType); GrGLSLVarying varying(kHalf4_GrSLType);
varyingHandler->addVarying("color", &varying); varyingHandler->addVarying("color", &varying);
// There are several optional steps to process the color. Start with the attribute, // Start with the attribute or with uniform color
// or with uniform color (in the case of folding coverage into a uniform color):
if (gp.hasVertexColor()) { if (gp.hasVertexColor()) {
vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name()); vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
} else { } else {
@ -95,22 +90,6 @@ public:
vertBuilder->codeAppendf("half4 color = %s;", colorUniformName); vertBuilder->codeAppendf("half4 color = %s;", colorUniformName);
} }
// For SkColor, do a red/blue swap, possible color space conversion, and premul
if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
vertBuilder->codeAppend("color = color.bgra;");
if (gp.fColorSpaceXform) {
fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
kVertex_GrShaderFlag);
SkString xformedColor;
vertBuilder->appendColorGamutXform(&xformedColor, "color",
&fColorSpaceHelper);
vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
}
vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
}
// Optionally fold coverage into alpha (color). // Optionally fold coverage into alpha (color).
if (tweakAlpha) { if (tweakAlpha) {
vertBuilder->codeAppendf("color = color * %s;", gp.fInCoverage.name()); vertBuilder->codeAppendf("color = color * %s;", gp.fInCoverage.name());
@ -130,23 +109,15 @@ public:
gp.viewMatrix(), gp.viewMatrix(),
&fViewMatrixUniform); &fViewMatrixUniform);
if (gp.fInLocalCoords.isInitialized()) { // emit transforms using either explicit local coords or positions
// emit transforms with explicit local coords const auto& coordsAttr = gp.fInLocalCoords.isInitialized() ? gp.fInLocalCoords
this->emitTransforms(vertBuilder, : gp.fInPosition;
varyingHandler, this->emitTransforms(vertBuilder,
uniformHandler, varyingHandler,
gp.fInLocalCoords.asShaderVar(), uniformHandler,
gp.localMatrix(), coordsAttr.asShaderVar(),
args.fFPCoordTransformHandler); gp.localMatrix(),
} else { args.fFPCoordTransformHandler);
// emit transforms with position
this->emitTransforms(vertBuilder,
varyingHandler,
uniformHandler,
gp.fInPosition.asShaderVar(),
gp.localMatrix(),
args.fFPCoordTransformHandler);
}
// Setup coverage as pass through // Setup coverage as pass through
if (gp.hasVertexCoverage() && !tweakAlpha) { if (gp.hasVertexCoverage() && !tweakAlpha) {
@ -174,7 +145,6 @@ public:
key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x100 : 0; key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x100 : 0;
key |= ComputePosKey(def.viewMatrix()) << 20; key |= ComputePosKey(def.viewMatrix()) << 20;
b->add32(key); b->add32(key);
b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get()));
} }
void setData(const GrGLSLProgramDataManager& pdman, void setData(const GrGLSLProgramDataManager& pdman,
@ -199,8 +169,6 @@ public:
fCoverage = dgp.coverage(); fCoverage = dgp.coverage();
} }
this->setTransformDataHelper(dgp.fLocalMatrix, pdman, transformRange); this->setTransformDataHelper(dgp.fLocalMatrix, pdman, transformRange);
fColorSpaceHelper.setData(pdman, dgp.fColorSpaceXform.get());
} }
private: private:
@ -210,7 +178,6 @@ public:
UniformHandle fViewMatrixUniform; UniformHandle fViewMatrixUniform;
UniformHandle fColorUniform; UniformHandle fColorUniform;
UniformHandle fCoverageUniform; UniformHandle fCoverageUniform;
GrGLSLColorSpaceXformHelper fColorSpaceHelper;
typedef GrGLSLGeometryProcessor INHERITED; typedef GrGLSLGeometryProcessor INHERITED;
}; };
@ -228,7 +195,6 @@ private:
DefaultGeoProc(uint32_t gpTypeFlags, DefaultGeoProc(uint32_t gpTypeFlags,
const SkPMColor4f& color, const SkPMColor4f& color,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& viewMatrix, const SkMatrix& viewMatrix,
const SkMatrix& localMatrix, const SkMatrix& localMatrix,
uint8_t coverage, uint8_t coverage,
@ -239,8 +205,7 @@ private:
, fLocalMatrix(localMatrix) , fLocalMatrix(localMatrix)
, fCoverage(coverage) , fCoverage(coverage)
, fFlags(gpTypeFlags) , fFlags(gpTypeFlags)
, fLocalCoordsWillBeRead(localCoordsWillBeRead) , fLocalCoordsWillBeRead(localCoordsWillBeRead) {
, fColorSpaceXform(std::move(colorSpaceXform)) {
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType}; fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
if (fFlags & kColorAttribute_GPFlag) { if (fFlags & kColorAttribute_GPFlag) {
fInColor = MakeColorAttribute("inColor", fInColor = MakeColorAttribute("inColor",
@ -266,7 +231,6 @@ private:
uint8_t fCoverage; uint8_t fCoverage;
uint32_t fFlags; uint32_t fFlags;
bool fLocalCoordsWillBeRead; bool fLocalCoordsWillBeRead;
sk_sp<GrColorSpaceXform> fColorSpaceXform;
GR_DECLARE_GEOMETRY_PROCESSOR_TEST GR_DECLARE_GEOMETRY_PROCESSOR_TEST
@ -281,9 +245,6 @@ GrGeometryProcessor* DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
if (d->fRandom->nextBool()) { if (d->fRandom->nextBool()) {
flags |= kColorAttribute_GPFlag; flags |= kColorAttribute_GPFlag;
} }
if (d->fRandom->nextBool()) {
flags |= kColorAttributeIsSkColor_GPFlag;
}
if (d->fRandom->nextBool()) { if (d->fRandom->nextBool()) {
flags |= kColorAttributeIsWide_GPFlag; flags |= kColorAttributeIsWide_GPFlag;
} }
@ -300,7 +261,6 @@ GrGeometryProcessor* DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
return DefaultGeoProc::Make(d->allocator(), return DefaultGeoProc::Make(d->allocator(),
flags, flags,
SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
GrTest::TestColorXform(d->fRandom),
GrTest::TestMatrix(d->fRandom), GrTest::TestMatrix(d->fRandom),
GrTest::TestMatrix(d->fRandom), GrTest::TestMatrix(d->fRandom),
d->fRandom->nextBool(), d->fRandom->nextBool(),
@ -316,8 +276,6 @@ GrGeometryProcessor* GrDefaultGeoProcFactory::Make(SkArenaAlloc* arena,
uint32_t flags = 0; uint32_t flags = 0;
if (Color::kPremulGrColorAttribute_Type == color.fType) { if (Color::kPremulGrColorAttribute_Type == color.fType) {
flags |= kColorAttribute_GPFlag; flags |= kColorAttribute_GPFlag;
} else if (Color::kUnpremulSkColorAttribute_Type == color.fType) {
flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag;
} else if (Color::kPremulWideColorAttribute_Type == color.fType) { } else if (Color::kPremulWideColorAttribute_Type == color.fType) {
flags |= kColorAttribute_GPFlag | kColorAttributeIsWide_GPFlag; flags |= kColorAttribute_GPFlag | kColorAttributeIsWide_GPFlag;
} }
@ -334,7 +292,6 @@ GrGeometryProcessor* GrDefaultGeoProcFactory::Make(SkArenaAlloc* arena,
return DefaultGeoProc::Make(arena, return DefaultGeoProc::Make(arena,
flags, flags,
color.fColor, color.fColor,
color.fColorSpaceXform,
viewMatrix, viewMatrix,
localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
localCoordsWillBeRead, localCoordsWillBeRead,

View File

@ -8,7 +8,6 @@
#ifndef GrDefaultGeoProcFactory_DEFINED #ifndef GrDefaultGeoProcFactory_DEFINED
#define GrDefaultGeoProcFactory_DEFINED #define GrDefaultGeoProcFactory_DEFINED
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrGeometryProcessor.h" #include "src/gpu/GrGeometryProcessor.h"
/* /*
@ -21,25 +20,18 @@ namespace GrDefaultGeoProcFactory {
kPremulGrColorUniform_Type, kPremulGrColorUniform_Type,
kPremulGrColorAttribute_Type, kPremulGrColorAttribute_Type,
kPremulWideColorAttribute_Type, kPremulWideColorAttribute_Type,
kUnpremulSkColorAttribute_Type,
}; };
explicit Color(const SkPMColor4f& color) explicit Color(const SkPMColor4f& color)
: fType(kPremulGrColorUniform_Type) : fType(kPremulGrColorUniform_Type)
, fColor(color) , fColor(color) {}
, fColorSpaceXform(nullptr) {}
Color(Type type) Color(Type type)
: fType(type) : fType(type)
, fColor(SK_PMColor4fILLEGAL) , fColor(SK_PMColor4fILLEGAL) {
, fColorSpaceXform(nullptr) {
SkASSERT(type != kPremulGrColorUniform_Type); SkASSERT(type != kPremulGrColorUniform_Type);
} }
Type fType; Type fType;
SkPMColor4f fColor; SkPMColor4f fColor;
// This only applies to SkColor. Any GrColors are assumed to have been color converted
// during paint conversion.
sk_sp<GrColorSpaceXform> fColorSpaceXform;
}; };
struct Coverage { struct Coverage {
@ -63,7 +55,6 @@ namespace GrDefaultGeoProcFactory {
kUnused_Type, kUnused_Type,
kUsePosition_Type, kUsePosition_Type,
kHasExplicit_Type, kHasExplicit_Type,
kHasTransformed_Type,
}; };
LocalCoords(Type type) : fType(type), fMatrix(nullptr) {} LocalCoords(Type type) : fType(type), fMatrix(nullptr) {}
LocalCoords(Type type, const SkMatrix* matrix) : fType(type), fMatrix(matrix) { LocalCoords(Type type, const SkMatrix* matrix) : fType(type), fMatrix(matrix) {

View File

@ -171,6 +171,7 @@ public:
kMappedNormalsFP_ClassID, kMappedNormalsFP_ClassID,
kLightingFP_ClassID, kLightingFP_ClassID,
kLinearStrokeProcessor_ClassID, kLinearStrokeProcessor_ClassID,
kVerticesGP_ClassID,
}; };
virtual ~GrProcessor() = default; virtual ~GrProcessor() = default;

View File

@ -5,19 +5,204 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "src/core/SkRectPriv.h" #include "src/core/SkArenaAlloc.h"
#include "src/core/SkVerticesPriv.h" #include "src/core/SkVerticesPriv.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrVertexWriter.h" #include "src/gpu/GrVertexWriter.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ops/GrDrawVerticesOp.h" #include "src/gpu/ops/GrDrawVerticesOp.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h" #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
namespace { namespace {
enum class ColorArrayType {
kUnused,
kPremulGrColor,
kSkColor,
};
enum class LocalCoordsType {
kUnused,
kUsePosition,
kExplicit,
};
class VerticesGP : public GrGeometryProcessor {
public:
static GrGeometryProcessor* Make(SkArenaAlloc* arena,
LocalCoordsType localCoordsType,
ColorArrayType colorArrayType,
const SkPMColor4f& color,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& viewMatrix) {
return arena->make<VerticesGP>(localCoordsType, colorArrayType, color,
std::move(colorSpaceXform), viewMatrix);
}
const char* name() const override { return "VerticesGP"; }
const SkPMColor4f& color() const { return fColor; }
bool hasVertexColor() const { return fInColor.isInitialized(); }
const SkMatrix& viewMatrix() const { return fViewMatrix; }
class GLSLProcessor : public GrGLSLGeometryProcessor {
public:
GLSLProcessor()
: fViewMatrix(SkMatrix::InvalidMatrix())
, fColor(SK_PMColor4fILLEGAL) {}
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const VerticesGP& gp = args.fGP.cast<VerticesGP>();
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
// emit attributes
varyingHandler->emitAttributes(gp);
// Setup pass through color
if (gp.hasVertexColor()) {
GrGLSLVarying varying(kHalf4_GrSLType);
varyingHandler->addVarying("color", &varying);
vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
// For SkColor, do a red/blue swap, possible color space conversion, and premul
if (gp.fColorArrayType == ColorArrayType::kSkColor) {
vertBuilder->codeAppend("color = color.bgra;");
if (gp.fColorSpaceXform) {
fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
kVertex_GrShaderFlag);
SkString xformedColor;
vertBuilder->appendColorGamutXform(&xformedColor, "color",
&fColorSpaceHelper);
vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
}
vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
}
vertBuilder->codeAppendf("%s = color;\n", varying.vsOut());
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
} else {
this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
&fColorUniform);
}
// Setup position
this->writeOutputPosition(vertBuilder,
uniformHandler,
gpArgs,
gp.fInPosition.name(),
gp.viewMatrix(),
&fViewMatrixUniform);
// emit transforms using either explicit local coords or positions
const auto& coordsAttr = gp.fInLocalCoords.isInitialized() ? gp.fInLocalCoords
: gp.fInPosition;
this->emitTransforms(vertBuilder,
varyingHandler,
uniformHandler,
coordsAttr.asShaderVar(),
SkMatrix::I(),
args.fFPCoordTransformHandler);
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}
static inline void GenKey(const GrGeometryProcessor& gp,
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
const VerticesGP& vgp = gp.cast<VerticesGP>();
uint32_t key = 0;
key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
key |= ComputePosKey(vgp.viewMatrix()) << 20;
b->add32(key);
b->add32(GrColorSpaceXform::XformKey(vgp.fColorSpaceXform.get()));
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp,
const CoordTransformRange& transformRange) override {
const VerticesGP& vgp = gp.cast<VerticesGP>();
if (!vgp.viewMatrix().isIdentity() &&
!SkMatrixPriv::CheapEqual(fViewMatrix, vgp.viewMatrix())) {
fViewMatrix = vgp.viewMatrix();
pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
}
if (!vgp.hasVertexColor() && vgp.color() != fColor) {
pdman.set4fv(fColorUniform, 1, vgp.color().vec());
fColor = vgp.color();
}
this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
fColorSpaceHelper.setData(pdman, vgp.fColorSpaceXform.get());
}
private:
SkMatrix fViewMatrix;
SkPMColor4f fColor;
UniformHandle fViewMatrixUniform;
UniformHandle fColorUniform;
GrGLSLColorSpaceXformHelper fColorSpaceHelper;
typedef GrGLSLGeometryProcessor INHERITED;
};
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
GLSLProcessor::GenKey(*this, caps, b);
}
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
return new GLSLProcessor();
}
private:
friend class ::SkArenaAlloc; // for access to ctor
VerticesGP(LocalCoordsType localCoordsType,
ColorArrayType colorArrayType,
const SkPMColor4f& color,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& viewMatrix)
: INHERITED(kVerticesGP_ClassID)
, fColorArrayType(colorArrayType)
, fColor(color)
, fViewMatrix(viewMatrix)
, fColorSpaceXform(std::move(colorSpaceXform)) {
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
if (fColorArrayType != ColorArrayType::kUnused) {
constexpr bool wideColor = false;
fInColor = MakeColorAttribute("inColor", wideColor);
}
if (localCoordsType == LocalCoordsType::kExplicit) {
fInLocalCoords = {"inLocalCoord", kFloat2_GrVertexAttribType,
kFloat2_GrSLType};
}
this->setVertexAttributes(&fInPosition, 3);
}
Attribute fInPosition;
Attribute fInColor;
Attribute fInLocalCoords;
ColorArrayType fColorArrayType;
SkPMColor4f fColor;
SkMatrix fViewMatrix;
sk_sp<GrColorSpaceXform> fColorSpaceXform;
typedef GrGeometryProcessor INHERITED;
};
class DrawVerticesOp final : public GrMeshDrawOp { class DrawVerticesOp final : public GrMeshDrawOp {
private: private:
using Helper = GrSimpleMeshDrawOpHelper; using Helper = GrSimpleMeshDrawOpHelper;
@ -48,11 +233,6 @@ public:
bool hasMixedSampledCoverage, GrClampType) override; bool hasMixedSampledCoverage, GrClampType) override;
private: private:
enum class ColorArrayType {
kPremulGrColor,
kSkColor,
};
GrProgramInfo* programInfo() override { return fProgramInfo; } GrProgramInfo* programInfo() override { return fProgramInfo; }
void onCreateProgramInfo(const GrCaps*, void onCreateProgramInfo(const GrCaps*,
@ -79,13 +259,8 @@ private:
SkPMColor4f fColor; // Used if this->hasPerVertexColors() is false. SkPMColor4f fColor; // Used if this->hasPerVertexColors() is false.
sk_sp<SkVertices> fVertices; sk_sp<SkVertices> fVertices;
SkMatrix fViewMatrix; SkMatrix fViewMatrix;
bool fIgnoreTexCoords;
bool fIgnoreColors; bool fIgnoreColors;
bool hasExplicitLocalCoords() const {
return SkVerticesPriv::HasTexCoords(fVertices.get()) && !fIgnoreTexCoords;
}
bool hasPerVertexColors() const { bool hasPerVertexColors() const {
return SkVerticesPriv::HasColors(fVertices.get()) && !fIgnoreColors; return SkVerticesPriv::HasColors(fVertices.get()) && !fIgnoreColors;
} }
@ -97,33 +272,11 @@ private:
} }
bool requiresPerVertexColors() const { bool requiresPerVertexColors() const {
return SkToBool(kRequiresPerVertexColors_Flag & fFlags); return fColorArrayType != ColorArrayType::kUnused;
}
bool anyMeshHasExplicitLocalCoords() const {
return SkToBool(kAnyMeshHasExplicitLocalCoords_Flag & fFlags);
}
GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType() const {
if (fHelper.usesLocalCoords()) {
// If we have multiple view matrices we will transform the positions into device space.
// We must then also provide untransformed positions as local coords.
if (this->anyMeshHasExplicitLocalCoords() || this->hasMultipleViewMatrices()) {
return GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type;
} else {
return GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type;
}
} else {
return GrDefaultGeoProcFactory::LocalCoords::kUnused_Type;
}
} }
bool requiresPerVertexLocalCoords() const { bool requiresPerVertexLocalCoords() const {
return this->localCoordsType() == GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type; return fLocalCoordsType == LocalCoordsType::kExplicit;
}
bool hasMultipleViewMatrices() const {
return SkToBool(kHasMultipleViewMatrices_Flag & fFlags);
} }
size_t vertexStride() const { size_t vertexStride() const {
@ -132,20 +285,15 @@ private:
(this->requiresPerVertexLocalCoords() ? sizeof(SkPoint) : 0); (this->requiresPerVertexLocalCoords() ? sizeof(SkPoint) : 0);
} }
enum Flags {
kRequiresPerVertexColors_Flag = 0x1,
kAnyMeshHasExplicitLocalCoords_Flag = 0x2,
kHasMultipleViewMatrices_Flag = 0x4,
};
Helper fHelper; Helper fHelper;
SkSTArray<1, Mesh, true> fMeshes; SkSTArray<1, Mesh, true> fMeshes;
// GrPrimitiveType is more expressive than fVertices.mode() so it is used instead and we ignore // GrPrimitiveType is more expressive than fVertices.mode() so it is used instead and we ignore
// the SkVertices mode (though fPrimitiveType may have been inferred from it). // the SkVertices mode (though fPrimitiveType may have been inferred from it).
GrPrimitiveType fPrimitiveType; GrPrimitiveType fPrimitiveType;
uint32_t fFlags;
int fVertexCount; int fVertexCount;
int fIndexCount; int fIndexCount;
bool fMultipleViewMatrices;
LocalCoordsType fLocalCoordsType;
ColorArrayType fColorArrayType; ColorArrayType fColorArrayType;
sk_sp<GrColorSpaceXform> fColorSpaceXform; sk_sp<GrColorSpaceXform> fColorSpaceXform;
@ -162,6 +310,7 @@ DrawVerticesOp::DrawVerticesOp(const Helper::MakeArgs& helperArgs, const SkPMCol
: INHERITED(ClassID()) : INHERITED(ClassID())
, fHelper(helperArgs, aaType) , fHelper(helperArgs, aaType)
, fPrimitiveType(primitiveType) , fPrimitiveType(primitiveType)
, fMultipleViewMatrices(false)
, fColorSpaceXform(std::move(colorSpaceXform)) { , fColorSpaceXform(std::move(colorSpaceXform)) {
SkASSERT(vertices); SkASSERT(vertices);
@ -171,23 +320,16 @@ DrawVerticesOp::DrawVerticesOp(const Helper::MakeArgs& helperArgs, const SkPMCol
fVertexCount = info.fVertexCount; fVertexCount = info.fVertexCount;
fIndexCount = info.fIndexCount; fIndexCount = info.fIndexCount;
fColorArrayType = info.hasColors() ? ColorArrayType::kSkColor fColorArrayType = info.hasColors() ? ColorArrayType::kSkColor
: ColorArrayType::kPremulGrColor; : ColorArrayType::kUnused;
fLocalCoordsType = info.hasTexCoords() ? LocalCoordsType::kExplicit
: LocalCoordsType::kUsePosition;
Mesh& mesh = fMeshes.push_back(); Mesh& mesh = fMeshes.push_back();
mesh.fColor = color; mesh.fColor = color;
mesh.fViewMatrix = viewMatrix; mesh.fViewMatrix = viewMatrix;
mesh.fVertices = std::move(vertices); mesh.fVertices = std::move(vertices);
mesh.fIgnoreTexCoords = false;
mesh.fIgnoreColors = false; mesh.fIgnoreColors = false;
fFlags = 0;
if (mesh.hasPerVertexColors()) {
fFlags |= kRequiresPerVertexColors_Flag;
}
if (mesh.hasExplicitLocalCoords()) {
fFlags |= kAnyMeshHasExplicitLocalCoords_Flag;
}
IsHairline zeroArea; IsHairline zeroArea;
if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) { if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
zeroArea = IsHairline::kYes; zeroArea = IsHairline::kYes;
@ -229,33 +371,22 @@ GrProcessorSet::Analysis DrawVerticesOp::finalize(
GrProcessorAnalysisCoverage::kNone, &gpColor); GrProcessorAnalysisCoverage::kNone, &gpColor);
if (gpColor.isConstant(&fMeshes.front().fColor)) { if (gpColor.isConstant(&fMeshes.front().fColor)) {
fMeshes.front().fIgnoreColors = true; fMeshes.front().fIgnoreColors = true;
fFlags &= ~kRequiresPerVertexColors_Flag; fColorArrayType = ColorArrayType::kUnused;
fColorArrayType = ColorArrayType::kPremulGrColor;
} }
if (!fHelper.usesLocalCoords()) { if (!fHelper.usesLocalCoords()) {
fMeshes[0].fIgnoreTexCoords = true; fLocalCoordsType = LocalCoordsType::kUnused;
fFlags &= ~kAnyMeshHasExplicitLocalCoords_Flag;
} }
return result; return result;
} }
GrGeometryProcessor* DrawVerticesOp::makeGP(SkArenaAlloc* arena) { GrGeometryProcessor* DrawVerticesOp::makeGP(SkArenaAlloc* arena) {
using namespace GrDefaultGeoProcFactory; sk_sp<GrColorSpaceXform> csxform =
fColorArrayType == ColorArrayType::kSkColor ? fColorSpaceXform : nullptr;
Color color(fMeshes[0].fColor); const SkMatrix& vm = fMultipleViewMatrices ? SkMatrix::I() : fMeshes[0].fViewMatrix;
if (this->requiresPerVertexColors()) {
if (fColorArrayType == ColorArrayType::kPremulGrColor) {
color.fType = Color::kPremulGrColorAttribute_Type;
} else {
color.fType = Color::kUnpremulSkColorAttribute_Type;
color.fColorSpaceXform = fColorSpaceXform;
}
}
const SkMatrix& vm = this->hasMultipleViewMatrices() ? SkMatrix::I() : fMeshes[0].fViewMatrix; auto gp = VerticesGP::Make(arena, fLocalCoordsType, fColorArrayType, fMeshes[0].fColor,
std::move(csxform), vm);
auto gp = GrDefaultGeoProcFactory::Make(arena, color, Coverage::kSolid_Type,
this->localCoordsType(), vm);
SkASSERT(this->vertexStride() == gp->vertexStride()); SkASSERT(this->vertexStride() == gp->vertexStride());
return gp; return gp;
} }
@ -313,8 +444,7 @@ void DrawVerticesOp::onPrepareDraws(Target* target) {
int vertexCount = info.fVertexCount; int vertexCount = info.fVertexCount;
const SkPoint* positions = info.fPositions; const SkPoint* positions = info.fPositions;
const SkColor* colors = info.fColors; const SkColor* colors = info.fColors;
const SkPoint* localCoords = const SkPoint* localCoords = info.fTexCoords ? info.fTexCoords : positions;
mesh.hasExplicitLocalCoords() ? info.fTexCoords : positions;
// TODO4F: Preserve float colors // TODO4F: Preserve float colors
GrColor meshColor = mesh.fColor.toBytes_RGBA(); GrColor meshColor = mesh.fColor.toBytes_RGBA();
@ -331,7 +461,7 @@ void DrawVerticesOp::onPrepareDraws(Target* target) {
} }
} }
if (this->hasMultipleViewMatrices()) { if (fMultipleViewMatrices) {
SkMatrixPriv::MapPointsWithStride(mesh.fViewMatrix, posBase, vertexStride, vertexCount); SkMatrixPriv::MapPointsWithStride(mesh.fViewMatrix, posBase, vertexStride, vertexCount);
} }
@ -378,28 +508,49 @@ GrOp::CombineResult DrawVerticesOp::onCombineIfPossible(GrOp* t, GrRecordingCont
return CombineResult::kCannotCombine; return CombineResult::kCannotCombine;
} }
if (fColorArrayType != that->fColorArrayType) { if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) {
return CombineResult::kCannotCombine; return CombineResult::kCannotCombine;
} }
if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) { // We can't mix draws that use SkColor vertex colors with those that don't. We can mix uniform
// color draws with GrColor draws (by expanding the uniform color into vertex color).
if ((fColorArrayType == ColorArrayType::kSkColor) !=
(that->fColorArrayType == ColorArrayType::kSkColor)) {
return CombineResult::kCannotCombine; return CombineResult::kCannotCombine;
} }
// If the other op already required per-vertex colors, the combined mesh does.
if (that->fColorArrayType == ColorArrayType::kPremulGrColor) {
fColorArrayType = ColorArrayType::kPremulGrColor;
}
// If we combine meshes with different (uniform) colors, switch to per-vertex colors.
if (fColorArrayType == ColorArrayType::kUnused) {
SkASSERT(that->fColorArrayType == ColorArrayType::kUnused);
if (this->fMeshes[0].fColor != that->fMeshes[0].fColor) {
fColorArrayType = ColorArrayType::kPremulGrColor;
}
}
// NOTE: For SkColor vertex colors, the source color space is always sRGB, and the destination // NOTE: For SkColor vertex colors, the source color space is always sRGB, and the destination
// gamut is determined by the render target context. A mis-match should be impossible. // gamut is determined by the render target context. A mis-match should be impossible.
SkASSERT(GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())); SkASSERT(GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get()));
// If either op required explicit local coords or per-vertex colors the combined mesh does. // If we're acquiring a mesh with a different view matrix, or an op that needed multiple view
// Same with multiple view matrices. // matrices, we need multiple view matrices.
fFlags |= that->fFlags; fMultipleViewMatrices =
fMultipleViewMatrices || that->fMultipleViewMatrices ||
!SkMatrixPriv::CheapEqual(this->fMeshes[0].fViewMatrix, that->fMeshes[0].fViewMatrix);
if (this->fMeshes[0].fColor != that->fMeshes[0].fColor) { // If the other op already required explicit local coords the combined mesh does.
fFlags |= kRequiresPerVertexColors_Flag; if (that->fLocalCoordsType == LocalCoordsType::kExplicit) {
fLocalCoordsType = LocalCoordsType::kExplicit;
} }
// Check whether we are about to acquire a mesh with a different view matrix.
if (!SkMatrixPriv::CheapEqual(this->fMeshes[0].fViewMatrix, that->fMeshes[0].fViewMatrix)) { // If we were planning to use positions for local coords but now have multiple view matrices,
fFlags |= kHasMultipleViewMatrices_Flag; // switch to explicit local coords.
if (fLocalCoordsType == LocalCoordsType::kUsePosition && fMultipleViewMatrices) {
fLocalCoordsType = LocalCoordsType::kExplicit;
} }
fMeshes.push_back_n(that->fMeshes.count(), that->fMeshes.begin()); fMeshes.push_back_n(that->fMeshes.count(), that->fMeshes.begin());