b948572c78
Remove late draw consolidation in GrOpFlushState. Rarely did anything and doesn't work with new allocation strategy. Ops can use GrMesh arrays to acheive the same thing. (Each Op that cared to would have to implement but it isn't applicable to most Ops). Modify GrMeshDrawOp::Target::draw() to take array of meshes, with single mesh as a special case. Change-Id: I552677de47b9ffd2fcaf55af85f70f290e5aa9c7 Reviewed-on: https://skia-review.googlesource.com/145426 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
660 lines
24 KiB
C++
660 lines
24 KiB
C++
/*
|
|
* Copyright 2013 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
// This test only works with the GPU backend.
|
|
|
|
#include "gm.h"
|
|
#include "sk_tool_utils.h"
|
|
|
|
#include "GrContext.h"
|
|
#include "GrMemoryPool.h"
|
|
#include "GrOpFlushState.h"
|
|
#include "GrPathUtils.h"
|
|
#include "GrRenderTargetContextPriv.h"
|
|
#include "GrTest.h"
|
|
#include "SkColorPriv.h"
|
|
#include "SkGeometry.h"
|
|
#include "SkPoint3.h"
|
|
#include "SkPointPriv.h"
|
|
#include "effects/GrBezierEffect.h"
|
|
#include "ops/GrMeshDrawOp.h"
|
|
|
|
namespace skiagm {
|
|
|
|
class BezierTestOp : public GrMeshDrawOp {
|
|
public:
|
|
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
|
|
|
|
RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
|
|
auto analysis = fProcessorSet.finalize(fColor, GrProcessorAnalysisCoverage::kSingleChannel,
|
|
clip, false, caps, &fColor);
|
|
return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
|
|
}
|
|
|
|
void visitProxies(const VisitProxyFunc& func) const override {
|
|
fProcessorSet.visitProxies(func);
|
|
}
|
|
|
|
protected:
|
|
BezierTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
|
|
int32_t classID)
|
|
: INHERITED(classID)
|
|
, fRect(rect)
|
|
, fColor(color)
|
|
, fGeometryProcessor(std::move(gp))
|
|
, fProcessorSet(SkBlendMode::kSrc) {
|
|
this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo);
|
|
}
|
|
|
|
Target::PipelineAndFixedDynamicState makePipeline(Target* target) {
|
|
return target->makePipeline(0, std::move(fProcessorSet), target->detachAppliedClip());
|
|
}
|
|
|
|
sk_sp<const GrGeometryProcessor> gp() const { return fGeometryProcessor; }
|
|
|
|
const SkRect& rect() const { return fRect; }
|
|
GrColor color() const { return fColor; }
|
|
|
|
private:
|
|
bool onCombineIfPossible(GrOp* op, const GrCaps& caps) override { return false; }
|
|
|
|
SkRect fRect;
|
|
GrColor fColor;
|
|
sk_sp<const GrGeometryProcessor> fGeometryProcessor;
|
|
GrProcessorSet fProcessorSet;
|
|
|
|
typedef GrMeshDrawOp INHERITED;
|
|
};
|
|
|
|
class BezierCubicTestOp : public BezierTestOp {
|
|
public:
|
|
DEFINE_OP_CLASS_ID
|
|
|
|
const char* name() const override { return "BezierCubicTestOp"; }
|
|
|
|
static std::unique_ptr<GrDrawOp> Make(GrContext* context,
|
|
sk_sp<const GrGeometryProcessor> gp,
|
|
const SkRect& rect,
|
|
GrColor color) {
|
|
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
|
|
|
|
return pool->allocate<BezierCubicTestOp>(std::move(gp), rect, color);
|
|
}
|
|
|
|
private:
|
|
friend class ::GrOpMemoryPool; // for ctor
|
|
|
|
BezierCubicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
|
|
: INHERITED(std::move(gp), rect, color, ClassID()) {}
|
|
|
|
void onPrepareDraws(Target* target) override {
|
|
SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(SkPoint));
|
|
QuadHelper helper(target, sizeof(SkPoint), 1);
|
|
SkPoint* pts = reinterpret_cast<SkPoint*>(helper.vertices());
|
|
if (!pts) {
|
|
return;
|
|
}
|
|
SkRect rect = this->rect();
|
|
SkPointPriv::SetRectTriStrip(pts, rect, sizeof(SkPoint));
|
|
auto pipe = this->makePipeline(target);
|
|
helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
|
|
}
|
|
|
|
static constexpr int kVertsPerCubic = 4;
|
|
static constexpr int kIndicesPerCubic = 6;
|
|
|
|
typedef BezierTestOp INHERITED;
|
|
};
|
|
|
|
/**
|
|
* This GM directly exercises effects that draw Bezier curves in the GPU backend.
|
|
*/
|
|
class BezierCubicEffects : public GM {
|
|
public:
|
|
BezierCubicEffects() {
|
|
this->setBGColor(0xFFFFFFFF);
|
|
}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("bezier_cubic_effects");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(800, 800);
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
GrRenderTargetContext* renderTargetContext =
|
|
canvas->internal_private_accessTopLayerRenderTargetContext();
|
|
if (!renderTargetContext) {
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
|
return;
|
|
}
|
|
|
|
GrContext* context = canvas->getGrContext();
|
|
if (!context) {
|
|
return;
|
|
}
|
|
|
|
if (!context->contextPriv().caps()->shaderCaps()->floatIs32Bits()) {
|
|
SkPaint paint;
|
|
sk_tool_utils::set_portable_typeface(&paint);
|
|
paint.setAntiAlias(true);
|
|
paint.setTextSize(20);
|
|
|
|
canvas->clear(SK_ColorWHITE);
|
|
canvas->drawString("float != fp32", 20, 40, paint);
|
|
return;
|
|
}
|
|
|
|
struct Vertex {
|
|
SkPoint fPosition;
|
|
float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
|
|
};
|
|
|
|
constexpr int kNumCubics = 15;
|
|
SkRandom rand;
|
|
|
|
// Mult by 3 for each edge effect type
|
|
int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
|
|
int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
|
|
SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
|
|
SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
|
|
int row = 0;
|
|
int col = 0;
|
|
constexpr GrColor color = 0xff000000;
|
|
|
|
for (int i = 0; i < kNumCubics; ++i) {
|
|
SkPoint baseControlPts[] = {
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
|
|
};
|
|
for(GrClipEdgeType edgeType : {GrClipEdgeType::kFillBW,
|
|
GrClipEdgeType::kFillAA,
|
|
GrClipEdgeType::kHairlineAA}) {
|
|
SkScalar x = col * w;
|
|
SkScalar y = row * h;
|
|
SkPoint controlPts[] = {
|
|
{x + baseControlPts[0].fX, y + baseControlPts[0].fY},
|
|
{x + baseControlPts[1].fX, y + baseControlPts[1].fY},
|
|
{x + baseControlPts[2].fX, y + baseControlPts[2].fY},
|
|
{x + baseControlPts[3].fX, y + baseControlPts[3].fY}
|
|
};
|
|
SkPoint chopped[10];
|
|
SkMatrix klm;
|
|
int loopIndex;
|
|
int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
|
|
chopped,
|
|
&klm,
|
|
&loopIndex);
|
|
|
|
SkPaint ctrlPtPaint;
|
|
ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
|
|
canvas->drawCircle(controlPts[0], 8.f, ctrlPtPaint);
|
|
for (int i = 1; i < 4; ++i) {
|
|
canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
|
|
}
|
|
|
|
SkPaint polyPaint;
|
|
polyPaint.setColor(0xffA0A0A0);
|
|
polyPaint.setStrokeWidth(0);
|
|
polyPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
|
|
|
|
SkPaint choppedPtPaint;
|
|
choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
|
|
|
|
for (int c = 0; c < cnt; ++c) {
|
|
SkPoint* pts = chopped + 3 * c;
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
|
|
}
|
|
|
|
SkRect bounds;
|
|
bounds.set(pts, 4);
|
|
|
|
SkPaint boundsPaint;
|
|
boundsPaint.setColor(0xff808080);
|
|
boundsPaint.setStrokeWidth(0);
|
|
boundsPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawRect(bounds, boundsPaint);
|
|
|
|
|
|
bool flipKL = (c == loopIndex && cnt != 3);
|
|
sk_sp<GrGeometryProcessor> gp =
|
|
GrCubicEffect::Make(color, SkMatrix::I(), klm, flipKL, edgeType,
|
|
*context->contextPriv().caps());
|
|
if (!gp) {
|
|
break;
|
|
}
|
|
|
|
std::unique_ptr<GrDrawOp> op =
|
|
BezierCubicTestOp::Make(context, std::move(gp), bounds, color);
|
|
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
|
|
}
|
|
++col;
|
|
if (numCols == col) {
|
|
col = 0;
|
|
++row;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
typedef GM INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class BezierConicTestOp : public BezierTestOp {
|
|
public:
|
|
DEFINE_OP_CLASS_ID
|
|
|
|
const char* name() const override { return "BezierConicTestOp"; }
|
|
|
|
static std::unique_ptr<GrDrawOp> Make(GrContext* context,
|
|
sk_sp<const GrGeometryProcessor> gp,
|
|
const SkRect& rect,
|
|
GrColor color,
|
|
const SkMatrix& klm) {
|
|
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
|
|
|
|
return pool->allocate<BezierConicTestOp>(std::move(gp), rect, color, klm);
|
|
}
|
|
|
|
private:
|
|
friend class ::GrOpMemoryPool; // for ctor
|
|
|
|
BezierConicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
|
|
const SkMatrix& klm)
|
|
: INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
|
|
|
|
struct Vertex {
|
|
SkPoint fPosition;
|
|
float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
|
|
};
|
|
|
|
void onPrepareDraws(Target* target) override {
|
|
SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
|
|
QuadHelper helper(target, sizeof(Vertex), 1);
|
|
Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
|
|
if (!verts) {
|
|
return;
|
|
}
|
|
SkRect rect = this->rect();
|
|
SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
|
|
rect.fBottom, sizeof(Vertex));
|
|
for (int v = 0; v < 4; ++v) {
|
|
SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
|
|
fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
|
|
}
|
|
auto pipe = this->makePipeline(target);
|
|
helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
|
|
}
|
|
|
|
SkMatrix fKLM;
|
|
|
|
static constexpr int kVertsPerCubic = 4;
|
|
static constexpr int kIndicesPerCubic = 6;
|
|
|
|
typedef BezierTestOp INHERITED;
|
|
};
|
|
|
|
|
|
/**
|
|
* This GM directly exercises effects that draw Bezier curves in the GPU backend.
|
|
*/
|
|
class BezierConicEffects : public GM {
|
|
public:
|
|
BezierConicEffects() {
|
|
this->setBGColor(0xFFFFFFFF);
|
|
}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("bezier_conic_effects");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(800, 800);
|
|
}
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
GrRenderTargetContext* renderTargetContext =
|
|
canvas->internal_private_accessTopLayerRenderTargetContext();
|
|
if (!renderTargetContext) {
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
|
return;
|
|
}
|
|
|
|
GrContext* context = canvas->getGrContext();
|
|
if (!context) {
|
|
return;
|
|
}
|
|
|
|
struct Vertex {
|
|
SkPoint fPosition;
|
|
float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
|
|
};
|
|
|
|
constexpr int kNumConics = 10;
|
|
SkRandom rand;
|
|
|
|
// Mult by 3 for each edge effect type
|
|
int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
|
|
int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
|
|
SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
|
|
SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
|
|
int row = 0;
|
|
int col = 0;
|
|
constexpr GrColor color = 0xff000000;
|
|
|
|
for (int i = 0; i < kNumConics; ++i) {
|
|
SkPoint baseControlPts[] = {
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
|
|
};
|
|
SkScalar weight = rand.nextRangeF(0.f, 2.f);
|
|
for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
|
|
sk_sp<GrGeometryProcessor> gp;
|
|
GrClipEdgeType et = (GrClipEdgeType)edgeType;
|
|
gp = GrConicEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
|
|
SkMatrix::I(), false);
|
|
if (!gp) {
|
|
continue;
|
|
}
|
|
|
|
SkScalar x = col * w;
|
|
SkScalar y = row * h;
|
|
SkPoint controlPts[] = {
|
|
{x + baseControlPts[0].fX, y + baseControlPts[0].fY},
|
|
{x + baseControlPts[1].fX, y + baseControlPts[1].fY},
|
|
{x + baseControlPts[2].fX, y + baseControlPts[2].fY}
|
|
};
|
|
SkConic dst[4];
|
|
SkMatrix klm;
|
|
int cnt = chop_conic(controlPts, dst, weight);
|
|
GrPathUtils::getConicKLM(controlPts, weight, &klm);
|
|
|
|
SkPaint ctrlPtPaint;
|
|
ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
|
|
for (int i = 0; i < 3; ++i) {
|
|
canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
|
|
}
|
|
|
|
SkPaint polyPaint;
|
|
polyPaint.setColor(0xffA0A0A0);
|
|
polyPaint.setStrokeWidth(0);
|
|
polyPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
|
|
|
|
SkPaint choppedPtPaint;
|
|
choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
|
|
|
|
for (int c = 0; c < cnt; ++c) {
|
|
SkPoint* pts = dst[c].fPts;
|
|
for (int i = 0; i < 3; ++i) {
|
|
canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
|
|
}
|
|
|
|
SkRect bounds;
|
|
//SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
|
|
//bounds.set(bPts, 2);
|
|
bounds.set(pts, 3);
|
|
|
|
SkPaint boundsPaint;
|
|
boundsPaint.setColor(0xff808080);
|
|
boundsPaint.setStrokeWidth(0);
|
|
boundsPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawRect(bounds, boundsPaint);
|
|
|
|
std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, gp, bounds,
|
|
color, klm);
|
|
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
|
|
}
|
|
++col;
|
|
if (numCols == col) {
|
|
col = 0;
|
|
++row;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
// Uses the max curvature function for quads to estimate
|
|
// where to chop the conic. If the max curvature is not
|
|
// found along the curve segment it will return 1 and
|
|
// dst[0] is the original conic. If it returns 2 the dst[0]
|
|
// and dst[1] are the two new conics.
|
|
int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
|
|
SkScalar t = SkFindQuadMaxCurvature(src);
|
|
if (t == 0 || t == 1) {
|
|
if (dst) {
|
|
dst[0].set(src, weight);
|
|
}
|
|
return 1;
|
|
} else {
|
|
if (dst) {
|
|
SkConic conic;
|
|
conic.set(src, weight);
|
|
if (!conic.chopAt(t, dst)) {
|
|
dst[0].set(src, weight);
|
|
return 1;
|
|
}
|
|
}
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
// Calls split_conic on the entire conic and then once more on each subsection.
|
|
// Most cases will result in either 1 conic (chop point is not within t range)
|
|
// or 3 points (split once and then one subsection is split again).
|
|
int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
|
|
SkConic dstTemp[2];
|
|
int conicCnt = split_conic(src, dstTemp, weight);
|
|
if (2 == conicCnt) {
|
|
int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
|
|
conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
|
|
} else {
|
|
dst[0] = dstTemp[0];
|
|
}
|
|
return conicCnt;
|
|
}
|
|
|
|
typedef GM INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class BezierQuadTestOp : public BezierTestOp {
|
|
public:
|
|
DEFINE_OP_CLASS_ID
|
|
const char* name() const override { return "BezierQuadTestOp"; }
|
|
|
|
static std::unique_ptr<GrDrawOp> Make(GrContext* context,
|
|
sk_sp<const GrGeometryProcessor> gp,
|
|
const SkRect& rect,
|
|
GrColor color,
|
|
const GrPathUtils::QuadUVMatrix& devToUV) {
|
|
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
|
|
|
|
return pool->allocate<BezierQuadTestOp>(std::move(gp), rect, color, devToUV);
|
|
}
|
|
|
|
private:
|
|
friend class ::GrOpMemoryPool; // for ctor
|
|
|
|
BezierQuadTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
|
|
const GrPathUtils::QuadUVMatrix& devToUV)
|
|
: INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
|
|
|
|
struct Vertex {
|
|
SkPoint fPosition;
|
|
float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
|
|
};
|
|
|
|
void onPrepareDraws(Target* target) override {
|
|
SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
|
|
QuadHelper helper(target, sizeof(Vertex), 1);
|
|
Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
|
|
if (!verts) {
|
|
return;
|
|
}
|
|
SkRect rect = this->rect();
|
|
SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
|
|
fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
|
|
auto pipe = this->makePipeline(target);
|
|
helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
|
|
}
|
|
|
|
GrPathUtils::QuadUVMatrix fDevToUV;
|
|
|
|
static constexpr int kVertsPerCubic = 4;
|
|
static constexpr int kIndicesPerCubic = 6;
|
|
|
|
typedef BezierTestOp INHERITED;
|
|
};
|
|
|
|
/**
|
|
* This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
|
|
*/
|
|
class BezierQuadEffects : public GM {
|
|
public:
|
|
BezierQuadEffects() {
|
|
this->setBGColor(0xFFFFFFFF);
|
|
}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("bezier_quad_effects");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(800, 800);
|
|
}
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
GrRenderTargetContext* renderTargetContext =
|
|
canvas->internal_private_accessTopLayerRenderTargetContext();
|
|
if (!renderTargetContext) {
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
|
return;
|
|
}
|
|
|
|
GrContext* context = canvas->getGrContext();
|
|
if (!context) {
|
|
return;
|
|
}
|
|
|
|
struct Vertex {
|
|
SkPoint fPosition;
|
|
float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
|
|
};
|
|
|
|
constexpr int kNumQuads = 5;
|
|
SkRandom rand;
|
|
|
|
int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
|
|
int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
|
|
SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
|
|
SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
|
|
int row = 0;
|
|
int col = 0;
|
|
constexpr GrColor color = 0xff000000;
|
|
|
|
for (int i = 0; i < kNumQuads; ++i) {
|
|
SkPoint baseControlPts[] = {
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
|
|
{rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
|
|
};
|
|
for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
|
|
sk_sp<GrGeometryProcessor> gp;
|
|
GrClipEdgeType et = (GrClipEdgeType)edgeType;
|
|
gp = GrQuadEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
|
|
SkMatrix::I(), false);
|
|
if (!gp) {
|
|
continue;
|
|
}
|
|
|
|
SkScalar x = col * w;
|
|
SkScalar y = row * h;
|
|
SkPoint controlPts[] = {
|
|
{x + baseControlPts[0].fX, y + baseControlPts[0].fY},
|
|
{x + baseControlPts[1].fX, y + baseControlPts[1].fY},
|
|
{x + baseControlPts[2].fX, y + baseControlPts[2].fY}
|
|
};
|
|
SkPoint chopped[5];
|
|
int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
|
|
|
|
SkPaint ctrlPtPaint;
|
|
ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
|
|
for (int i = 0; i < 3; ++i) {
|
|
canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
|
|
}
|
|
|
|
SkPaint polyPaint;
|
|
polyPaint.setColor(0xffA0A0A0);
|
|
polyPaint.setStrokeWidth(0);
|
|
polyPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
|
|
|
|
SkPaint choppedPtPaint;
|
|
choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
|
|
|
|
for (int c = 0; c < cnt; ++c) {
|
|
SkPoint* pts = chopped + 2 * c;
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
|
|
}
|
|
|
|
SkRect bounds;
|
|
bounds.set(pts, 3);
|
|
|
|
SkPaint boundsPaint;
|
|
boundsPaint.setColor(0xff808080);
|
|
boundsPaint.setStrokeWidth(0);
|
|
boundsPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawRect(bounds, boundsPaint);
|
|
|
|
GrPaint grPaint;
|
|
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
|
|
|
|
GrPathUtils::QuadUVMatrix DevToUV(pts);
|
|
|
|
std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, gp,
|
|
bounds, color, DevToUV);
|
|
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
|
|
}
|
|
++col;
|
|
if (numCols == col) {
|
|
col = 0;
|
|
++row;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
typedef GM INHERITED;
|
|
};
|
|
|
|
DEF_GM(return new BezierCubicEffects;)
|
|
DEF_GM(return new BezierConicEffects;)
|
|
DEF_GM(return new BezierQuadEffects;)
|
|
}
|