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

View File

@ -8,7 +8,6 @@
#ifndef GrDefaultGeoProcFactory_DEFINED
#define GrDefaultGeoProcFactory_DEFINED
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrGeometryProcessor.h"
/*
@ -21,25 +20,18 @@ namespace GrDefaultGeoProcFactory {
kPremulGrColorUniform_Type,
kPremulGrColorAttribute_Type,
kPremulWideColorAttribute_Type,
kUnpremulSkColorAttribute_Type,
};
explicit Color(const SkPMColor4f& color)
: fType(kPremulGrColorUniform_Type)
, fColor(color)
, fColorSpaceXform(nullptr) {}
, fColor(color) {}
Color(Type type)
: fType(type)
, fColor(SK_PMColor4fILLEGAL)
, fColorSpaceXform(nullptr) {
, fColor(SK_PMColor4fILLEGAL) {
SkASSERT(type != kPremulGrColorUniform_Type);
}
Type fType;
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 {
@ -63,7 +55,6 @@ namespace GrDefaultGeoProcFactory {
kUnused_Type,
kUsePosition_Type,
kHasExplicit_Type,
kHasTransformed_Type,
};
LocalCoords(Type type) : fType(type), fMatrix(nullptr) {}
LocalCoords(Type type, const SkMatrix* matrix) : fType(type), fMatrix(matrix) {

View File

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

View File

@ -5,19 +5,204 @@
* found in the LICENSE file.
*/
#include "src/core/SkRectPriv.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkVerticesPriv.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrVertexWriter.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/GrSimpleMeshDrawOpHelper.h"
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 {
private:
using Helper = GrSimpleMeshDrawOpHelper;
@ -48,11 +233,6 @@ public:
bool hasMixedSampledCoverage, GrClampType) override;
private:
enum class ColorArrayType {
kPremulGrColor,
kSkColor,
};
GrProgramInfo* programInfo() override { return fProgramInfo; }
void onCreateProgramInfo(const GrCaps*,
@ -79,13 +259,8 @@ private:
SkPMColor4f fColor; // Used if this->hasPerVertexColors() is false.
sk_sp<SkVertices> fVertices;
SkMatrix fViewMatrix;
bool fIgnoreTexCoords;
bool fIgnoreColors;
bool hasExplicitLocalCoords() const {
return SkVerticesPriv::HasTexCoords(fVertices.get()) && !fIgnoreTexCoords;
}
bool hasPerVertexColors() const {
return SkVerticesPriv::HasColors(fVertices.get()) && !fIgnoreColors;
}
@ -97,33 +272,11 @@ private:
}
bool requiresPerVertexColors() const {
return SkToBool(kRequiresPerVertexColors_Flag & fFlags);
}
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;
}
return fColorArrayType != ColorArrayType::kUnused;
}
bool requiresPerVertexLocalCoords() const {
return this->localCoordsType() == GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type;
}
bool hasMultipleViewMatrices() const {
return SkToBool(kHasMultipleViewMatrices_Flag & fFlags);
return fLocalCoordsType == LocalCoordsType::kExplicit;
}
size_t vertexStride() const {
@ -132,20 +285,15 @@ private:
(this->requiresPerVertexLocalCoords() ? sizeof(SkPoint) : 0);
}
enum Flags {
kRequiresPerVertexColors_Flag = 0x1,
kAnyMeshHasExplicitLocalCoords_Flag = 0x2,
kHasMultipleViewMatrices_Flag = 0x4,
};
Helper fHelper;
SkSTArray<1, Mesh, true> fMeshes;
// 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).
GrPrimitiveType fPrimitiveType;
uint32_t fFlags;
int fVertexCount;
int fIndexCount;
bool fMultipleViewMatrices;
LocalCoordsType fLocalCoordsType;
ColorArrayType fColorArrayType;
sk_sp<GrColorSpaceXform> fColorSpaceXform;
@ -162,6 +310,7 @@ DrawVerticesOp::DrawVerticesOp(const Helper::MakeArgs& helperArgs, const SkPMCol
: INHERITED(ClassID())
, fHelper(helperArgs, aaType)
, fPrimitiveType(primitiveType)
, fMultipleViewMatrices(false)
, fColorSpaceXform(std::move(colorSpaceXform)) {
SkASSERT(vertices);
@ -171,23 +320,16 @@ DrawVerticesOp::DrawVerticesOp(const Helper::MakeArgs& helperArgs, const SkPMCol
fVertexCount = info.fVertexCount;
fIndexCount = info.fIndexCount;
fColorArrayType = info.hasColors() ? ColorArrayType::kSkColor
: ColorArrayType::kPremulGrColor;
: ColorArrayType::kUnused;
fLocalCoordsType = info.hasTexCoords() ? LocalCoordsType::kExplicit
: LocalCoordsType::kUsePosition;
Mesh& mesh = fMeshes.push_back();
mesh.fColor = color;
mesh.fViewMatrix = viewMatrix;
mesh.fVertices = std::move(vertices);
mesh.fIgnoreTexCoords = false;
mesh.fIgnoreColors = false;
fFlags = 0;
if (mesh.hasPerVertexColors()) {
fFlags |= kRequiresPerVertexColors_Flag;
}
if (mesh.hasExplicitLocalCoords()) {
fFlags |= kAnyMeshHasExplicitLocalCoords_Flag;
}
IsHairline zeroArea;
if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
zeroArea = IsHairline::kYes;
@ -229,33 +371,22 @@ GrProcessorSet::Analysis DrawVerticesOp::finalize(
GrProcessorAnalysisCoverage::kNone, &gpColor);
if (gpColor.isConstant(&fMeshes.front().fColor)) {
fMeshes.front().fIgnoreColors = true;
fFlags &= ~kRequiresPerVertexColors_Flag;
fColorArrayType = ColorArrayType::kPremulGrColor;
fColorArrayType = ColorArrayType::kUnused;
}
if (!fHelper.usesLocalCoords()) {
fMeshes[0].fIgnoreTexCoords = true;
fFlags &= ~kAnyMeshHasExplicitLocalCoords_Flag;
fLocalCoordsType = LocalCoordsType::kUnused;
}
return result;
}
GrGeometryProcessor* DrawVerticesOp::makeGP(SkArenaAlloc* arena) {
using namespace GrDefaultGeoProcFactory;
sk_sp<GrColorSpaceXform> csxform =
fColorArrayType == ColorArrayType::kSkColor ? fColorSpaceXform : nullptr;
Color color(fMeshes[0].fColor);
if (this->requiresPerVertexColors()) {
if (fColorArrayType == ColorArrayType::kPremulGrColor) {
color.fType = Color::kPremulGrColorAttribute_Type;
} else {
color.fType = Color::kUnpremulSkColorAttribute_Type;
color.fColorSpaceXform = fColorSpaceXform;
}
}
const SkMatrix& vm = fMultipleViewMatrices ? SkMatrix::I() : fMeshes[0].fViewMatrix;
const SkMatrix& vm = this->hasMultipleViewMatrices() ? SkMatrix::I() : fMeshes[0].fViewMatrix;
auto gp = GrDefaultGeoProcFactory::Make(arena, color, Coverage::kSolid_Type,
this->localCoordsType(), vm);
auto gp = VerticesGP::Make(arena, fLocalCoordsType, fColorArrayType, fMeshes[0].fColor,
std::move(csxform), vm);
SkASSERT(this->vertexStride() == gp->vertexStride());
return gp;
}
@ -313,8 +444,7 @@ void DrawVerticesOp::onPrepareDraws(Target* target) {
int vertexCount = info.fVertexCount;
const SkPoint* positions = info.fPositions;
const SkColor* colors = info.fColors;
const SkPoint* localCoords =
mesh.hasExplicitLocalCoords() ? info.fTexCoords : positions;
const SkPoint* localCoords = info.fTexCoords ? info.fTexCoords : positions;
// TODO4F: Preserve float colors
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);
}
@ -378,28 +508,49 @@ GrOp::CombineResult DrawVerticesOp::onCombineIfPossible(GrOp* t, GrRecordingCont
return CombineResult::kCannotCombine;
}
if (fColorArrayType != that->fColorArrayType) {
if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) {
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;
}
// 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
// gamut is determined by the render target context. A mis-match should be impossible.
SkASSERT(GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get()));
// If either op required explicit local coords or per-vertex colors the combined mesh does.
// Same with multiple view matrices.
fFlags |= that->fFlags;
// If we're acquiring a mesh with a different view matrix, or an op that needed multiple view
// matrices, we need multiple view matrices.
fMultipleViewMatrices =
fMultipleViewMatrices || that->fMultipleViewMatrices ||
!SkMatrixPriv::CheapEqual(this->fMeshes[0].fViewMatrix, that->fMeshes[0].fViewMatrix);
if (this->fMeshes[0].fColor != that->fMeshes[0].fColor) {
fFlags |= kRequiresPerVertexColors_Flag;
// If the other op already required explicit local coords the combined mesh does.
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)) {
fFlags |= kHasMultipleViewMatrices_Flag;
// If we were planning to use positions for local coords but now have multiple view matrices,
// switch to explicit local coords.
if (fLocalCoordsType == LocalCoordsType::kUsePosition && fMultipleViewMatrices) {
fLocalCoordsType = LocalCoordsType::kExplicit;
}
fMeshes.push_back_n(that->fMeshes.count(), that->fMeshes.begin());