Revert "Track quad type on GrQuad directly"

This reverts commit 85766c4cd3.

Reason for revert: red - so much red

Original change's description:
> Track quad type on GrQuad directly
> 
> This makes subsequent higher-level drawing APIs more compact, and
> shouldn't come with a performance hit. Everywhere we used to need
> a GrPerspQuad, we'd also take the GrQuadType as a second argument.
> The quad list types already deconstruct the quad so there's no
> extra overhead in the op's memory usage.
> 
> It also improves usability and decreases the likelihood that an
> incorrect quad type is ever associated with the quad.
> 
> Bug: skia:
> Change-Id: Iba908fb133ad664744a5788a7088d90de0d3a1c2
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/214820
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>

TBR=bsalomon@google.com,robertphillips@google.com,michaelludwig@google.com

Change-Id: Ied594673116fb901287b334fea41da3c71494fb1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/215607
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2019-05-23 17:22:19 +00:00 committed by Skia Commit-Bot
parent 2b35b7db51
commit 0dee19bacc
7 changed files with 171 additions and 178 deletions

View File

@ -69,39 +69,10 @@ static void rearrange_sk_to_gr_points(const SkPoint skQuadPts[4], V4f* xs, V4f*
*ys = V4f{skQuadPts[0].fY, skQuadPts[3].fY, skQuadPts[1].fY, skQuadPts[2].fY};
}
// If an SkRect is transformed by this matrix, what class of quad is required to represent it.
static GrQuadType quad_type_for_transformed_rect(const SkMatrix& matrix) {
if (matrix.rectStaysRect()) {
return GrQuadType::kRect;
} else if (matrix.preservesRightAngles()) {
return GrQuadType::kRectilinear;
} else if (matrix.hasPerspective()) {
return GrQuadType::kPerspective;
} else {
return GrQuadType::kStandard;
}
}
// Perform minimal analysis of 'pts' (which are suitable for MakeFromSkQuad), and determine a
// quad type that will be as minimally general as possible.
static GrQuadType quad_type_for_points(const SkPoint pts[4], const SkMatrix& matrix) {
if (matrix.hasPerspective()) {
return GrQuadType::kPerspective;
}
// If 'pts' was formed by SkRect::toQuad() and not transformed further, it is safe to use the
// quad type derived from 'matrix'. Otherwise don't waste any more time and assume kStandard
// (most general 2D quad).
if ((pts[0].fX == pts[3].fX && pts[1].fX == pts[2].fX) &&
(pts[0].fY == pts[1].fY && pts[2].fY == pts[3].fY)) {
return quad_type_for_transformed_rect(matrix);
} else {
return GrQuadType::kStandard;
}
}
template <typename Q>
void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
const Q& quad, GrAAType* outAAType, GrQuadAAFlags* outEdgeFlags) {
const Q& quad, GrQuadType knownType,
GrAAType* outAAType, GrQuadAAFlags* outEdgeFlags) {
// Most cases will keep the requested types unchanged
*outAAType = requestedAAType;
*outEdgeFlags = requestedEdgeFlags;
@ -115,7 +86,7 @@ void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdg
} else {
// For coverage AA, if the quad is a rect and it lines up with pixel boundaries
// then overall aa and per-edge aa can be completely disabled
if (quad.quadType() == GrQuadType::kRect && !quad.aaHasEffectOnRect()) {
if (knownType == GrQuadType::kRect && !quad.aaHasEffectOnRect()) {
*outAAType = GrAAType::kNone;
*outEdgeFlags = GrQuadAAFlags::kNone;
}
@ -136,46 +107,58 @@ void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdg
};
// Instantiate GrResolve... for GrQuad and GrPerspQuad
template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrQuad&,
template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrQuad&, GrQuadType,
GrAAType*, GrQuadAAFlags*);
template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrPerspQuad&,
template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrPerspQuad&, GrQuadType,
GrAAType*, GrQuadAAFlags*);
GrQuadType GrQuadTypeForTransformedRect(const SkMatrix& matrix) {
if (matrix.rectStaysRect()) {
return GrQuadType::kRect;
} else if (matrix.preservesRightAngles()) {
return GrQuadType::kRectilinear;
} else if (matrix.hasPerspective()) {
return GrQuadType::kPerspective;
} else {
return GrQuadType::kStandard;
}
}
GrQuadType GrQuadTypeForPoints(const SkPoint pts[4], const SkMatrix& matrix) {
if (matrix.hasPerspective()) {
return GrQuadType::kPerspective;
}
// If 'pts' was formed by SkRect::toQuad() and not transformed further, it is safe to use the
// quad type derived from 'matrix'. Otherwise don't waste any more time and assume kStandard
// (most general 2D quad).
if ((pts[0].fX == pts[3].fX && pts[1].fX == pts[2].fX) &&
(pts[0].fY == pts[1].fY && pts[2].fY == pts[3].fY)) {
return GrQuadTypeForTransformedRect(matrix);
} else {
return GrQuadType::kStandard;
}
}
GrQuad GrQuad::MakeFromRect(const SkRect& rect, const SkMatrix& m) {
V4f x, y;
SkMatrix::TypeMask tm = m.getType();
GrQuadType type;
if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
map_rect_translate_scale(rect, m, &x, &y);
type = GrQuadType::kRect;
} else {
map_rect_general(rect, m, &x, &y, nullptr);
type = quad_type_for_transformed_rect(m);
if (type == GrQuadType::kPerspective) {
// While the matrix created perspective, the coordinates were projected to a 2D quad
// in map_rect_general since no w V4f was provided.
type = GrQuadType::kStandard;
}
}
return GrQuad(x, y, type);
return GrQuad(x, y);
}
GrQuad GrQuad::MakeFromSkQuad(const SkPoint pts[4], const SkMatrix& matrix) {
V4f xs, ys;
rearrange_sk_to_gr_points(pts, &xs, &ys);
GrQuadType type = quad_type_for_points(pts, matrix);
if (type == GrQuadType::kPerspective) {
// While the matrix created perspective, the coordinates were projected to a 2D quad
// in map_rect_general since no w V4f was provided.
type = GrQuadType::kStandard;
}
if (matrix.isIdentity()) {
return GrQuad(xs, ys, type);
return GrQuad(xs, ys);
} else {
V4f mx, my;
map_quad_general(xs, ys, matrix, &mx, &my, nullptr);
return GrQuad(mx, my, type);
return GrQuad(mx, my);
}
}
@ -184,8 +167,7 @@ bool GrQuad::aaHasEffectOnRect() const {
}
// Private constructor used by GrQuadList to quickly fill in a quad's values from the channel arrays
GrPerspQuad::GrPerspQuad(const float* xs, const float* ys, const float* ws, GrQuadType type)
: fType(type) {
GrPerspQuad::GrPerspQuad(const float* xs, const float* ys, const float* ws) {
memcpy(fX, xs, 4 * sizeof(float));
memcpy(fY, ys, 4 * sizeof(float));
memcpy(fW, ws, 4 * sizeof(float));
@ -194,28 +176,24 @@ GrPerspQuad::GrPerspQuad(const float* xs, const float* ys, const float* ws, GrQu
GrPerspQuad GrPerspQuad::MakeFromRect(const SkRect& rect, const SkMatrix& m) {
V4f x, y, w;
SkMatrix::TypeMask tm = m.getType();
GrQuadType type;
if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
map_rect_translate_scale(rect, m, &x, &y);
w = 1.f;
type = GrQuadType::kRect;
} else {
map_rect_general(rect, m, &x, &y, &w);
type = quad_type_for_transformed_rect(m);
}
return GrPerspQuad(x, y, w, type);
return GrPerspQuad(x, y, w);
}
GrPerspQuad GrPerspQuad::MakeFromSkQuad(const SkPoint pts[4], const SkMatrix& matrix) {
V4f xs, ys;
rearrange_sk_to_gr_points(pts, &xs, &ys);
GrQuadType type = quad_type_for_points(pts, matrix);
if (matrix.isIdentity()) {
return GrPerspQuad(xs, ys, 1.f, type);
return GrPerspQuad(xs, ys, 1.f);
} else {
V4f mx, my, mw;
map_quad_general(xs, ys, matrix, &mx, &my, &mw);
return GrPerspQuad(mx, my, mw, type);
return GrPerspQuad(mx, my, mw);
}
}

View File

@ -34,12 +34,19 @@ enum class GrQuadType {
};
static const int kGrQuadTypeCount = static_cast<int>(GrQuadType::kLast) + 1;
// If an SkRect is transformed by this matrix, what class of quad is required to represent it.
GrQuadType GrQuadTypeForTransformedRect(const SkMatrix& matrix);
// Perform minimal analysis of 'pts' (which are suitable for MakeFromSkQuad), and determine a
// quad type that will be as minimally general as possible.
GrQuadType GrQuadTypeForPoints(const SkPoint pts[4], const SkMatrix& matrix);
// Resolve disagreements between the overall requested AA type and the per-edge quad AA flags.
// knownQuadType must have come from GrQuadTypeForTransformedRect with the matrix that created the
// provided quad. Both outAAType and outEdgeFlags will be updated.
template <typename Q>
void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
const Q& quad, GrAAType* outAAtype, GrQuadAAFlags* outEdgeFlags);
const Q& quad, GrQuadType knownQuadType,
GrAAType* outAAtype, GrQuadAAFlags* outEdgeFlags);
/**
* GrQuad is a collection of 4 points which can be used to represent an arbitrary quadrilateral. The
@ -53,15 +60,17 @@ public:
explicit GrQuad(const SkRect& rect)
: fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
, fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom}
, fType(GrQuadType::kRect) {}
, fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom} {}
GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, GrQuadType type)
: fType(type) {
GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys) {
xs.store(fX);
ys.store(fY);
}
explicit GrQuad(const SkPoint pts[4])
: fX{pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX}
, fY{pts[0].fY, pts[1].fY, pts[2].fY, pts[3].fY} {}
/** Sets the quad to the rect as transformed by the matrix. */
static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);
@ -86,8 +95,6 @@ public:
skvx::Vec<4, float> x4f() const { return skvx::Vec<4, float>::Load(fX); }
skvx::Vec<4, float> y4f() const { return skvx::Vec<4, float>::Load(fY); }
GrQuadType quadType() const { return fType; }
// True if anti-aliasing affects this quad. Only valid when quadType == kRect_QuadType
bool aaHasEffectOnRect() const;
@ -97,8 +104,6 @@ private:
float fX[4];
float fY[4];
GrQuadType fType;
};
class GrPerspQuad {
@ -108,21 +113,16 @@ public:
explicit GrPerspQuad(const SkRect& rect)
: fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
, fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom}
, fW{1.f, 1.f, 1.f, 1.f}
, fType(GrQuadType::kRect) {}
, fW{1.f, 1.f, 1.f, 1.f} {}
GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
GrQuadType type)
: fType(type) {
SkASSERT(type != GrQuadType::kPerspective);
GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys) {
xs.store(fX);
ys.store(fY);
fW[0] = fW[1] = fW[2] = fW[3] = 1.f;
}
GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
const skvx::Vec<4, float>& ws, GrQuadType type)
: fType(type) {
const skvx::Vec<4, float>& ws) {
xs.store(fX);
ys.store(fY);
ws.store(fW);
@ -139,10 +139,10 @@ public:
SkPoint3 point(int i) const { return {fX[i], fY[i], fW[i]}; }
SkRect bounds() const {
SkRect bounds(GrQuadType type) const {
auto x = this->x4f();
auto y = this->y4f();
if (fType == GrQuadType::kPerspective) {
if (type == GrQuadType::kPerspective) {
auto iw = this->iw4f();
x *= iw;
y *= iw;
@ -161,9 +161,7 @@ public:
skvx::Vec<4, float> w4f() const { return skvx::Vec<4, float>::Load(fW); }
skvx::Vec<4, float> iw4f() const { return 1.f / this->w4f(); }
GrQuadType quadType() const { return fType; }
bool hasPerspective() const { return fType == GrQuadType::kPerspective; }
bool hasPerspective() const { return any(w4f() != 1.f); }
// True if anti-aliasing affects this quad. Only valid when quadType == kRect_QuadType
bool aaHasEffectOnRect() const;
@ -173,13 +171,11 @@ private:
friend class GrQuadListBase;
// Copy 4 values from each of the arrays into the quad's components
GrPerspQuad(const float xs[4], const float ys[4], const float ws[4], GrQuadType type);
GrPerspQuad(const float xs[4], const float ys[4], const float ws[4]);
float fX[4];
float fY[4];
float fW[4];
GrQuadType fType;
};
// Underlying data used by GrQuadListBase. It is defined outside of GrQuadListBase due to compiler
@ -209,9 +205,9 @@ public:
GrQuadType quadType() const { return fType; }
void reserve(int count, bool needsPerspective) {
void reserve(int count, GrQuadType forType) {
fXYs.reserve(count);
if (needsPerspective || fType == GrQuadType::kPerspective) {
if (forType == GrQuadType::kPerspective || fType == GrQuadType::kPerspective) {
fWs.reserve(4 * count);
}
}
@ -223,11 +219,11 @@ public:
const QuadData<T>& item = fXYs[i];
if (fType == GrQuadType::kPerspective) {
// Read the explicit ws
return GrPerspQuad(item.fX, item.fY, fWs.begin() + 4 * i, fType);
return GrPerspQuad(item.fX, item.fY, fWs.begin() + 4 * i);
} else {
// Ws are implicitly 1s.
static constexpr float kNoPerspectiveWs[4] = {1.f, 1.f, 1.f, 1.f};
return GrPerspQuad(item.fX, item.fY, kNoPerspectiveWs, fType);
return GrPerspQuad(item.fX, item.fY, kNoPerspectiveWs);
}
}
@ -253,8 +249,8 @@ protected:
}
// Returns the added item data so that its metadata can be initialized if T is not void
QuadData<T>& pushBackImpl(const GrQuad& quad) {
this->upgradeType(quad.quadType());
QuadData<T>& pushBackImpl(const GrQuad& quad, GrQuadType type) {
this->upgradeType(type);
QuadData<T>& item = fXYs.push_back();
memcpy(item.fX, quad.fX, 4 * sizeof(float));
memcpy(item.fY, quad.fY, 4 * sizeof(float));
@ -264,8 +260,8 @@ protected:
return item;
}
QuadData<T>& pushBackImpl(const GrPerspQuad& quad) {
this->upgradeType(quad.quadType());
QuadData<T>& pushBackImpl(const GrPerspQuad& quad, GrQuadType type) {
this->upgradeType(type);
QuadData<T>& item = fXYs.push_back();
memcpy(item.fX, quad.fX, 4 * sizeof(float));
memcpy(item.fY, quad.fY, 4 * sizeof(float));
@ -313,12 +309,12 @@ public:
this->concatImpl(that);
}
void push_back(const GrQuad& quad) {
this->pushBackImpl(quad);
void push_back(const GrQuad& quad, GrQuadType type) {
this->pushBackImpl(quad, type);
}
void push_back(const GrPerspQuad& quad) {
this->pushBackImpl(quad);
void push_back(const GrPerspQuad& quad, GrQuadType type) {
this->pushBackImpl(quad, type);
}
private:
@ -337,13 +333,13 @@ public:
}
// Adding to the list requires metadata
void push_back(const GrQuad& quad, T&& metadata) {
QuadData<T>& item = this->pushBackImpl(quad);
void push_back(const GrQuad& quad, GrQuadType type, T&& metadata) {
QuadData<T>& item = this->pushBackImpl(quad, type);
item.fMetadata = std::move(metadata);
}
void push_back(const GrPerspQuad& quad, T&& metadata) {
QuadData<T>& item = this->pushBackImpl(quad);
void push_back(const GrPerspQuad& quad, GrQuadType type, T&& metadata) {
QuadData<T>& item = this->pushBackImpl(quad, type);
item.fMetadata = std::move(metadata);
}

View File

@ -64,32 +64,35 @@ public:
GrQuadAAFlags edgeAA,
const GrUserStencilSettings* stencilSettings,
const GrPerspQuad& deviceQuad,
const GrPerspQuad& localQuad) {
GrQuadType deviceQuadType,
const GrPerspQuad& localQuad,
GrQuadType localQuadType) {
// Clean up deviations between aaType and edgeAA
GrResolveAATypeForQuad(aaType, edgeAA, deviceQuad, &aaType, &edgeAA);
GrResolveAATypeForQuad(aaType, edgeAA, deviceQuad, deviceQuadType, &aaType, &edgeAA);
return Helper::FactoryHelper<FillRectOp>(context, std::move(paint), aaType, edgeAA,
stencilSettings, deviceQuad, localQuad);
stencilSettings, deviceQuad, deviceQuadType, localQuad, localQuadType);
}
// aaType is passed to Helper in the initializer list, so incongruities between aaType and
// edgeFlags must be resolved prior to calling this constructor.
FillRectOp(Helper::MakeArgs args, SkPMColor4f paintColor, GrAAType aaType,
GrQuadAAFlags edgeFlags, const GrUserStencilSettings* stencil,
const GrPerspQuad& deviceQuad, const GrPerspQuad& localQuad)
const GrPerspQuad& deviceQuad, GrQuadType deviceQuadType,
const GrPerspQuad& localQuad, GrQuadType localQuadType)
: INHERITED(ClassID())
, fHelper(args, aaType, stencil) {
// The color stored with the quad is the clear color if a scissor-clear is decided upon
// when executing the op.
fDeviceQuads.push_back(deviceQuad, { paintColor, edgeFlags });
fDeviceQuads.push_back(deviceQuad, deviceQuadType, { paintColor, edgeFlags });
if (!fHelper.isTrivial()) {
// Conservatively keep track of the local coordinates; it may be that the paint doesn't
// need them after analysis is finished. If the paint is known to be solid up front they
// can be skipped entirely.
fLocalQuads.push_back(localQuad);
fLocalQuads.push_back(localQuad, localQuadType);
}
this->setBounds(deviceQuad.bounds(), HasAABloat(aaType == GrAAType::kCoverage),
IsZeroArea::kNo);
this->setBounds(deviceQuad.bounds(deviceQuadType),
HasAABloat(aaType == GrAAType::kCoverage), IsZeroArea::kNo);
}
const char* name() const override { return "FillRectOp"; }
@ -294,7 +297,8 @@ private:
// used with quad sets, which uses the same view matrix for each quad so this assumes that the
// device quad type of the new quad is the same as the op's.
void addQuad(const GrPerspQuad& deviceQuad, const GrPerspQuad& localQuad,
const SkPMColor4f& color, GrQuadAAFlags edgeAA, GrAAType aaType) {
GrQuadType localQuadType, const SkPMColor4f& color, GrQuadAAFlags edgeAA,
GrAAType aaType) {
// The new quad's aa type should be the same as the first quad's or none, except when the
// first quad's aa type was already downgraded to none, in which case the stored type must
// be lifted to back to the requested type.
@ -310,12 +314,12 @@ private:
// Update the bounds and add the quad to this op's storage
SkRect newBounds = this->bounds();
newBounds.joinPossiblyEmptyRect(deviceQuad.bounds());
newBounds.joinPossiblyEmptyRect(deviceQuad.bounds(fDeviceQuads.quadType()));
this->setBounds(newBounds, HasAABloat(fHelper.aaType() == GrAAType::kCoverage),
IsZeroArea::kNo);
fDeviceQuads.push_back(deviceQuad, { color, edgeAA });
fDeviceQuads.push_back(deviceQuad, fDeviceQuads.quadType(), { color, edgeAA });
if (!fHelper.isTrivial()) {
fLocalQuads.push_back(localQuad);
fLocalQuads.push_back(localQuad, localQuadType);
}
}
@ -352,8 +356,10 @@ std::unique_ptr<GrDrawOp> MakePerEdge(GrRecordingContext* context,
const SkMatrix& viewMatrix,
const SkRect& rect,
const GrUserStencilSettings* stencilSettings) {
GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
GrPerspQuad::MakeFromRect(rect, viewMatrix), GrPerspQuad(rect));
GrPerspQuad::MakeFromRect(rect, viewMatrix), dstQuadType,
GrPerspQuad(rect), GrQuadType::kRect);
}
std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalMatrix(GrRecordingContext* context,
@ -364,9 +370,11 @@ std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalMatrix(GrRecordingContext* context
const SkMatrix& localMatrix,
const SkRect& rect,
const GrUserStencilSettings* stencilSettings) {
GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
GrQuadType localQuadType = GrQuadTypeForTransformedRect(localMatrix);
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
GrPerspQuad::MakeFromRect(rect, viewMatrix),
GrPerspQuad::MakeFromRect(rect, localMatrix));
GrPerspQuad::MakeFromRect(rect, viewMatrix), dstQuadType,
GrPerspQuad::MakeFromRect(rect, localMatrix), localQuadType);
}
std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalRect(GrRecordingContext* context,
@ -377,8 +385,10 @@ std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalRect(GrRecordingContext* context,
const SkRect& rect,
const SkRect& localRect,
const GrUserStencilSettings* stencilSettings) {
GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
GrPerspQuad::MakeFromRect(rect, viewMatrix), GrPerspQuad(localRect));
GrPerspQuad::MakeFromRect(rect, viewMatrix), dstQuadType,
GrPerspQuad(localRect), GrQuadType::kRect);
}
std::unique_ptr<GrDrawOp> MakePerEdgeQuad(GrRecordingContext* context,
@ -389,10 +399,12 @@ std::unique_ptr<GrDrawOp> MakePerEdgeQuad(GrRecordingContext* context,
const SkPoint quad[4],
const SkPoint localQuad[4],
const GrUserStencilSettings* stencilSettings) {
GrQuadType deviceType = GrQuadTypeForPoints(quad, viewMatrix);
GrQuadType localType = GrQuadTypeForPoints(localQuad ? localQuad : quad, SkMatrix::I());
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
GrPerspQuad::MakeFromSkQuad(quad, viewMatrix),
GrPerspQuad::MakeFromSkQuad(quad, viewMatrix), deviceType,
GrPerspQuad::MakeFromSkQuad(localQuad ? localQuad : quad,
SkMatrix::I()));
SkMatrix::I()), localType);
}
std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
@ -404,12 +416,14 @@ std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
const GrUserStencilSettings* stencilSettings) {
// First make a draw op for the first quad in the set
SkASSERT(cnt > 0);
GrQuadType deviceQuadType = GrQuadTypeForTransformedRect(viewMatrix);
paint.setColor4f(quads[0].fColor);
std::unique_ptr<GrDrawOp> op = FillRectOp::Make(context, std::move(paint), aaType,
quads[0].fAAFlags, stencilSettings,
GrPerspQuad::MakeFromRect(quads[0].fRect, viewMatrix),
GrPerspQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix));
GrPerspQuad::MakeFromRect(quads[0].fRect, viewMatrix), deviceQuadType,
GrPerspQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix),
GrQuadTypeForTransformedRect(quads[0].fLocalMatrix));
auto* fillRects = op->cast<FillRectOp>();
// Accumulate remaining quads similar to onCombineIfPossible() without creating an op
@ -418,12 +432,13 @@ std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
GrAAType resolvedAA;
GrQuadAAFlags resolvedEdgeFlags;
GrResolveAATypeForQuad(aaType, quads[i].fAAFlags, deviceQuad,
GrResolveAATypeForQuad(aaType, quads[i].fAAFlags, deviceQuad, deviceQuadType,
&resolvedAA, &resolvedEdgeFlags);
fillRects->addQuad(deviceQuad,
GrPerspQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
quads[i].fColor, resolvedEdgeFlags,resolvedAA);
GrQuadTypeForTransformedRect(quads[i].fLocalMatrix), quads[i].fColor,
resolvedEdgeFlags,resolvedAA);
}
return op;

View File

@ -742,9 +742,6 @@ ColorType MinColorType(SkPMColor4f color, GrClampType clampType, const GrCaps& c
void* Tessellate(void* vertices, const VertexSpec& spec, const GrPerspQuad& deviceQuad,
const SkPMColor4f& color4f, const GrPerspQuad& localQuad, const SkRect& domain,
GrQuadAAFlags aaFlags) {
SkASSERT(deviceQuad.quadType() <= spec.deviceQuadType());
SkASSERT(!spec.hasLocalCoords() || localQuad.quadType() <= spec.localQuadType());
CoverageMode mode = get_mode_for_spec(spec);
// Load position data into V4fs (always x, y, and load w to avoid branching down the road)

View File

@ -91,9 +91,6 @@ namespace GrQuadPerEdgeAA {
// based on the configuration in the vertex spec; if that attribute is disabled in the spec,
// then its corresponding function argument is ignored.
//
// Tessellation is based on the quad type of the vertex spec, not the provided GrPerspQuad's
// so that all quads in a batch are tessellated the same.
//
// Returns the advanced pointer in vertices.
void* Tessellate(void* vertices, const VertexSpec& spec, const GrPerspQuad& deviceQuad,
const SkPMColor4f& color, const GrPerspQuad& localQuad, const SkRect& domain,

View File

@ -99,7 +99,7 @@ static GrPerspQuad compute_src_quad(GrSurfaceOrigin origin, const GrPerspQuad& s
if (origin == kBottomLeft_GrSurfaceOrigin) {
ys = h - ys;
}
return GrPerspQuad(xs, ys, GrQuadType::kStandard);
return GrPerspQuad(xs, ys);
}
/**
@ -120,8 +120,9 @@ public:
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
GrPerspQuad dstQuad = GrPerspQuad::MakeFromRect(dstRect, viewMatrix);
GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
if (dstQuad.quadType() == GrQuadType::kRect) {
if (dstQuadType == GrQuadType::kRect) {
// Disable filtering if possible (note AA optimizations for rects are automatically
// handled above in GrResolveAATypeForQuad).
if (filter != GrSamplerState::Filter::kNearest &&
@ -133,8 +134,8 @@ public:
GrOpMemoryPool* pool = context->priv().opMemoryPool();
// srcRect provides both local coords and domain (if needed), so use nullptr for srcQuad
return pool->allocate<TextureOp>(
std::move(proxy), filter, color, dstQuad, srcRect, constraint,
nullptr, aaType, aaFlags, std::move(textureColorSpaceXform));
std::move(proxy), filter, color, dstQuad, dstQuadType, srcRect, constraint,
nullptr, GrQuadType::kRect, aaType, aaFlags, std::move(textureColorSpaceXform));
}
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
sk_sp<GrTextureProxy> proxy,
@ -148,7 +149,9 @@ public:
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
GrPerspQuad grDstQuad = GrPerspQuad::MakeFromSkQuad(dstQuad, viewMatrix);
GrQuadType dstQuadType = GrQuadTypeForPoints(dstQuad, viewMatrix);
GrPerspQuad grSrcQuad = GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I());
GrQuadType srcQuadType = GrQuadTypeForPoints(srcQuad, SkMatrix::I());
// If constraint remains fast, the value in srcRect will be ignored since srcQuads provides
// the local coordinates and a domain won't be used.
@ -162,8 +165,9 @@ public:
GrOpMemoryPool* pool = context->priv().opMemoryPool();
// Pass domain as srcRect if provided, but send srcQuad as a GrPerspQuad for local coords
return pool->allocate<TextureOp>(
std::move(proxy), filter, color, grDstQuad, srcRect, constraint, &grSrcQuad,
aaType, aaFlags, std::move(textureColorSpaceXform));
std::move(proxy), filter, color, grDstQuad, dstQuadType, srcRect, constraint,
&grSrcQuad, srcQuadType, aaType, aaFlags,
std::move(textureColorSpaceXform));
}
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
const GrRenderTargetContext::TextureSetEntry set[],
@ -255,8 +259,9 @@ private:
// If srcQuad is provided, it will be used for the local coords instead of srcRect, although
// srcRect will still specify the domain constraint if needed.
TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, const SkPMColor4f& color,
const GrPerspQuad& dstQuad, const SkRect& srcRect,
SkCanvas::SrcRectConstraint constraint, const GrPerspQuad* srcQuad, GrAAType aaType,
const GrPerspQuad& dstQuad, GrQuadType dstQuadType,
const SkRect& srcRect, SkCanvas::SrcRectConstraint constraint,
const GrPerspQuad* srcQuad, GrQuadType srcQuadType, GrAAType aaType,
GrQuadAAFlags aaFlags, sk_sp<GrColorSpaceXform> textureColorSpaceXform)
: INHERITED(ClassID())
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
@ -264,7 +269,7 @@ private:
, fFinalized(0) {
// Clean up disparities between the overall aa type and edge configuration and apply
// optimizations based on the rect and matrix when appropriate
GrResolveAATypeForQuad(aaType, aaFlags, dstQuad, &aaType, &aaFlags);
GrResolveAATypeForQuad(aaType, aaFlags, dstQuad, dstQuadType, &aaType, &aaFlags);
fAAType = static_cast<unsigned>(aaType);
// We expect our caller to have already caught this optimization.
@ -283,14 +288,14 @@ private:
Domain domain = constraint == SkCanvas::kStrict_SrcRectConstraint ? Domain::kYes
: Domain::kNo;
// Initially, if srcQuad is provided it will always be at index 0 of fSrcQuads
fQuads.push_back(dstQuad, {color, srcRect, srcQuad ? 0 : -1, domain, aaFlags});
fQuads.push_back(dstQuad, dstQuadType, {color, srcRect, srcQuad ? 0 : -1, domain, aaFlags});
if (srcQuad) {
fSrcQuads.push_back(*srcQuad);
fSrcQuads.push_back(*srcQuad, srcQuadType);
}
fProxyCnt = 1;
fProxies[0] = {proxy.release(), 1};
this->setBounds(dstQuad.bounds(), HasAABloat(aaType == GrAAType::kCoverage),
IsZeroArea::kNo);
auto bounds = dstQuad.bounds(dstQuadType);
this->setBounds(bounds, HasAABloat(aaType == GrAAType::kCoverage), IsZeroArea::kNo);
fDomain = static_cast<unsigned>(domain);
}
TextureOp(const GrRenderTargetContext::TextureSetEntry set[], int cnt,
@ -308,7 +313,7 @@ private:
// Most dst rects are transformed by the same view matrix, so their quad types start
// identical, unless an entry provides a dstClip or additional transform that changes it.
// The quad list will automatically adapt to that.
fQuads.reserve(cnt, viewMatrix.hasPerspective());
fQuads.reserve(cnt, GrQuadTypeForTransformedRect(viewMatrix));
bool allOpaque = true;
Domain netDomain = Domain::kNo;
for (unsigned p = 0; p < fProxyCnt; ++p) {
@ -326,19 +331,22 @@ private:
auto quad = set[p].fDstClipQuad == nullptr ?
GrPerspQuad::MakeFromRect(set[p].fDstRect, ctm) :
GrPerspQuad::MakeFromSkQuad(set[p].fDstClipQuad, ctm);
GrQuadType quadType =
set[p].fDstClipQuad ? GrQuadTypeForPoints(set[p].fDstClipQuad, ctm)
: GrQuadTypeForTransformedRect(ctm);
bounds.joinPossiblyEmptyRect(quad.bounds());
bounds.joinPossiblyEmptyRect(quad.bounds(quadType));
GrQuadAAFlags aaFlags;
// Don't update the overall aaType, might be inappropriate for some of the quads
GrAAType aaForQuad;
GrResolveAATypeForQuad(aaType, set[p].fAAFlags, quad, &aaForQuad, &aaFlags);
GrResolveAATypeForQuad(aaType, set[p].fAAFlags, quad, quadType, &aaForQuad, &aaFlags);
// Resolve sets aaForQuad to aaType or None, there is never a change between aa methods
SkASSERT(aaForQuad == GrAAType::kNone || aaForQuad == aaType);
if (overallAAType == GrAAType::kNone && aaForQuad != GrAAType::kNone) {
overallAAType = aaType;
}
if (!mustFilter && this->filter() != GrSamplerState::Filter::kNearest) {
mustFilter = quad.quadType() != GrQuadType::kRect ||
mustFilter = quadType != GrQuadType::kRect ||
GrTextureOp::GetFilterHasEffect(ctm, set[p].fSrcRect,
set[p].fDstRect);
}
@ -362,10 +370,12 @@ private:
// but with respect to srcRect
SkPoint srcQuad[4];
GrMapRectPoints(set[p].fDstRect, set[p].fSrcRect, set[p].fDstClipQuad, srcQuad, 4);
fSrcQuads.push_back(GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()));
fSrcQuads.push_back(GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()),
GrQuadTypeForPoints(srcQuad, SkMatrix::I()));
srcQuadIndex = fSrcQuads.count() - 1;
}
fQuads.push_back(quad, {color, set[p].fSrcRect, srcQuadIndex, domainForQuad, aaFlags});
fQuads.push_back(quad, quadType,
{color, set[p].fSrcRect, srcQuadIndex, domainForQuad, aaFlags});
}
fAAType = static_cast<unsigned>(overallAAType);
if (!mustFilter) {

View File

@ -55,8 +55,8 @@ TEST(Add2D) {
GrQuadList list2D;
// Add a plain quad, a 2D persp quad, and then a 3D persp quad, then read back and make sure
// the coordinates make sense (including that the type was lifted to perspective).
list2D.push_back(make_2d_quad());
list2D.push_back(make_2d_persp_quad());
list2D.push_back(make_2d_quad(), GrQuadType::kRect);
list2D.push_back(make_2d_persp_quad(), GrQuadType::kRect);
// Check 2D state of the list
ASSERTF(list2D.count() == 2, "Unexpected count: %d", list2D.count());
@ -66,7 +66,7 @@ TEST(Add2D) {
ASSERTF(is_2d_persp_quad(list2D[1]), "Incorrect quad at i=1");
// Force the 2D quads to be updated to store ws by adding a perspective quad
list2D.push_back(make_3d_persp_quad());
list2D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
ASSERTF(list2D.quadType() == GrQuadType::kPerspective,
"Expected 2D list to be upgraded to perspective");
@ -81,9 +81,9 @@ TEST(Add3D) {
// Now make a list that starts with a 3D persp quad, then has conventional quads added to it
// and make sure its state is correct
GrQuadList list3D;
list3D.push_back(make_3d_persp_quad());
list3D.push_back(make_2d_persp_quad());
list3D.push_back(make_2d_quad());
list3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
list3D.push_back(make_2d_persp_quad(), GrQuadType::kRect);
list3D.push_back(make_2d_quad(), GrQuadType::kRect);
ASSERTF(list3D.count() == 3, "Unexpected count: %d", list3D.count());
ASSERTF(is_3d_persp_quad(list3D[0]), "Incorrect quad at i=0");
@ -96,8 +96,8 @@ TEST(AddWithMetadata2D) {
GrTQuadList<TestData> list2D;
// Add a plain quad, a 2D persp quad, and then a 3D persp quad, then read back and make sure
// the coordinates make sense (including that the type was lifted to perspective).
list2D.push_back(make_2d_quad(), {1, 1.f});
list2D.push_back(make_2d_persp_quad(), {2, 2.f});
list2D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
list2D.push_back(make_2d_persp_quad(), GrQuadType::kRect, {2, 2.f});
// Check 2D state of the list
ASSERTF(list2D.count() == 2, "Unexpected count: %d", list2D.count());
@ -111,7 +111,7 @@ TEST(AddWithMetadata2D) {
"Incorrect metadata at i=1");
// Force the 2D quads to be updated to store ws by adding a perspective quad
list2D.push_back(make_3d_persp_quad(), {3, 3.f});
list2D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {3, 3.f});
ASSERTF(list2D.quadType() == GrQuadType::kPerspective,
"Expected 2D list to be upgraded to perspective");
@ -132,9 +132,9 @@ TEST(AddWithMetadata3D) {
// Now make a list that starts with a 3D persp quad, then has conventional quads added to it
// and make sure its state is correct
GrTQuadList<TestData> list3D;
list3D.push_back(make_3d_persp_quad(), {3, 3.f});
list3D.push_back(make_2d_persp_quad(), {2, 2.f});
list3D.push_back(make_2d_quad(), {1, 1.f});
list3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {3, 3.f});
list3D.push_back(make_2d_persp_quad(), GrQuadType::kRect, {2, 2.f});
list3D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
ASSERTF(list3D.count() == 3, "Unexpected count: %d", list3D.count());
ASSERTF(is_3d_persp_quad(list3D[0]), "Incorrect quad at i=0");
@ -150,9 +150,9 @@ TEST(AddWithMetadata3D) {
TEST(Concat2DWith2D) {
GrQuadList a2D;
a2D.push_back(make_2d_quad());
a2D.push_back(make_2d_quad(), GrQuadType::kRect);
GrQuadList b2D;
b2D.push_back(make_2d_persp_quad());
b2D.push_back(make_2d_persp_quad(), GrQuadType::kRect);
a2D.concat(b2D);
@ -163,9 +163,9 @@ TEST(Concat2DWith2D) {
TEST(Concat2DWith3D) {
GrQuadList a2D;
a2D.push_back(make_2d_quad());
a2D.push_back(make_2d_quad(), GrQuadType::kRect);
GrQuadList b3D;
b3D.push_back(make_3d_persp_quad());
b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
a2D.concat(b3D);
@ -176,9 +176,9 @@ TEST(Concat2DWith3D) {
TEST(Concat3DWith2D) {
GrQuadList a3D;
a3D.push_back(make_3d_persp_quad());
a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
GrQuadList b2D;
b2D.push_back(make_2d_quad());
b2D.push_back(make_2d_quad(), GrQuadType::kRect);
a3D.concat(b2D);
@ -189,9 +189,9 @@ TEST(Concat3DWith2D) {
TEST(Concat3DWith3D) {
GrQuadList a3D;
a3D.push_back(make_3d_persp_quad());
a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
GrQuadList b3D;
b3D.push_back(make_3d_persp_quad());
b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
a3D.concat(b3D);
@ -202,9 +202,9 @@ TEST(Concat3DWith3D) {
TEST(Concat2DWith2DMetadata) {
GrTQuadList<TestData> a2D;
a2D.push_back(make_2d_quad(), {1, 1.f});
a2D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
GrTQuadList<TestData> b2D;
b2D.push_back(make_2d_persp_quad(), {2, 2.f});
b2D.push_back(make_2d_persp_quad(), GrQuadType::kRect, {2, 2.f});
a2D.concat(b2D);
@ -219,9 +219,9 @@ TEST(Concat2DWith2DMetadata) {
TEST(Concat2DWith3DMetadata) {
GrTQuadList<TestData> a2D;
a2D.push_back(make_2d_quad(), {1, 1.f});
a2D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
GrTQuadList<TestData> b3D;
b3D.push_back(make_3d_persp_quad(), {2, 2.f});
b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {2, 2.f});
a2D.concat(b3D);
@ -236,9 +236,9 @@ TEST(Concat2DWith3DMetadata) {
TEST(Concat3DWith2DMetadata) {
GrTQuadList<TestData> a3D;
a3D.push_back(make_3d_persp_quad(), {1, 1.f});
a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {1, 1.f});
GrTQuadList<TestData> b2D;
b2D.push_back(make_2d_quad(), {2, 2.f});
b2D.push_back(make_2d_quad(), GrQuadType::kRect, {2, 2.f});
a3D.concat(b2D);
@ -253,9 +253,9 @@ TEST(Concat3DWith2DMetadata) {
TEST(Concat3DWith3DMetadata) {
GrTQuadList<TestData> a3D;
a3D.push_back(make_3d_persp_quad(), {1, 1.f});
a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {1, 1.f});
GrTQuadList<TestData> b3D;
b3D.push_back(make_3d_persp_quad(), {2, 2.f});
b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {2, 2.f});
a3D.concat(b3D);
@ -270,7 +270,7 @@ TEST(Concat3DWith3DMetadata) {
TEST(WriteMetadata) {
GrTQuadList<TestData> list;
list.push_back(make_2d_quad(), {1, 1.f});
list.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
ASSERTF(list.metadata(0).fItem1 == 1 && list.metadata(0).fItem2 == 1.f,
"Incorrect metadata at i=0"); // Sanity check