CCPR: Rename GrCCPR* -> GrCC*

Also runs clang-format on the files that don't have special shader
builder styling.

Bug: skia:
Change-Id: I4a67569a7c8472acfb9200644c913844a92e3b2d
Reviewed-on: https://skia-review.googlesource.com/92083
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Chris Dalton 2018-01-08 17:21:41 -05:00 committed by Skia Commit-Bot
parent c35959f3cb
commit 383a2ef6ed
26 changed files with 562 additions and 593 deletions

View File

@ -296,26 +296,26 @@ skia_gpu_sources = [
"$_src/gpu/ops/GrTextureOp.h", "$_src/gpu/ops/GrTextureOp.h",
# coverage counting path renderer # coverage counting path renderer
"$_src/gpu/ccpr/GrCCPRAtlas.cpp", "$_src/gpu/ccpr/GrCCAtlas.cpp",
"$_src/gpu/ccpr/GrCCPRAtlas.h", "$_src/gpu/ccpr/GrCCAtlas.h",
"$_src/gpu/ccpr/GrCCPRClipProcessor.cpp", "$_src/gpu/ccpr/GrCCClipProcessor.cpp",
"$_src/gpu/ccpr/GrCCPRClipProcessor.h", "$_src/gpu/ccpr/GrCCClipProcessor.h",
"$_src/gpu/ccpr/GrCCPRCoverageOp.cpp", "$_src/gpu/ccpr/GrCCCoverageOp.cpp",
"$_src/gpu/ccpr/GrCCPRCoverageOp.h", "$_src/gpu/ccpr/GrCCCoverageOp.h",
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.cpp", "$_src/gpu/ccpr/GrCCCoverageProcessor.cpp",
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp", "$_src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp",
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp", "$_src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp",
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.h", "$_src/gpu/ccpr/GrCCCoverageProcessor.h",
"$_src/gpu/ccpr/GrCCPRCubicShader.cpp", "$_src/gpu/ccpr/GrCCCubicShader.cpp",
"$_src/gpu/ccpr/GrCCPRCubicShader.h", "$_src/gpu/ccpr/GrCCCubicShader.h",
"$_src/gpu/ccpr/GrCCPRGeometry.cpp", "$_src/gpu/ccpr/GrCCGeometry.cpp",
"$_src/gpu/ccpr/GrCCPRGeometry.h", "$_src/gpu/ccpr/GrCCGeometry.h",
"$_src/gpu/ccpr/GrCCPRPathProcessor.cpp", "$_src/gpu/ccpr/GrCCPathProcessor.cpp",
"$_src/gpu/ccpr/GrCCPRPathProcessor.h", "$_src/gpu/ccpr/GrCCPathProcessor.h",
"$_src/gpu/ccpr/GrCCPRQuadraticShader.cpp", "$_src/gpu/ccpr/GrCCQuadraticShader.cpp",
"$_src/gpu/ccpr/GrCCPRQuadraticShader.h", "$_src/gpu/ccpr/GrCCQuadraticShader.h",
"$_src/gpu/ccpr/GrCCPRTriangleShader.cpp", "$_src/gpu/ccpr/GrCCTriangleShader.cpp",
"$_src/gpu/ccpr/GrCCPRTriangleShader.h", "$_src/gpu/ccpr/GrCCTriangleShader.h",
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp", "$_src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp",
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h", "$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h",

View File

@ -21,18 +21,18 @@
#include "SkPath.h" #include "SkPath.h"
#include "SkRectPriv.h" #include "SkRectPriv.h"
#include "SkView.h" #include "SkView.h"
#include "ccpr/GrCCPRCoverageProcessor.h" #include "ccpr/GrCCCoverageProcessor.h"
#include "ccpr/GrCCPRGeometry.h" #include "ccpr/GrCCGeometry.h"
#include "gl/GrGLGpu.cpp" #include "gl/GrGLGpu.cpp"
#include "ops/GrDrawOp.h" #include "ops/GrDrawOp.h"
using TriangleInstance = GrCCPRCoverageProcessor::TriangleInstance; using TriangleInstance = GrCCCoverageProcessor::TriangleInstance;
using CubicInstance = GrCCPRCoverageProcessor::CubicInstance; using CubicInstance = GrCCCoverageProcessor::CubicInstance;
using RenderPass = GrCCPRCoverageProcessor::RenderPass; using RenderPass = GrCCCoverageProcessor::RenderPass;
static constexpr float kDebugBloat = 40; static constexpr float kDebugBloat = 40;
static int is_quadratic(RenderPass pass) { static int is_quadratic(RenderPass pass) {
return pass == RenderPass::kQuadraticHulls || pass == RenderPass::kQuadraticCorners; return pass == RenderPass::kQuadraticHulls || pass == RenderPass::kQuadraticCorners;
} }
@ -55,9 +55,7 @@ private:
class Click; class Click;
class Op; class Op;
void updateAndInval() { void updateAndInval() { this->updateGpuData(); }
this->updateGpuData();
}
void updateGpuData(); void updateGpuData();
@ -66,11 +64,7 @@ private:
SkMatrix fCubicKLM; SkMatrix fCubicKLM;
SkPoint fPoints[4] = { SkPoint fPoints[4] = {
{100.05f, 100.05f}, {100.05f, 100.05f}, {400.75f, 100.05f}, {400.75f, 300.95f}, {100.05f, 300.95f}};
{400.75f, 100.05f},
{400.75f, 300.95f},
{100.05f, 300.95f}
};
SkTArray<TriangleInstance> fTriangleInstances; SkTArray<TriangleInstance> fTriangleInstances;
SkTArray<CubicInstance> fCubicInstances; SkTArray<CubicInstance> fCubicInstances;
@ -82,9 +76,7 @@ class CCPRGeometryView::Op : public GrDrawOp {
DEFINE_OP_CLASS_ID DEFINE_OP_CLASS_ID
public: public:
Op(CCPRGeometryView* view) Op(CCPRGeometryView* view) : INHERITED(ClassID()), fView(view) {
: INHERITED(ClassID())
, fView(view) {
this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo); this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
} }
@ -110,11 +102,11 @@ static void draw_klm_line(int w, int h, SkCanvas* canvas, const SkScalar line[3]
if (SkScalarAbs(line[1]) > SkScalarAbs(line[0])) { if (SkScalarAbs(line[1]) > SkScalarAbs(line[0])) {
// Draw from vertical edge to vertical edge. // Draw from vertical edge to vertical edge.
p1 = {0, -line[2] / line[1]}; p1 = {0, -line[2] / line[1]};
p2 = {(SkScalar) w, (-line[2] - w * line[0]) / line[1]}; p2 = {(SkScalar)w, (-line[2] - w * line[0]) / line[1]};
} else { } else {
// Draw from horizontal edge to horizontal edge. // Draw from horizontal edge to horizontal edge.
p1 = {-line[2] / line[0], 0}; p1 = {-line[2] / line[0], 0};
p2 = {(-line[2] - h * line[1]) / line[0], (SkScalar) h}; p2 = {(-line[2] - h * line[1]) / line[0], (SkScalar)h};
} }
SkPaint linePaint; SkPaint linePaint;
@ -132,7 +124,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
SkPath outline; SkPath outline;
outline.moveTo(fPoints[0]); outline.moveTo(fPoints[0]);
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) { if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
outline.cubicTo(fPoints[1], fPoints[2], fPoints[3]); outline.cubicTo(fPoints[1], fPoints[2], fPoints[3]);
} else if (is_quadratic(fRenderPass)) { } else if (is_quadratic(fRenderPass)) {
outline.quadTo(fPoints[1], fPoints[3]); outline.quadTo(fPoints[1], fPoints[3]);
@ -164,11 +156,10 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
#endif #endif
SkString caption; SkString caption;
if (GrRenderTargetContext* rtc = if (GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext()) {
canvas->internal_private_accessTopLayerRenderTargetContext()) {
rtc->priv().testingOnly_addDrawOp(skstd::make_unique<Op>(this)); rtc->priv().testingOnly_addDrawOp(skstd::make_unique<Op>(this));
caption.appendf("RenderPass_%s", GrCCPRCoverageProcessor::RenderPassName(fRenderPass)); caption.appendf("RenderPass_%s", GrCCCoverageProcessor::RenderPassName(fRenderPass));
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) { if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
caption.appendf(" (%s)", SkCubicTypeName(fCubicType)); caption.appendf(" (%s)", SkCubicTypeName(fCubicType));
} }
} else { } else {
@ -180,7 +171,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
pointsPaint.setStrokeWidth(8); pointsPaint.setStrokeWidth(8);
pointsPaint.setAntiAlias(true); pointsPaint.setAntiAlias(true);
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) { if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
int w = this->width(), h = this->height(); int w = this->width(), h = this->height();
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint); canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
draw_klm_line(w, h, canvas, &fCubicKLM[0], SK_ColorYELLOW); draw_klm_line(w, h, canvas, &fCubicKLM[0], SK_ColorYELLOW);
@ -202,46 +193,47 @@ void CCPRGeometryView::updateGpuData() {
fTriangleInstances.reset(); fTriangleInstances.reset();
fCubicInstances.reset(); fCubicInstances.reset();
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) { if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
double t[2], s[2]; double t[2], s[2];
fCubicType = GrPathUtils::getCubicKLM(fPoints, &fCubicKLM, t, s); fCubicType = GrPathUtils::getCubicKLM(fPoints, &fCubicKLM, t, s);
GrCCPRGeometry geometry; GrCCGeometry geometry;
geometry.beginContour(fPoints[0]); geometry.beginContour(fPoints[0]);
geometry.cubicTo(fPoints[1], fPoints[2], fPoints[3], kDebugBloat/2, kDebugBloat/2); geometry.cubicTo(fPoints[1], fPoints[2], fPoints[3], kDebugBloat / 2, kDebugBloat / 2);
geometry.endContour(); geometry.endContour();
int ptsIdx = 0; int ptsIdx = 0;
for (GrCCPRGeometry::Verb verb : geometry.verbs()) { for (GrCCGeometry::Verb verb : geometry.verbs()) {
switch (verb) { switch (verb) {
case GrCCPRGeometry::Verb::kLineTo: case GrCCGeometry::Verb::kLineTo:
++ptsIdx; ++ptsIdx;
continue; continue;
case GrCCPRGeometry::Verb::kMonotonicQuadraticTo: case GrCCGeometry::Verb::kMonotonicQuadraticTo:
ptsIdx += 2; ptsIdx += 2;
continue; continue;
case GrCCPRGeometry::Verb::kMonotonicCubicTo: case GrCCGeometry::Verb::kMonotonicCubicTo:
fCubicInstances.push_back().set(&geometry.points()[ptsIdx], 0, 0); fCubicInstances.push_back().set(&geometry.points()[ptsIdx], 0, 0);
ptsIdx += 3; ptsIdx += 3;
continue; continue;
default: continue; default:
continue;
} }
} }
} else if (is_quadratic(fRenderPass)) { } else if (is_quadratic(fRenderPass)) {
GrCCPRGeometry geometry; GrCCGeometry geometry;
geometry.beginContour(fPoints[0]); geometry.beginContour(fPoints[0]);
geometry.quadraticTo(fPoints[1], fPoints[3]); geometry.quadraticTo(fPoints[1], fPoints[3]);
geometry.endContour(); geometry.endContour();
int ptsIdx = 0; int ptsIdx = 0;
for (GrCCPRGeometry::Verb verb : geometry.verbs()) { for (GrCCGeometry::Verb verb : geometry.verbs()) {
if (GrCCPRGeometry::Verb::kBeginContour == verb || if (GrCCGeometry::Verb::kBeginContour == verb ||
GrCCPRGeometry::Verb::kEndOpenContour == verb || GrCCGeometry::Verb::kEndOpenContour == verb ||
GrCCPRGeometry::Verb::kEndClosedContour == verb) { GrCCGeometry::Verb::kEndClosedContour == verb) {
continue; continue;
} }
if (GrCCPRGeometry::Verb::kLineTo == verb) { if (GrCCGeometry::Verb::kLineTo == verb) {
++ptsIdx; ++ptsIdx;
continue; continue;
} }
SkASSERT(GrCCPRGeometry::Verb::kMonotonicQuadraticTo == verb); SkASSERT(GrCCGeometry::Verb::kMonotonicQuadraticTo == verb);
fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0)); fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0));
ptsIdx += 2; ptsIdx += 2;
} }
@ -253,34 +245,34 @@ void CCPRGeometryView::updateGpuData() {
void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) { void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) {
GrResourceProvider* rp = state->resourceProvider(); GrResourceProvider* rp = state->resourceProvider();
GrContext* context = state->gpu()->getContext(); GrContext* context = state->gpu()->getContext();
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend() ? GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend()
static_cast<GrGLGpu*>(state->gpu()) : nullptr; ? static_cast<GrGLGpu*>(state->gpu())
: nullptr;
if (!GrCCPRCoverageProcessor::DoesRenderPass(fView->fRenderPass, *state->caps().shaderCaps())) { if (!GrCCCoverageProcessor::DoesRenderPass(fView->fRenderPass, *state->caps().shaderCaps())) {
return; return;
} }
GrCCPRCoverageProcessor proc(rp, fView->fRenderPass, *state->caps().shaderCaps()); GrCCCoverageProcessor proc(rp, fView->fRenderPass, *state->caps().shaderCaps());
SkDEBUGCODE(proc.enableDebugVisualizations(kDebugBloat);) SkDEBUGCODE(proc.enableDebugVisualizations(kDebugBloat);)
SkSTArray<1, GrMesh> mesh; SkSTArray<1, GrMesh>
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) { mesh;
sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fCubicInstances.count() * if (GrCCCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) {
sizeof(CubicInstance), kVertex_GrBufferType, sk_sp<GrBuffer> instBuff(rp->createBuffer(
kDynamic_GrAccessPattern, fView->fCubicInstances.count() * sizeof(CubicInstance), kVertex_GrBufferType,
GrResourceProvider::kNoPendingIO_Flag | kDynamic_GrAccessPattern,
GrResourceProvider::kRequireGpuMemory_Flag, GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag,
fView->fCubicInstances.begin())); fView->fCubicInstances.begin()));
if (!fView->fCubicInstances.empty() && instBuff) { if (!fView->fCubicInstances.empty() && instBuff) {
proc.appendMesh(instBuff.get(), fView->fCubicInstances.count(), 0, &mesh); proc.appendMesh(instBuff.get(), fView->fCubicInstances.count(), 0, &mesh);
} }
} else { } else {
sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fTriangleInstances.count() * sk_sp<GrBuffer> instBuff(rp->createBuffer(
sizeof(TriangleInstance), kVertex_GrBufferType, fView->fTriangleInstances.count() * sizeof(TriangleInstance), kVertex_GrBufferType,
kDynamic_GrAccessPattern, kDynamic_GrAccessPattern,
GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag,
GrResourceProvider::kRequireGpuMemory_Flag, fView->fTriangleInstances.begin()));
fView->fTriangleInstances.begin()));
if (!fView->fTriangleInstances.empty() && instBuff) { if (!fView->fTriangleInstances.empty() && instBuff) {
proc.appendMesh(instBuff.get(), fView->fTriangleInstances.count(), 0, &mesh); proc.appendMesh(instBuff.get(), fView->fTriangleInstances.count(), 0, &mesh);
} }
@ -320,7 +312,7 @@ public:
} }
private: private:
void dragPoint(SkPoint points[], int idx) { void dragPoint(SkPoint points[], int idx) {
SkIPoint delta = fICurr - fIPrev; SkIPoint delta = fICurr - fIPrev;
points[idx] += SkPoint::Make(delta.x(), delta.y()); points[idx] += SkPoint::Make(delta.x(), delta.y());
} }
@ -330,7 +322,7 @@ private:
SkView::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, unsigned) { SkView::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, unsigned) {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
if (!GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass) && 2 == i) { if (!GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass) && 2 == i) {
continue; continue;
} }
if (fabs(x - fPoints[i].x()) < 20 && fabsf(y - fPoints[i].y()) < 20) { if (fabs(x - fPoints[i].x()) < 20 && fabsf(y - fPoints[i].y()) < 20) {
@ -341,7 +333,7 @@ SkView::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, unsi
} }
bool CCPRGeometryView::onClick(SampleView::Click* click) { bool CCPRGeometryView::onClick(SampleView::Click* click) {
Click* myClick = (Click*) click; Click* myClick = (Click*)click;
myClick->doClick(fPoints); myClick->doClick(fPoints);
this->updateAndInval(); this->updateAndInval();
return true; return true;
@ -372,6 +364,6 @@ bool CCPRGeometryView::onQuery(SkEvent* evt) {
return this->INHERITED::onQuery(evt); return this->INHERITED::onQuery(evt);
} }
DEF_SAMPLE( return new CCPRGeometryView; ) DEF_SAMPLE(return new CCPRGeometryView;)
#endif // SK_SUPPORT_GPU #endif // SK_SUPPORT_GPU

View File

@ -67,7 +67,6 @@ public:
enum ClassID { enum ClassID {
kBigKeyProcessor_ClassID, kBigKeyProcessor_ClassID,
kBlockInputFragmentProcessor_ClassID, kBlockInputFragmentProcessor_ClassID,
kCCPRClipProcessor_ClassID,
kCircleGeometryProcessor_ClassID, kCircleGeometryProcessor_ClassID,
kCircularRRectEffect_ClassID, kCircularRRectEffect_ClassID,
kColorMatrixEffect_ClassID, kColorMatrixEffect_ClassID,
@ -91,8 +90,9 @@ public:
kGrBicubicEffect_ClassID, kGrBicubicEffect_ClassID,
kGrBitmapTextGeoProc_ClassID, kGrBitmapTextGeoProc_ClassID,
kGrBlurredEdgeFragmentProcessor_ClassID, kGrBlurredEdgeFragmentProcessor_ClassID,
kGrCCPRCoverageProcessor_ClassID, kGrCCClipProcessor_ClassID,
kGrCCPRPathProcessor_ClassID, kGrCCCoverageProcessor_ClassID,
kGrCCPathProcessor_ClassID,
kGrCircleBlurFragmentProcessor_ClassID, kGrCircleBlurFragmentProcessor_ClassID,
kGrCircleEffect_ClassID, kGrCircleEffect_ClassID,
kGrColorSpaceXformEffect_ClassID, kGrColorSpaceXformEffect_ClassID,

View File

@ -409,7 +409,7 @@ private:
friend class GrMSAAPathRenderer; // for access to add[Mesh]DrawOp friend class GrMSAAPathRenderer; // for access to add[Mesh]DrawOp
friend class GrStencilAndCoverPathRenderer; // for access to add[Mesh]DrawOp friend class GrStencilAndCoverPathRenderer; // for access to add[Mesh]DrawOp
friend class GrTessellatingPathRenderer; // for access to add[Mesh]DrawOp friend class GrTessellatingPathRenderer; // for access to add[Mesh]DrawOp
friend class GrCCPRAtlas; // for access to addDrawOp friend class GrCCAtlas; // for access to addDrawOp
friend class GrCoverageCountingPathRenderer; // for access to addDrawOp friend class GrCoverageCountingPathRenderer; // for access to addDrawOp
// for a unit test // for a unit test
friend void test_draw_op(GrRenderTargetContext*, std::unique_ptr<GrFragmentProcessor>, friend void test_draw_op(GrRenderTargetContext*, std::unique_ptr<GrFragmentProcessor>,

View File

@ -5,24 +5,22 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRAtlas.h" #include "GrCCAtlas.h"
#include "GrOnFlushResourceProvider.h"
#include "GrClip.h" #include "GrClip.h"
#include "GrOnFlushResourceProvider.h"
#include "GrRectanizer_skyline.h" #include "GrRectanizer_skyline.h"
#include "GrTextureProxy.h"
#include "GrRenderTargetContext.h" #include "GrRenderTargetContext.h"
#include "GrTextureProxy.h"
#include "SkMakeUnique.h" #include "SkMakeUnique.h"
#include "SkMathPriv.h" #include "SkMathPriv.h"
#include "ccpr/GrCCPRCoverageProcessor.h" #include "ccpr/GrCCCoverageProcessor.h"
#include "ops/GrDrawOp.h" #include "ops/GrDrawOp.h"
class GrCCPRAtlas::Node { class GrCCAtlas::Node {
public: public:
Node(std::unique_ptr<Node> previous, int l, int t, int r, int b) Node(std::unique_ptr<Node> previous, int l, int t, int r, int b)
: fPrevious(std::move(previous)) : fPrevious(std::move(previous)), fX(l), fY(t), fRectanizer(r - l, b - t) {}
, fX(l), fY(t)
, fRectanizer(r - l, b - t) {}
Node* previous() const { return fPrevious.get(); } Node* previous() const { return fPrevious.get(); }
@ -38,14 +36,13 @@ public:
} }
private: private:
const std::unique_ptr<Node> fPrevious; const std::unique_ptr<Node> fPrevious;
const int fX, fY; const int fX, fY;
GrRectanizerSkyline fRectanizer; GrRectanizerSkyline fRectanizer;
}; };
GrCCPRAtlas::GrCCPRAtlas(const GrCaps& caps, int minWidth, int minHeight) GrCCAtlas::GrCCAtlas(const GrCaps& caps, int minWidth, int minHeight)
: fMaxAtlasSize(caps.maxRenderTargetSize()) : fMaxAtlasSize(caps.maxRenderTargetSize()), fDrawBounds{0, 0} {
, fDrawBounds{0, 0} {
SkASSERT(fMaxAtlasSize <= caps.maxTextureSize()); SkASSERT(fMaxAtlasSize <= caps.maxTextureSize());
SkASSERT(SkTMax(minWidth, minHeight) <= fMaxAtlasSize); SkASSERT(SkTMax(minWidth, minHeight) <= fMaxAtlasSize);
int initialSize = GrNextPow2(SkTMax(minWidth, minHeight)); int initialSize = GrNextPow2(SkTMax(minWidth, minHeight));
@ -55,10 +52,9 @@ GrCCPRAtlas::GrCCPRAtlas(const GrCaps& caps, int minWidth, int minHeight)
fTopNode = skstd::make_unique<Node>(nullptr, 0, 0, initialSize, initialSize); fTopNode = skstd::make_unique<Node>(nullptr, 0, 0, initialSize, initialSize);
} }
GrCCPRAtlas::~GrCCPRAtlas() { GrCCAtlas::~GrCCAtlas() {}
}
bool GrCCPRAtlas::addRect(int w, int h, SkIPoint16* loc) { bool GrCCAtlas::addRect(int w, int h, SkIPoint16* loc) {
// This can't be called anymore once finalize() has been called. // This can't be called anymore once finalize() has been called.
SkASSERT(!fTextureProxy); SkASSERT(!fTextureProxy);
@ -71,7 +67,7 @@ bool GrCCPRAtlas::addRect(int w, int h, SkIPoint16* loc) {
return true; return true;
} }
bool GrCCPRAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) { bool GrCCAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
SkASSERT(SkTMax(w, h) < fMaxAtlasSize); SkASSERT(SkTMax(w, h) < fMaxAtlasSize);
for (Node* node = fTopNode.get(); node; node = node->previous()) { for (Node* node = fTopNode.get(); node; node = node->previous()) {
@ -100,8 +96,8 @@ bool GrCCPRAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
return true; return true;
} }
sk_sp<GrRenderTargetContext> GrCCPRAtlas::finalize(GrOnFlushResourceProvider* onFlushRP, sk_sp<GrRenderTargetContext> GrCCAtlas::finalize(
std::unique_ptr<GrDrawOp> atlasOp) { GrOnFlushResourceProvider* onFlushRP, std::unique_ptr<GrDrawOp> atlasOp) {
SkASSERT(!fTextureProxy); SkASSERT(!fTextureProxy);
GrSurfaceDesc desc; GrSurfaceDesc desc;

View File

@ -5,8 +5,8 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRAtlas_DEFINED #ifndef GrCCAtlas_DEFINED
#define GrCCPRAtlas_DEFINED #define GrCCAtlas_DEFINED
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "SkSize.h" #include "SkSize.h"
@ -23,18 +23,18 @@ struct SkIPoint16;
* dependent max texture size. When finalized, it also creates and stores a GrTextureProxy for the * dependent max texture size. When finalized, it also creates and stores a GrTextureProxy for the
* underlying atlas. * underlying atlas.
*/ */
class GrCCPRAtlas { class GrCCAtlas {
public: public:
static constexpr int kMinSize = 1024; static constexpr int kMinSize = 1024;
GrCCPRAtlas(const GrCaps&, int minWidth, int minHeight); GrCCAtlas(const GrCaps&, int minWidth, int minHeight);
~GrCCPRAtlas(); ~GrCCAtlas();
bool addRect(int devWidth, int devHeight, SkIPoint16* loc); bool addRect(int devWidth, int devHeight, SkIPoint16* loc);
const SkISize& drawBounds() { return fDrawBounds; } const SkISize& drawBounds() { return fDrawBounds; }
sk_sp<GrRenderTargetContext> SK_WARN_UNUSED_RESULT finalize(GrOnFlushResourceProvider*, sk_sp<GrRenderTargetContext> SK_WARN_UNUSED_RESULT
std::unique_ptr<GrDrawOp> atlasOp); finalize(GrOnFlushResourceProvider*, std::unique_ptr<GrDrawOp> atlasOp);
GrTextureProxy* textureProxy() const { return fTextureProxy.get(); } GrTextureProxy* textureProxy() const { return fTextureProxy.get(); }
@ -43,14 +43,14 @@ private:
bool internalPlaceRect(int w, int h, SkIPoint16* loc); bool internalPlaceRect(int w, int h, SkIPoint16* loc);
const int fMaxAtlasSize; const int fMaxAtlasSize;
int fWidth; int fWidth;
int fHeight; int fHeight;
SkISize fDrawBounds; SkISize fDrawBounds;
std::unique_ptr<Node> fTopNode; std::unique_ptr<Node> fTopNode;
sk_sp<GrTextureProxy> fTextureProxy; sk_sp<GrTextureProxy> fTextureProxy;
}; };
#endif #endif

View File

@ -5,7 +5,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRClipProcessor.h" #include "GrCCClipProcessor.h"
#include "GrTexture.h" #include "GrTexture.h"
#include "GrTextureProxy.h" #include "GrTextureProxy.h"
@ -13,9 +13,9 @@
#include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLFragmentShaderBuilder.h"
GrCCPRClipProcessor::GrCCPRClipProcessor(const ClipPath* clipPath, MustCheckBounds mustCheckBounds, GrCCClipProcessor::GrCCClipProcessor(const ClipPath* clipPath, MustCheckBounds mustCheckBounds,
SkPath::FillType overrideFillType) SkPath::FillType overrideFillType)
: INHERITED(kCCPRClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) : INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fClipPath(clipPath) , fClipPath(clipPath)
, fMustCheckBounds((bool)mustCheckBounds) , fMustCheckBounds((bool)mustCheckBounds)
, fOverrideFillType(overrideFillType) , fOverrideFillType(overrideFillType)
@ -24,18 +24,17 @@ GrCCPRClipProcessor::GrCCPRClipProcessor(const ClipPath* clipPath, MustCheckBoun
this->addTextureSampler(&fAtlasAccess); this->addTextureSampler(&fAtlasAccess);
} }
std::unique_ptr<GrFragmentProcessor> GrCCPRClipProcessor::clone() const { std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
return skstd::make_unique<GrCCPRClipProcessor>(fClipPath, MustCheckBounds(fMustCheckBounds), return skstd::make_unique<GrCCClipProcessor>(fClipPath, MustCheckBounds(fMustCheckBounds),
fOverrideFillType); fOverrideFillType);
} }
void GrCCPRClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
GrProcessorKeyBuilder* b) const {
b->add32((fOverrideFillType << 1) | (int)fMustCheckBounds); b->add32((fOverrideFillType << 1) | (int)fMustCheckBounds);
} }
bool GrCCPRClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const { bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
const GrCCPRClipProcessor& that = fp.cast<GrCCPRClipProcessor>(); const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>();
// Each ClipPath path has a unique atlas proxy, so hasSameSamplersAndAccesses should have // Each ClipPath path has a unique atlas proxy, so hasSameSamplersAndAccesses should have
// already weeded out FPs with different ClipPaths. // already weeded out FPs with different ClipPaths.
SkASSERT(that.fClipPath->deviceSpacePath().getGenerationID() == SkASSERT(that.fClipPath->deviceSpacePath().getGenerationID() ==
@ -43,10 +42,10 @@ bool GrCCPRClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
return that.fOverrideFillType == fOverrideFillType; return that.fOverrideFillType == fOverrideFillType;
} }
class GrCCPRClipProcessor::Impl : public GrGLSLFragmentProcessor { class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
public: public:
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
const GrCCPRClipProcessor& proc = args.fFp.cast<GrCCPRClipProcessor>(); const GrCCClipProcessor& proc = args.fFp.cast<GrCCClipProcessor>();
GrGLSLUniformHandler* uniHandler = args.fUniformHandler; GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
GrGLSLFPFragmentBuilder* f = args.fFragBuilder; GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
@ -93,7 +92,7 @@ public:
void onSetData(const GrGLSLProgramDataManager& pdman, void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& fp) override { const GrFragmentProcessor& fp) override {
const GrCCPRClipProcessor& proc = fp.cast<GrCCPRClipProcessor>(); const GrCCClipProcessor& proc = fp.cast<GrCCClipProcessor>();
if (proc.fMustCheckBounds) { if (proc.fMustCheckBounds) {
const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds()); const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds());
pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(), pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(),
@ -109,6 +108,6 @@ private:
UniformHandle fAtlasTransformUniform; UniformHandle fAtlasTransformUniform;
}; };
GrGLSLFragmentProcessor* GrCCPRClipProcessor::onCreateGLSLInstance() const { GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const {
return new Impl(); return new Impl();
} }

View File

@ -5,13 +5,13 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRClipProcessor_DEFINED #ifndef GrCCClipProcessor_DEFINED
#define GrCCPRClipProcessor_DEFINED #define GrCCClipProcessor_DEFINED
#include "GrFragmentProcessor.h" #include "GrFragmentProcessor.h"
#include "ccpr/GrCoverageCountingPathRenderer.h" #include "ccpr/GrCoverageCountingPathRenderer.h"
class GrCCPRClipProcessor : public GrFragmentProcessor { class GrCCClipProcessor : public GrFragmentProcessor {
public: public:
using ClipPath = GrCoverageCountingPathRenderer::ClipPath; using ClipPath = GrCoverageCountingPathRenderer::ClipPath;
@ -20,9 +20,9 @@ public:
kYes = true kYes = true
}; };
GrCCPRClipProcessor(const ClipPath*, MustCheckBounds, SkPath::FillType overrideFillType); GrCCClipProcessor(const ClipPath*, MustCheckBounds, SkPath::FillType overrideFillType);
const char* name() const override { return "GrCCPRClipProcessor"; } const char* name() const override { return "GrCCClipProcessor"; }
std::unique_ptr<GrFragmentProcessor> clone() const override; std::unique_ptr<GrFragmentProcessor> clone() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override; bool onIsEqual(const GrFragmentProcessor&) const override;

View File

@ -5,7 +5,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRCoverageOp.h" #include "GrCCCoverageOp.h"
#include "GrCaps.h" #include "GrCaps.h"
#include "GrGpuCommandBuffer.h" #include "GrGpuCommandBuffer.h"
@ -15,13 +15,13 @@
#include "SkPath.h" #include "SkPath.h"
#include "SkPathPriv.h" #include "SkPathPriv.h"
#include "SkPoint.h" #include "SkPoint.h"
#include "ccpr/GrCCPRGeometry.h" #include "ccpr/GrCCGeometry.h"
using TriangleInstance = GrCCPRCoverageProcessor::TriangleInstance; using TriangleInstance = GrCCCoverageProcessor::TriangleInstance;
using CubicInstance = GrCCPRCoverageProcessor::CubicInstance; using CubicInstance = GrCCCoverageProcessor::CubicInstance;
void GrCCPRCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds, void GrCCCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds,
SkRect* devBounds45) { SkRect* devBounds45) {
const SkPoint* pts = SkPathPriv::PointData(path); const SkPoint* pts = SkPathPriv::PointData(path);
int numPts = path.countPoints(); int numPts = path.countPoints();
SkASSERT(numPts + 1 <= fLocalDevPtsBuffer.count()); SkASSERT(numPts + 1 <= fLocalDevPtsBuffer.count());
@ -69,19 +69,19 @@ void GrCCPRCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path,
SkPoint topLeftPts[2], bottomRightPts[2]; SkPoint topLeftPts[2], bottomRightPts[2];
topLeft.store(topLeftPts); topLeft.store(topLeftPts);
bottomRight.store(bottomRightPts); bottomRight.store(bottomRightPts);
devBounds->setLTRB(topLeftPts[0].x(), topLeftPts[0].y(), devBounds->setLTRB(topLeftPts[0].x(), topLeftPts[0].y(), bottomRightPts[0].x(),
bottomRightPts[0].x(), bottomRightPts[0].y()); bottomRightPts[0].y());
devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(), devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(), bottomRightPts[1].x(),
bottomRightPts[1].x(), bottomRightPts[1].y()); bottomRightPts[1].y());
this->parsePath(path, fLocalDevPtsBuffer.get()); this->parsePath(path, fLocalDevPtsBuffer.get());
} }
void GrCCPRCoverageOpsBuilder::parseDeviceSpacePath(const SkPath& deviceSpacePath) { void GrCCCoverageOpsBuilder::parseDeviceSpacePath(const SkPath& deviceSpacePath) {
this->parsePath(deviceSpacePath, SkPathPriv::PointData(deviceSpacePath)); this->parsePath(deviceSpacePath, SkPathPriv::PointData(deviceSpacePath));
} }
void GrCCPRCoverageOpsBuilder::parsePath(const SkPath& path, const SkPoint* deviceSpacePts) { void GrCCCoverageOpsBuilder::parsePath(const SkPath& path, const SkPoint* deviceSpacePts) {
SkASSERT(!fParsingPath); SkASSERT(!fParsingPath);
SkDEBUGCODE(fParsingPath = true); SkDEBUGCODE(fParsingPath = true);
SkASSERT(path.isEmpty() || deviceSpacePts); SkASSERT(path.isEmpty() || deviceSpacePts);
@ -134,36 +134,30 @@ void GrCCPRCoverageOpsBuilder::parsePath(const SkPath& path, const SkPoint* devi
this->endContourIfNeeded(insideContour); this->endContourIfNeeded(insideContour);
} }
void GrCCPRCoverageOpsBuilder::endContourIfNeeded(bool insideContour) { void GrCCCoverageOpsBuilder::endContourIfNeeded(bool insideContour) {
if (insideContour) { if (insideContour) {
fCurrPathTallies += fGeometry.endContour(); fCurrPathTallies += fGeometry.endContour();
} }
} }
void GrCCPRCoverageOpsBuilder::saveParsedPath(ScissorMode scissorMode, void GrCCCoverageOpsBuilder::saveParsedPath(ScissorMode scissorMode,
const SkIRect& clippedDevIBounds, const SkIRect& clippedDevIBounds, int16_t atlasOffsetX,
int16_t atlasOffsetX, int16_t atlasOffsetY) { int16_t atlasOffsetY) {
SkASSERT(fParsingPath); SkASSERT(fParsingPath);
fPathsInfo.push_back() = { fPathsInfo.push_back() = {scissorMode, atlasOffsetX, atlasOffsetY, std::move(fTerminatingOp)};
scissorMode,
atlasOffsetX, atlasOffsetY,
std::move(fTerminatingOp)
};
fTallies[(int)scissorMode] += fCurrPathTallies; fTallies[(int)scissorMode] += fCurrPathTallies;
if (ScissorMode::kScissored == scissorMode) { if (ScissorMode::kScissored == scissorMode) {
fScissorBatches.push_back() = { fScissorBatches.push_back() = {fCurrPathTallies,
fCurrPathTallies, clippedDevIBounds.makeOffset(atlasOffsetX, atlasOffsetY)};
clippedDevIBounds.makeOffset(atlasOffsetX, atlasOffsetY)
};
} }
SkDEBUGCODE(fParsingPath = false); SkDEBUGCODE(fParsingPath = false);
} }
void GrCCPRCoverageOpsBuilder::discardParsedPath() { void GrCCCoverageOpsBuilder::discardParsedPath() {
SkASSERT(fParsingPath); SkASSERT(fParsingPath);
// The code will still work whether or not the below assertion is true. It is just unlikely that // The code will still work whether or not the below assertion is true. It is just unlikely that
@ -175,9 +169,9 @@ void GrCCPRCoverageOpsBuilder::discardParsedPath() {
SkDEBUGCODE(fParsingPath = false); SkDEBUGCODE(fParsingPath = false);
} }
void GrCCPRCoverageOpsBuilder::emitOp(SkISize drawBounds) { void GrCCCoverageOpsBuilder::emitOp(SkISize drawBounds) {
SkASSERT(!fTerminatingOp); SkASSERT(!fTerminatingOp);
fTerminatingOp.reset(new GrCCPRCoverageOp(std::move(fScissorBatches), drawBounds)); fTerminatingOp.reset(new GrCCCoverageOp(std::move(fScissorBatches), drawBounds));
SkASSERT(fScissorBatches.empty()); SkASSERT(fScissorBatches.empty());
} }
@ -204,8 +198,7 @@ static TriangleInstance* emit_recursive_fan(const SkTArray<SkPoint, true>& pts,
const int32_t oneThirdCount = indexCount / 3; const int32_t oneThirdCount = indexCount / 3;
const int32_t twoThirdsCount = (2 * indexCount) / 3; const int32_t twoThirdsCount = (2 * indexCount) / 3;
out++->set(pts[indices[firstIndex]], out++->set(pts[indices[firstIndex]], pts[indices[firstIndex + oneThirdCount]],
pts[indices[firstIndex + oneThirdCount]],
pts[indices[firstIndex + twoThirdsCount]], atlasOffset); pts[indices[firstIndex + twoThirdsCount]], atlasOffset);
out = emit_recursive_fan(pts, indices, firstIndex, oneThirdCount + 1, atlasOffset, out); out = emit_recursive_fan(pts, indices, firstIndex, oneThirdCount + 1, atlasOffset, out);
@ -222,8 +215,8 @@ static TriangleInstance* emit_recursive_fan(const SkTArray<SkPoint, true>& pts,
return out; return out;
} }
bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP, bool GrCCCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
SkTArray<std::unique_ptr<GrCCPRCoverageOp>>* ops) { SkTArray<std::unique_ptr<GrCCCoverageOp>>* ops) {
SkASSERT(!fParsingPath); SkASSERT(!fParsingPath);
// Here we build a single instance buffer to share with every draw call from every CoverageOP we // Here we build a single instance buffer to share with every draw call from every CoverageOP we
@ -252,14 +245,14 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
// Cubics (loops and serpentines) view the same instance buffer as an array of CubicInstance[]. // Cubics (loops and serpentines) view the same instance buffer as an array of CubicInstance[].
// So, reinterpreting the instance data as CubicInstance[], we start them on the first index // So, reinterpreting the instance data as CubicInstance[], we start them on the first index
// that will not overwrite previous TriangleInstance data. // that will not overwrite previous TriangleInstance data.
int cubicBaseIdx = GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriangleInstance), int cubicBaseIdx =
sizeof(CubicInstance)); GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriangleInstance), sizeof(CubicInstance));
baseInstances[0].fCubics = cubicBaseIdx; baseInstances[0].fCubics = cubicBaseIdx;
baseInstances[1].fCubics = baseInstances[0].fCubics + fTallies[0].fCubics; baseInstances[1].fCubics = baseInstances[0].fCubics + fTallies[0].fCubics;
int cubicEndIdx = baseInstances[1].fCubics + fTallies[1].fCubics; int cubicEndIdx = baseInstances[1].fCubics + fTallies[1].fCubics;
sk_sp<GrBuffer> instanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType, sk_sp<GrBuffer> instanceBuffer =
cubicEndIdx * sizeof(CubicInstance)); onFlushRP->makeBuffer(kVertex_GrBufferType, cubicEndIdx * sizeof(CubicInstance));
if (!instanceBuffer) { if (!instanceBuffer) {
return false; return false;
} }
@ -285,9 +278,9 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
const SkTArray<SkPoint, true>& pts = fGeometry.points(); const SkTArray<SkPoint, true>& pts = fGeometry.points();
// Expand the ccpr verbs into GPU instance buffers. // Expand the ccpr verbs into GPU instance buffers.
for (GrCCPRGeometry::Verb verb : fGeometry.verbs()) { for (GrCCGeometry::Verb verb : fGeometry.verbs()) {
switch (verb) { switch (verb) {
case GrCCPRGeometry::Verb::kBeginPath: case GrCCGeometry::Verb::kBeginPath:
SkASSERT(currFan.empty()); SkASSERT(currFan.empty());
currIndices = &instanceIndices[(int)currPathInfo->fScissorMode]; currIndices = &instanceIndices[(int)currPathInfo->fScissorMode];
atlasOffsetX = static_cast<float>(currPathInfo->fAtlasOffsetX); atlasOffsetX = static_cast<float>(currPathInfo->fAtlasOffsetX);
@ -308,42 +301,42 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
++currPathInfo; ++currPathInfo;
continue; continue;
case GrCCPRGeometry::Verb::kBeginContour: case GrCCGeometry::Verb::kBeginContour:
SkASSERT(currFan.empty()); SkASSERT(currFan.empty());
currFan.push_back(++ptsIdx); currFan.push_back(++ptsIdx);
continue; continue;
case GrCCPRGeometry::Verb::kLineTo: case GrCCGeometry::Verb::kLineTo:
SkASSERT(!currFan.empty()); SkASSERT(!currFan.empty());
currFan.push_back(++ptsIdx); currFan.push_back(++ptsIdx);
continue; continue;
case GrCCPRGeometry::Verb::kMonotonicQuadraticTo: case GrCCGeometry::Verb::kMonotonicQuadraticTo:
SkASSERT(!currFan.empty()); SkASSERT(!currFan.empty());
triangleInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx], atlasOffset); triangleInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx], atlasOffset);
currFan.push_back(ptsIdx += 2); currFan.push_back(ptsIdx += 2);
continue; continue;
case GrCCPRGeometry::Verb::kMonotonicCubicTo: case GrCCGeometry::Verb::kMonotonicCubicTo:
SkASSERT(!currFan.empty()); SkASSERT(!currFan.empty());
cubicInstanceData[currIndices->fCubics++].set(&pts[ptsIdx], cubicInstanceData[currIndices->fCubics++].set(&pts[ptsIdx], atlasOffsetX,
atlasOffsetX, atlasOffsetY); atlasOffsetY);
currFan.push_back(ptsIdx += 3); currFan.push_back(ptsIdx += 3);
continue; continue;
case GrCCPRGeometry::Verb::kEndClosedContour: // endPt == startPt. case GrCCGeometry::Verb::kEndClosedContour: // endPt == startPt.
SkASSERT(!currFan.empty()); SkASSERT(!currFan.empty());
currFan.pop_back(); currFan.pop_back();
// fallthru. // fallthru.
case GrCCPRGeometry::Verb::kEndOpenContour: // endPt != startPt. case GrCCGeometry::Verb::kEndOpenContour: // endPt != startPt.
if (currFan.count() >= 3) { if (currFan.count() >= 3) {
int fanSize = currFan.count(); int fanSize = currFan.count();
// Reserve space for emit_recursive_fan. Technically this can grow to // Reserve space for emit_recursive_fan. Technically this can grow to
// fanSize + log3(fanSize), but we approximate with log2. // fanSize + log3(fanSize), but we approximate with log2.
currFan.push_back_n(SkNextLog2(fanSize)); currFan.push_back_n(SkNextLog2(fanSize));
SkDEBUGCODE(TriangleInstance* end =) SkDEBUGCODE(TriangleInstance* end =)
emit_recursive_fan(pts, currFan, 0, fanSize, atlasOffset, emit_recursive_fan(pts, currFan, 0, fanSize, atlasOffset,
triangleInstanceData + currIndices->fTriangles); triangleInstanceData + currIndices->fTriangles);
currIndices->fTriangles += fanSize - 2; currIndices->fTriangles += fanSize - 2;
SkASSERT(triangleInstanceData + currIndices->fTriangles == end); SkASSERT(triangleInstanceData + currIndices->fTriangles == end);
} }
@ -372,9 +365,9 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
return true; return true;
} }
void GrCCPRCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer, void GrCCCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
const PrimitiveTallies baseInstances[kNumScissorModes], const PrimitiveTallies baseInstances[kNumScissorModes],
const PrimitiveTallies endInstances[kNumScissorModes]) { const PrimitiveTallies endInstances[kNumScissorModes]) {
fInstanceBuffer = std::move(instanceBuffer); fInstanceBuffer = std::move(instanceBuffer);
fBaseInstances[0] = baseInstances[0]; fBaseInstances[0] = baseInstances[0];
fBaseInstances[1] = baseInstances[1]; fBaseInstances[1] = baseInstances[1];
@ -382,8 +375,8 @@ void GrCCPRCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
fInstanceCounts[1] = endInstances[1] - baseInstances[1]; fInstanceCounts[1] = endInstances[1] - baseInstances[1];
} }
void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) { void GrCCCoverageOp::onExecute(GrOpFlushState* flushState) {
using RenderPass = GrCCPRCoverageProcessor::RenderPass; using RenderPass = GrCCCoverageProcessor::RenderPass;
SkASSERT(fInstanceBuffer); SkASSERT(fInstanceBuffer);
@ -397,7 +390,7 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls, this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls,
&PrimitiveTallies::fTriangles); &PrimitiveTallies::fTriangles);
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges, this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges,
&PrimitiveTallies::fTriangles); // Might get skipped. &PrimitiveTallies::fTriangles); // Might get skipped.
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners, this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners,
&PrimitiveTallies::fTriangles); &PrimitiveTallies::fTriangles);
@ -414,21 +407,21 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
&PrimitiveTallies::fCubics); &PrimitiveTallies::fCubics);
} }
void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline, void GrCCCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline,
GrCCPRCoverageProcessor::RenderPass renderPass, GrCCCoverageProcessor::RenderPass renderPass,
int PrimitiveTallies::* instanceType) const { int PrimitiveTallies::*instanceType) const {
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode; using ScissorMode = GrCCCoverageOpsBuilder::ScissorMode;
SkASSERT(pipeline.getScissorState().enabled()); SkASSERT(pipeline.getScissorState().enabled());
if (!GrCCPRCoverageProcessor::DoesRenderPass(renderPass, *flushState->caps().shaderCaps())) { if (!GrCCCoverageProcessor::DoesRenderPass(renderPass, *flushState->caps().shaderCaps())) {
return; return;
} }
fMeshesScratchBuffer.reset(); fMeshesScratchBuffer.reset();
fDynamicStatesScratchBuffer.reset(); fDynamicStatesScratchBuffer.reset();
GrCCPRCoverageProcessor proc(flushState->resourceProvider(), renderPass, GrCCCoverageProcessor proc(flushState->resourceProvider(), renderPass,
*flushState->caps().shaderCaps()); *flushState->caps().shaderCaps());
if (int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) { if (int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
SkASSERT(instanceCount > 0); SkASSERT(instanceCount > 0);

View File

@ -5,23 +5,23 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRCoverageOp_DEFINED #ifndef GrCCCoverageOp_DEFINED
#define GrCCPRCoverageOp_DEFINED #define GrCCCoverageOp_DEFINED
#include "GrMesh.h" #include "GrMesh.h"
#include "SkRect.h" #include "SkRect.h"
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "ccpr/GrCCPRCoverageProcessor.h" #include "ccpr/GrCCCoverageProcessor.h"
#include "ccpr/GrCCPRGeometry.h" #include "ccpr/GrCCGeometry.h"
#include "ops/GrDrawOp.h" #include "ops/GrDrawOp.h"
class GrCCPRCoverageOp; class GrCCCoverageOp;
class GrOnFlushResourceProvider; class GrOnFlushResourceProvider;
class SkMatrix; class SkMatrix;
class SkPath; class SkPath;
/** /**
* This class produces GrCCPRCoverageOps that render coverage count masks and atlases. A path is * This class produces GrCCCoverageOps that render coverage count masks and atlases. A path is
* added to the current op in two steps: * added to the current op in two steps:
* *
* 1) parsePath(ScissorMode, viewMatrix, path, &devBounds, &devBounds45); * 1) parsePath(ScissorMode, viewMatrix, path, &devBounds, &devBounds45);
@ -30,28 +30,25 @@ class SkPath;
* *
* 2) saveParsedPath(offsetX, offsetY, clipBounds); * 2) saveParsedPath(offsetX, offsetY, clipBounds);
* *
* The client can flush the currently saved paths to a GrCCPRCoverageOp by calling emitOp, and * The client can flush the currently saved paths to a GrCCCoverageOp by calling emitOp, and
* retrieve all emitted ops after calling finalize(). * retrieve all emitted ops after calling finalize().
*/ */
class GrCCPRCoverageOpsBuilder { class GrCCCoverageOpsBuilder {
public: public:
// Indicates whether a path should enforce a scissor clip when rendering its mask. (Specified // Indicates whether a path should enforce a scissor clip when rendering its mask. (Specified
// as an int because these values get used directly as indices into arrays.) // as an int because these values get used directly as indices into arrays.)
enum class ScissorMode : int { enum class ScissorMode : int { kNonScissored = 0, kScissored = 1 };
kNonScissored = 0,
kScissored = 1
};
static constexpr int kNumScissorModes = 2; static constexpr int kNumScissorModes = 2;
GrCCPRCoverageOpsBuilder(int maxTotalPaths, int maxPathPoints, int numSkPoints, int numSkVerbs) GrCCCoverageOpsBuilder(int maxTotalPaths, int maxPathPoints, int numSkPoints, int numSkVerbs)
: fPathsInfo(maxTotalPaths) : fPathsInfo(maxTotalPaths)
, fLocalDevPtsBuffer(maxPathPoints + 1) // Overallocate by one point to accomodate for , fLocalDevPtsBuffer(maxPathPoints + 1) // Overallocate by one point to accomodate for
// overflow with Sk4f. (See parsePath.) // overflow with Sk4f. (See parsePath.)
, fGeometry(numSkPoints, numSkVerbs) , fGeometry(numSkPoints, numSkVerbs)
, fTallies{PrimitiveTallies(), PrimitiveTallies()} , fTallies{PrimitiveTallies(), PrimitiveTallies()}
, fScissorBatches(maxTotalPaths) {} , fScissorBatches(maxTotalPaths) {}
~GrCCPRCoverageOpsBuilder() { ~GrCCCoverageOpsBuilder() {
// Enforce the contract that the client always calls saveParsedPath or discardParsedPath. // Enforce the contract that the client always calls saveParsedPath or discardParsedPath.
SkASSERT(!fParsingPath); SkASSERT(!fParsingPath);
} }
@ -72,27 +69,27 @@ public:
// Commits the currently-parsed path from staging to the next Op, and specifies whether the mask // Commits the currently-parsed path from staging to the next Op, and specifies whether the mask
// should be rendered with a scissor clip in effect. Accepts an optional post-device-space // should be rendered with a scissor clip in effect. Accepts an optional post-device-space
// translate for placement in an atlas. // translate for placement in an atlas.
void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds, void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds, int16_t atlasOffsetX,
int16_t atlasOffsetX, int16_t atlasOffsetY); int16_t atlasOffsetY);
void discardParsedPath(); void discardParsedPath();
// Flushes all currently-saved paths internally to a GrCCPRCoverageOp. // Flushes all currently-saved paths internally to a GrCCCoverageOp.
// //
// NOTE: if there is a parsed path in the staging area, it will not be included. But the client // NOTE: if there is a parsed path in the staging area, it will not be included. But the client
// may still call saveParsedPath to include it in a future Op. // may still call saveParsedPath to include it in a future Op.
void emitOp(SkISize drawBounds); void emitOp(SkISize drawBounds);
// Builds GPU buffers and returns the list of GrCCPRCoverageOps as specified by calls to emitOp. // Builds GPU buffers and returns the list of GrCCCoverageOps as specified by calls to emitOp.
bool finalize(GrOnFlushResourceProvider*, SkTArray<std::unique_ptr<GrCCPRCoverageOp>>*); bool finalize(GrOnFlushResourceProvider*, SkTArray<std::unique_ptr<GrCCCoverageOp>>*);
private: private:
using PrimitiveTallies = GrCCPRGeometry::PrimitiveTallies; using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;
// Every kBeginPath verb has a corresponding PathInfo entry. // Every kBeginPath verb has a corresponding PathInfo entry.
struct PathInfo { struct PathInfo {
ScissorMode fScissorMode; ScissorMode fScissorMode;
int16_t fAtlasOffsetX, fAtlasOffsetY; int16_t fAtlasOffsetX, fAtlasOffsetY;
std::unique_ptr<GrCCPRCoverageOp> fTerminatingOp; std::unique_ptr<GrCCCoverageOp> fTerminatingOp;
}; };
// Every PathInfo with a mode of kScissored has a corresponding ScissorBatch. // Every PathInfo with a mode of kScissored has a corresponding ScissorBatch.
@ -113,25 +110,25 @@ private:
SkSTArray<32, PathInfo, true> fPathsInfo; SkSTArray<32, PathInfo, true> fPathsInfo;
const SkAutoSTArray<32, SkPoint> fLocalDevPtsBuffer; const SkAutoSTArray<32, SkPoint> fLocalDevPtsBuffer;
GrCCPRGeometry fGeometry; GrCCGeometry fGeometry;
PrimitiveTallies fTallies[kNumScissorModes]; PrimitiveTallies fTallies[kNumScissorModes];
SkTArray<ScissorBatch, true> fScissorBatches; SkTArray<ScissorBatch, true> fScissorBatches;
std::unique_ptr<GrCCPRCoverageOp> fTerminatingOp; std::unique_ptr<GrCCCoverageOp> fTerminatingOp;
friend class GrCCPRCoverageOp; // For ScissorBatch. friend class GrCCCoverageOp; // For ScissorBatch.
}; };
/** /**
* This Op renders coverage count masks and atlases. Create it using GrCCPRCoverageOpsBuilder. * This Op renders coverage count masks and atlases. Create it using GrCCCoverageOpsBuilder.
*/ */
class GrCCPRCoverageOp : public GrDrawOp { class GrCCCoverageOp : public GrDrawOp {
public: public:
DEFINE_OP_CLASS_ID DEFINE_OP_CLASS_ID
// GrDrawOp interface. // GrDrawOp interface.
const char* name() const override { return "GrCCPRCoverageOp"; } const char* name() const override { return "GrCCCoverageOp"; }
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*, RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
GrPixelConfigIsClamped) override { GrPixelConfigIsClamped) override {
@ -142,14 +139,14 @@ public:
void onExecute(GrOpFlushState*) override; void onExecute(GrOpFlushState*) override;
private: private:
static constexpr int kNumScissorModes = GrCCPRCoverageOpsBuilder::kNumScissorModes; static constexpr int kNumScissorModes = GrCCCoverageOpsBuilder::kNumScissorModes;
using PrimitiveTallies = GrCCPRGeometry::PrimitiveTallies; using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;
using ScissorBatch = GrCCPRCoverageOpsBuilder::ScissorBatch; using ScissorBatch = GrCCCoverageOpsBuilder::ScissorBatch;
GrCCPRCoverageOp(SkTArray<ScissorBatch, true>&& scissorBatches, const SkISize& drawBounds) GrCCCoverageOp(SkTArray<ScissorBatch, true>&& scissorBatches, const SkISize& drawBounds)
: INHERITED(ClassID()) : INHERITED(ClassID())
, fScissorBatches(std::move(scissorBatches)) , fScissorBatches(std::move(scissorBatches))
, fDrawBounds(drawBounds) { , fDrawBounds(drawBounds) {
this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()), this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()),
GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo); GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
} }
@ -158,8 +155,8 @@ private:
const PrimitiveTallies baseInstances[kNumScissorModes], const PrimitiveTallies baseInstances[kNumScissorModes],
const PrimitiveTallies endInstances[kNumScissorModes]); const PrimitiveTallies endInstances[kNumScissorModes]);
void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&, GrCCPRCoverageProcessor::RenderPass, void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&, GrCCCoverageProcessor::RenderPass,
int PrimitiveTallies::* instanceType) const; int PrimitiveTallies::*instanceType) const;
sk_sp<GrBuffer> fInstanceBuffer; sk_sp<GrBuffer> fInstanceBuffer;
PrimitiveTallies fBaseInstances[kNumScissorModes]; PrimitiveTallies fBaseInstances[kNumScissorModes];
@ -170,7 +167,7 @@ private:
mutable SkTArray<GrMesh> fMeshesScratchBuffer; mutable SkTArray<GrMesh> fMeshesScratchBuffer;
mutable SkTArray<GrPipeline::DynamicState, true> fDynamicStatesScratchBuffer; mutable SkTArray<GrPipeline::DynamicState, true> fDynamicStatesScratchBuffer;
friend class GrCCPRCoverageOpsBuilder; friend class GrCCCoverageOpsBuilder;
typedef GrDrawOp INHERITED; typedef GrDrawOp INHERITED;
}; };

View File

@ -5,20 +5,20 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRCoverageProcessor.h" #include "GrCCCoverageProcessor.h"
#include "SkMakeUnique.h" #include "SkMakeUnique.h"
#include "ccpr/GrCCPRCubicShader.h" #include "ccpr/GrCCCubicShader.h"
#include "ccpr/GrCCPRQuadraticShader.h" #include "ccpr/GrCCQuadraticShader.h"
#include "ccpr/GrCCPRTriangleShader.h" #include "ccpr/GrCCTriangleShader.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler, void GrCCCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code, GrGLSLVarying::Scope scope, SkString* code,
const char* position, const char* coverage, const char* position, const char* coverage,
const char* wind) { const char* wind) {
SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope); SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
WindHandling windHandling = this->onEmitVaryings(varyingHandler, scope, code, position, WindHandling windHandling = this->onEmitVaryings(varyingHandler, scope, code, position,
coverage, wind); coverage, wind);
@ -29,10 +29,10 @@ void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varying
} }
} }
void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProcessor& proc, void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
GrGLSLPPFragmentBuilder* f, GrGLSLPPFragmentBuilder* f,
const char* skOutputColor, const char* skOutputColor,
const char* skOutputCoverage) const { const char* skOutputCoverage) const {
f->codeAppendf("half coverage = 0;"); f->codeAppendf("half coverage = 0;");
this->onEmitFragmentCode(f, "coverage"); this->onEmitFragmentCode(f, "coverage");
if (fWind.fsIn()) { if (fWind.fsIn()) {
@ -49,10 +49,10 @@ void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProce
#endif #endif
} }
void GrCCPRCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s, void GrCCCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s,
const char* leftPt, const char* leftPt,
const char* rightPt, const char* rightPt,
const char* outputDistanceEquation) { const char* outputDistanceEquation) {
s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);", s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
rightPt, leftPt, leftPt, rightPt); rightPt, leftPt, leftPt, rightPt);
s->codeAppend ("float nwidth = (abs(n.x) + abs(n.y)) * (bloat * 2);"); s->codeAppend ("float nwidth = (abs(n.x) + abs(n.y)) * (bloat * 2);");
@ -62,8 +62,8 @@ void GrCCPRCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBu
s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt); s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt);
} }
int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, int GrCCCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
const char* samplesName) { const char* samplesName) {
// Standard DX11 sample locations. // Standard DX11 sample locations.
#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS) #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
f->defineConstant("float2[8]", samplesName, "float2[8](" f->defineConstant("float2[8]", samplesName, "float2[8]("
@ -82,8 +82,8 @@ int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentB
#endif #endif
} }
void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&, void GrCCCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
GrProcessorKeyBuilder* b) const { GrProcessorKeyBuilder* b) const {
int key = (int)fRenderPass << 1; int key = (int)fRenderPass << 1;
if (Impl::kGeometryShader == fImpl) { if (Impl::kGeometryShader == fImpl) {
key |= 1; key |= 1;
@ -96,27 +96,27 @@ void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
b->add32(key); b->add32(key);
} }
GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const { GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
std::unique_ptr<Shader> shader; std::unique_ptr<Shader> shader;
switch (fRenderPass) { switch (fRenderPass) {
case RenderPass::kTriangleHulls: case RenderPass::kTriangleHulls:
case RenderPass::kTriangleEdges: case RenderPass::kTriangleEdges:
shader = skstd::make_unique<GrCCPRTriangleShader>(); shader = skstd::make_unique<GrCCTriangleShader>();
break; break;
case RenderPass::kTriangleCorners: case RenderPass::kTriangleCorners:
shader = skstd::make_unique<GrCCPRTriangleCornerShader>(); shader = skstd::make_unique<GrCCTriangleCornerShader>();
break; break;
case RenderPass::kQuadraticHulls: case RenderPass::kQuadraticHulls:
shader = skstd::make_unique<GrCCPRQuadraticHullShader>(); shader = skstd::make_unique<GrCCQuadraticHullShader>();
break; break;
case RenderPass::kQuadraticCorners: case RenderPass::kQuadraticCorners:
shader = skstd::make_unique<GrCCPRQuadraticCornerShader>(); shader = skstd::make_unique<GrCCQuadraticCornerShader>();
break; break;
case RenderPass::kCubicHulls: case RenderPass::kCubicHulls:
shader = skstd::make_unique<GrCCPRCubicHullShader>(); shader = skstd::make_unique<GrCCCubicHullShader>();
break; break;
case RenderPass::kCubicCorners: case RenderPass::kCubicCorners:
shader = skstd::make_unique<GrCCPRCubicCornerShader>(); shader = skstd::make_unique<GrCCCubicCornerShader>();
break; break;
} }
return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader)) return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))

View File

@ -5,8 +5,8 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRCoverageProcessor_DEFINED #ifndef GrCCCoverageProcessor_DEFINED
#define GrCCPRCoverageProcessor_DEFINED #define GrCCCoverageProcessor_DEFINED
#include "GrGeometryProcessor.h" #include "GrGeometryProcessor.h"
#include "GrShaderCaps.h" #include "GrShaderCaps.h"
@ -26,11 +26,11 @@ class GrMesh;
* The caller is responsible to execute all render passes for all applicable primitives into a * The caller is responsible to execute all render passes for all applicable primitives into a
* cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass * cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass
* below). Once all of a path's primitives have been drawn, the render target contains a composite * below). Once all of a path's primitives have been drawn, the render target contains a composite
* coverage count that can then be used to draw the path (see GrCCPRPathProcessor). * coverage count that can then be used to draw the path (see GrCCPathProcessor).
* *
* To draw a renderer pass, see appendMesh below. * To draw a renderer pass, see appendMesh below.
*/ */
class GrCCPRCoverageProcessor : public GrGeometryProcessor { class GrCCCoverageProcessor : public GrGeometryProcessor {
public: public:
// Defines a single triangle or closed quadratic bezier, with transposed x,y point values. // Defines a single triangle or closed quadratic bezier, with transposed x,y point values.
struct TriangleInstance { struct TriangleInstance {
@ -91,8 +91,8 @@ public:
return RenderPass::kTriangleEdges != renderPass || caps.geometryShaderSupport(); return RenderPass::kTriangleEdges != renderPass || caps.geometryShaderSupport();
} }
GrCCPRCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrShaderCaps& caps) GrCCCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrShaderCaps& caps)
: INHERITED(kGrCCPRCoverageProcessor_ClassID) : INHERITED(kGrCCCoverageProcessor_ClassID)
, fRenderPass(pass) , fRenderPass(pass)
, fImpl(caps.geometryShaderSupport() ? Impl::kGeometryShader : Impl::kVertexShader) { , fImpl(caps.geometryShaderSupport() ? Impl::kGeometryShader : Impl::kVertexShader) {
SkASSERT(DoesRenderPass(pass, caps)); SkASSERT(DoesRenderPass(pass, caps));
@ -162,7 +162,7 @@ public:
void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code, void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage, const char* wind); const char* position, const char* coverage, const char* wind);
void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*, void emitFragmentCode(const GrCCCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
const char* skOutputColor, const char* skOutputCoverage) const; const char* skOutputColor, const char* skOutputCoverage) const;
// Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
@ -246,31 +246,31 @@ private:
const Impl fImpl; const Impl fImpl;
sk_sp<const GrBuffer> fVertexBuffer; // Used by VSImpl. sk_sp<const GrBuffer> fVertexBuffer; // Used by VSImpl.
sk_sp<const GrBuffer> fIndexBuffer; // Used by VSImpl. sk_sp<const GrBuffer> fIndexBuffer; // Used by VSImpl.
SkDEBUGCODE(float fDebugBloat = 0;) SkDEBUGCODE(float fDebugBloat = 0);
typedef GrGeometryProcessor INHERITED; typedef GrGeometryProcessor INHERITED;
}; };
inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) { inline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) {
this->set(p[0], p[1], p[2], trans); this->set(p[0], p[1], p[2], trans);
} }
inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1, inline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
const SkPoint& p2, const Sk2f& trans) { const SkPoint& p2, const Sk2f& trans) {
Sk2f P0 = Sk2f::Load(&p0) + trans; Sk2f P0 = Sk2f::Load(&p0) + trans;
Sk2f P1 = Sk2f::Load(&p1) + trans; Sk2f P1 = Sk2f::Load(&p1) + trans;
Sk2f P2 = Sk2f::Load(&p2) + trans; Sk2f P2 = Sk2f::Load(&p2) + trans;
Sk2f::Store3(this, P0, P1, P2); Sk2f::Store3(this, P0, P1, P2);
} }
inline void GrCCPRCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) { inline void GrCCCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) {
Sk4f X,Y; Sk4f X,Y;
Sk4f::Load2(p, &X, &Y); Sk4f::Load2(p, &X, &Y);
(X + dx).store(&fX); (X + dx).store(&fX);
(Y + dy).store(&fY); (Y + dy).store(&fY);
} }
inline bool GrCCPRCoverageProcessor::RenderPassIsCubic(RenderPass pass) { inline bool GrCCCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
switch (pass) { switch (pass) {
case RenderPass::kTriangleHulls: case RenderPass::kTriangleHulls:
case RenderPass::kTriangleEdges: case RenderPass::kTriangleEdges:
@ -286,7 +286,7 @@ inline bool GrCCPRCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
return false; return false;
} }
inline const char* GrCCPRCoverageProcessor::RenderPassName(RenderPass pass) { inline const char* GrCCCoverageProcessor::RenderPassName(RenderPass pass) {
switch (pass) { switch (pass) {
case RenderPass::kTriangleHulls: return "kTriangleHulls"; case RenderPass::kTriangleHulls: return "kTriangleHulls";
case RenderPass::kTriangleEdges: return "kTriangleEdges"; case RenderPass::kTriangleEdges: return "kTriangleEdges";

View File

@ -5,19 +5,19 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRCoverageProcessor.h" #include "GrCCCoverageProcessor.h"
#include "GrMesh.h" #include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
using InputType = GrGLSLGeometryBuilder::InputType; using InputType = GrGLSLGeometryBuilder::InputType;
using OutputType = GrGLSLGeometryBuilder::OutputType; using OutputType = GrGLSLGeometryBuilder::OutputType;
using Shader = GrCCPRCoverageProcessor::Shader; using Shader = GrCCCoverageProcessor::Shader;
/** /**
* This class and its subclasses implement the coverage processor with geometry shaders. * This class and its subclasses implement the coverage processor with geometry shaders.
*/ */
class GrCCPRCoverageProcessor::GSImpl : public GrGLSLGeometryProcessor { class GrCCCoverageProcessor::GSImpl : public GrGLSLGeometryProcessor {
protected: protected:
GSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {} GSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
@ -27,7 +27,7 @@ protected:
} }
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final { void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
const GrCCPRCoverageProcessor& proc = args.fGP.cast<GrCCPRCoverageProcessor>(); const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();
// The vertex shader simply forwards transposed x or y values to the geometry shader. // The vertex shader simply forwards transposed x or y values to the geometry shader.
SkASSERT(1 == proc.numAttribs()); SkASSERT(1 == proc.numAttribs());
@ -45,7 +45,7 @@ protected:
fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage); fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
} }
void emitGeometryShader(const GrCCPRCoverageProcessor& proc, void emitGeometryShader(const GrCCCoverageProcessor& proc,
GrGLSLVaryingHandler* varyingHandler, GrGLSLGeometryBuilder* g, GrGLSLVaryingHandler* varyingHandler, GrGLSLGeometryBuilder* g,
const char* rtAdjust) const { const char* rtAdjust) const {
int numInputPoints = proc.numInputPoints(); int numInputPoints = proc.numInputPoints();
@ -102,7 +102,7 @@ protected:
/** /**
* Generates a conservative raster hull around a triangle. (See comments for RenderPass) * Generates a conservative raster hull around a triangle. (See comments for RenderPass)
*/ */
class GSHull3Impl : public GrCCPRCoverageProcessor::GSImpl { class GSHull3Impl : public GrCCCoverageProcessor::GSImpl {
public: public:
GSHull3Impl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {} GSHull3Impl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
@ -175,7 +175,7 @@ public:
/** /**
* Generates a conservative raster hull around a convex quadrilateral. (See comments for RenderPass) * Generates a conservative raster hull around a convex quadrilateral. (See comments for RenderPass)
*/ */
class GSHull4Impl : public GrCCPRCoverageProcessor::GSImpl { class GSHull4Impl : public GrCCCoverageProcessor::GSImpl {
public: public:
GSHull4Impl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {} GSHull4Impl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
@ -246,7 +246,7 @@ public:
/** /**
* Generates conservatives around each edge of a triangle. (See comments for RenderPass) * Generates conservatives around each edge of a triangle. (See comments for RenderPass)
*/ */
class GSEdgeImpl : public GrCCPRCoverageProcessor::GSImpl { class GSEdgeImpl : public GrCCCoverageProcessor::GSImpl {
public: public:
GSEdgeImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {} GSEdgeImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
@ -295,7 +295,7 @@ public:
/** /**
* Generates conservative rasters around corners. (See comments for RenderPass) * Generates conservative rasters around corners. (See comments for RenderPass)
*/ */
class GSCornerImpl : public GrCCPRCoverageProcessor::GSImpl { class GSCornerImpl : public GrCCCoverageProcessor::GSImpl {
public: public:
GSCornerImpl(std::unique_ptr<Shader> shader, int numCorners) GSCornerImpl(std::unique_ptr<Shader> shader, int numCorners)
: GSImpl(std::move(shader)), fNumCorners(numCorners) {} : GSImpl(std::move(shader)), fNumCorners(numCorners) {}
@ -320,7 +320,7 @@ private:
const int fNumCorners; const int fNumCorners;
}; };
void GrCCPRCoverageProcessor::initGS() { void GrCCCoverageProcessor::initGS() {
SkASSERT(Impl::kGeometryShader == fImpl); SkASSERT(Impl::kGeometryShader == fImpl);
if (RenderPassIsCubic(fRenderPass)) { if (RenderPassIsCubic(fRenderPass)) {
this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.) this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.)
@ -332,8 +332,8 @@ void GrCCPRCoverageProcessor::initGS() {
this->setWillUseGeoShader(); this->setWillUseGeoShader();
} }
void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, void GrCCCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, SkTArray<GrMesh>* out) const { int baseInstance, SkTArray<GrMesh>* out) const {
// GSImpl doesn't actually make instanced draw calls. Instead, we feed transposed x,y point // GSImpl doesn't actually make instanced draw calls. Instead, we feed transposed x,y point
// values to the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex // values to the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex
// invocation receives either the shape's x or y values as inputs, which it forwards to the // invocation receives either the shape's x or y values as inputs, which it forwards to the
@ -344,21 +344,20 @@ void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanc
mesh.setVertexData(instanceBuffer, baseInstance * 2); mesh.setVertexData(instanceBuffer, baseInstance * 2);
} }
GrGLSLPrimitiveProcessor* GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGSImpl(std::unique_ptr<Shader> shadr) const {
GrCCPRCoverageProcessor::createGSImpl(std::unique_ptr<Shader> shader) const {
switch (fRenderPass) { switch (fRenderPass) {
case RenderPass::kTriangleHulls: case RenderPass::kTriangleHulls:
return new GSHull3Impl(std::move(shader)); return new GSHull3Impl(std::move(shadr));
case RenderPass::kQuadraticHulls: case RenderPass::kQuadraticHulls:
case RenderPass::kCubicHulls: case RenderPass::kCubicHulls:
return new GSHull4Impl(std::move(shader)); return new GSHull4Impl(std::move(shadr));
case RenderPass::kTriangleEdges: case RenderPass::kTriangleEdges:
return new GSEdgeImpl(std::move(shader)); return new GSEdgeImpl(std::move(shadr));
case RenderPass::kTriangleCorners: case RenderPass::kTriangleCorners:
return new GSCornerImpl(std::move(shader), 3); return new GSCornerImpl(std::move(shadr), 3);
case RenderPass::kQuadraticCorners: case RenderPass::kQuadraticCorners:
case RenderPass::kCubicCorners: case RenderPass::kCubicCorners:
return new GSCornerImpl(std::move(shader), 2); return new GSCornerImpl(std::move(shadr), 2);
} }
SK_ABORT("Invalid RenderPass"); SK_ABORT("Invalid RenderPass");
return nullptr; return nullptr;

View File

@ -5,12 +5,12 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRCoverageProcessor.h" #include "GrCCCoverageProcessor.h"
#include "GrMesh.h" #include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
using Shader = GrCCPRCoverageProcessor::Shader; using Shader = GrCCCoverageProcessor::Shader;
static constexpr int kAttribIdx_X = 0; static constexpr int kAttribIdx_X = 0;
static constexpr int kAttribIdx_Y = 1; static constexpr int kAttribIdx_Y = 1;
@ -19,7 +19,7 @@ static constexpr int kAttribIdx_VertexData = 2;
/** /**
* This class and its subclasses implement the coverage processor with vertex shaders. * This class and its subclasses implement the coverage processor with vertex shaders.
*/ */
class GrCCPRCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor { class GrCCCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
protected: protected:
VSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {} VSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
@ -29,7 +29,7 @@ protected:
} }
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final { void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
const GrCCPRCoverageProcessor& proc = args.fGP.cast<GrCCPRCoverageProcessor>(); const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();
// Vertex shader. // Vertex shader.
GrGLSLVertexBuilder* v = args.fVertBuilder; GrGLSLVertexBuilder* v = args.fVertBuilder;
@ -69,7 +69,7 @@ protected:
fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage); fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
} }
virtual const char* emitVertexPosition(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*, virtual const char* emitVertexPosition(const GrCCCoverageProcessor&, GrGLSLVertexBuilder*,
GrGPArgs*) const = 0; GrGPArgs*) const = 0;
virtual ~VSImpl() {} virtual ~VSImpl() {}
@ -208,12 +208,12 @@ GR_DECLARE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);
* Generates a conservative raster hull around a convex polygon. For triangles, we also generate * Generates a conservative raster hull around a convex polygon. For triangles, we also generate
* independent conservative rasters around each edge. (See comments for RenderPass) * independent conservative rasters around each edge. (See comments for RenderPass)
*/ */
class VSHullAndEdgeImpl : public GrCCPRCoverageProcessor::VSImpl { class VSHullAndEdgeImpl : public GrCCCoverageProcessor::VSImpl {
public: public:
VSHullAndEdgeImpl(std::unique_ptr<Shader> shader, int numSides) VSHullAndEdgeImpl(std::unique_ptr<Shader> shader, int numSides)
: VSImpl(std::move(shader)), fNumSides(numSides) {} : VSImpl(std::move(shader)), fNumSides(numSides) {}
const char* emitVertexPosition(const GrCCPRCoverageProcessor& proc, GrGLSLVertexBuilder* v, const char* emitVertexPosition(const GrCCCoverageProcessor& proc, GrGLSLVertexBuilder* v,
GrGPArgs* gpArgs) const override { GrGPArgs* gpArgs) const override {
Shader::GeometryVars vars; Shader::GeometryVars vars;
fShader->emitSetupCode(v, "pts", nullptr, "wind", &vars); fShader->emitSetupCode(v, "pts", nullptr, "wind", &vars);
@ -300,11 +300,11 @@ GR_DECLARE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);
/** /**
* Generates conservative rasters around corners. (See comments for RenderPass) * Generates conservative rasters around corners. (See comments for RenderPass)
*/ */
class VSCornerImpl : public GrCCPRCoverageProcessor::VSImpl { class VSCornerImpl : public GrCCCoverageProcessor::VSImpl {
public: public:
VSCornerImpl(std::unique_ptr<Shader> shader) : VSImpl(std::move(shader)) {} VSCornerImpl(std::unique_ptr<Shader> shader) : VSImpl(std::move(shader)) {}
const char* emitVertexPosition(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder* v, const char* emitVertexPosition(const GrCCCoverageProcessor&, GrGLSLVertexBuilder* v,
GrGPArgs* gpArgs) const override { GrGPArgs* gpArgs) const override {
Shader::GeometryVars vars; Shader::GeometryVars vars;
v->codeAppend ("int corner_id = sk_VertexID / 4;"); v->codeAppend ("int corner_id = sk_VertexID / 4;");
@ -319,7 +319,7 @@ public:
} }
}; };
void GrCCPRCoverageProcessor::initVS(GrResourceProvider* rp) { void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) {
SkASSERT(Impl::kVertexShader == fImpl); SkASSERT(Impl::kVertexShader == fImpl);
GrVertexAttribType inputPtsType = RenderPassIsCubic(fRenderPass) ? GrVertexAttribType inputPtsType = RenderPassIsCubic(fRenderPass) ?
@ -388,9 +388,9 @@ void GrCCPRCoverageProcessor::initVS(GrResourceProvider* rp) {
#endif #endif
} }
static int num_indices_per_instance(GrCCPRCoverageProcessor::RenderPass pass) { static int num_indices_per_instance(GrCCCoverageProcessor::RenderPass pass) {
switch (pass) { switch (pass) {
using RenderPass = GrCCPRCoverageProcessor::RenderPass; using RenderPass = GrCCCoverageProcessor::RenderPass;
case RenderPass::kTriangleHulls: case RenderPass::kTriangleHulls:
return SK_ARRAY_COUNT(kHull3AndEdgeIndices); return SK_ARRAY_COUNT(kHull3AndEdgeIndices);
case RenderPass::kQuadraticHulls: case RenderPass::kQuadraticHulls:
@ -409,8 +409,8 @@ static int num_indices_per_instance(GrCCPRCoverageProcessor::RenderPass pass) {
return 0; return 0;
} }
void GrCCPRCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, void GrCCCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, SkTArray<GrMesh>* out) const { int baseInstance, SkTArray<GrMesh>* out) const {
SkASSERT(Impl::kVertexShader == fImpl); SkASSERT(Impl::kVertexShader == fImpl);
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangles); GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangles);
mesh.setIndexedInstanced(fIndexBuffer.get(), num_indices_per_instance(fRenderPass), mesh.setIndexedInstanced(fIndexBuffer.get(), num_indices_per_instance(fRenderPass),
@ -420,21 +420,20 @@ void GrCCPRCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanc
} }
} }
GrGLSLPrimitiveProcessor* GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const {
GrCCPRCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shader) const {
switch (fRenderPass) { switch (fRenderPass) {
case RenderPass::kTriangleHulls: case RenderPass::kTriangleHulls:
return new VSHullAndEdgeImpl(std::move(shader), 3); return new VSHullAndEdgeImpl(std::move(shadr), 3);
case RenderPass::kQuadraticHulls: case RenderPass::kQuadraticHulls:
case RenderPass::kCubicHulls: case RenderPass::kCubicHulls:
return new VSHullAndEdgeImpl(std::move(shader), 4); return new VSHullAndEdgeImpl(std::move(shadr), 4);
case RenderPass::kTriangleEdges: case RenderPass::kTriangleEdges:
SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl."); SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
return nullptr; return nullptr;
case RenderPass::kTriangleCorners: case RenderPass::kTriangleCorners:
case RenderPass::kQuadraticCorners: case RenderPass::kQuadraticCorners:
case RenderPass::kCubicCorners: case RenderPass::kCubicCorners:
return new VSCornerImpl(std::move(shader)); return new VSCornerImpl(std::move(shadr));
} }
SK_ABORT("Invalid RenderPass"); SK_ABORT("Invalid RenderPass");
return nullptr; return nullptr;

View File

@ -5,16 +5,16 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRCubicShader.h" #include "GrCCCubicShader.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
using Shader = GrCCPRCoverageProcessor::Shader; using Shader = GrCCCoverageProcessor::Shader;
void GrCCPRCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
const char* repetitionID, const char* wind, const char* repetitionID, const char* wind,
GeometryVars* vars) const { GeometryVars* vars) const {
// Find the cubic's power basis coefficients. // Find the cubic's power basis coefficients.
s->codeAppendf("float2x4 C = float4x4(-1, 3, -3, 1, " s->codeAppendf("float2x4 C = float4x4(-1, 3, -3, 1, "
" 3, -6, 3, 0, " " 3, -6, 3, 0, "
@ -75,10 +75,10 @@ void GrCCPRCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts
this->onEmitSetupCode(s, pts, repetitionID, vars); this->onEmitSetupCode(s, pts, repetitionID, vars);
} }
Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, Shader::WindHandling GrCCCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, GrGLSLVarying::Scope scope,
SkString* code, const char* position, SkString* code, const char* position,
const char* coverage, const char* /*wind*/) { const char* coverage, const char* /*wind*/) {
SkASSERT(!coverage); SkASSERT(!coverage);
fKLMD.reset(kFloat4_GrSLType, scope); fKLMD.reset(kFloat4_GrSLType, scope);
@ -91,8 +91,8 @@ Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* var
return WindHandling::kNotHandled; return WindHandling::kNotHandled;
} }
void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, void GrCCCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code) { GrGLSLVarying::Scope scope, SkString* code) {
fGradMatrix.reset(kFloat2x2_GrSLType, scope); fGradMatrix.reset(kFloat2x2_GrSLType, scope);
varyingHandler->addVarying("grad_matrix", &fGradMatrix); varyingHandler->addVarying("grad_matrix", &fGradMatrix);
// "klm" was just defined by the base class. // "klm" was just defined by the base class.
@ -101,8 +101,8 @@ void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str()); OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str());
} }
void GrCCPRCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, void GrCCCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;", f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn()); fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
f->codeAppend ("float f = k*k*k - l*m;"); f->codeAppend ("float f = k*k*k - l*m;");
@ -111,14 +111,14 @@ void GrCCPRCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat closing edge. f->codeAppendf("%s += min(d, 0);", outputCoverage); // Flat closing edge.
} }
void GrCCPRCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, void GrCCCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
const char* repetitionID, GeometryVars* vars) const { const char* repetitionID, GeometryVars* vars) const {
s->codeAppendf("float2 corner = %s[%s * 3];", pts, repetitionID); s->codeAppendf("float2 corner = %s[%s * 3];", pts, repetitionID);
vars->fCornerVars.fPoint = "corner"; vars->fCornerVars.fPoint = "corner";
} }
void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, void GrCCCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code) { GrGLSLVarying::Scope scope, SkString* code) {
fdKLMDdx.reset(kFloat4_GrSLType, scope); fdKLMDdx.reset(kFloat4_GrSLType, scope);
varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx); varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx);
code->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);", code->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
@ -132,8 +132,8 @@ void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandle
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str()); fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
} }
void GrCCPRCubicCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, void GrCCCubicCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("float2x4 grad_klmd = float2x4(%s, %s);", fdKLMDdx.fsIn(), fdKLMDdy.fsIn()); f->codeAppendf("float2x4 grad_klmd = float2x4(%s, %s);", fdKLMDdx.fsIn(), fdKLMDdy.fsIn());
// Erase what the previous hull shader wrote. We don't worry about the two corners falling on // Erase what the previous hull shader wrote. We don't worry about the two corners falling on

View File

@ -5,10 +5,10 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRCubicShader_DEFINED #ifndef GrCCCubicShader_DEFINED
#define GrCCPRCubicShader_DEFINED #define GrCCCubicShader_DEFINED
#include "ccpr/GrCCPRCoverageProcessor.h" #include "ccpr/GrCCCoverageProcessor.h"
/** /**
* This class renders the coverage of convex closed cubic segments using the techniques outlined in * This class renders the coverage of convex closed cubic segments using the techniques outlined in
@ -19,9 +19,9 @@
* *
* The provided curve segments must be convex, monotonic with respect to the vector of their closing * The provided curve segments must be convex, monotonic with respect to the vector of their closing
* edge [P3 - P0], and must not contain or be near any inflection points or loop intersections. * edge [P3 - P0], and must not contain or be near any inflection points or loop intersections.
* (Use GrCCPRGeometry.) * (Use GrCCGeometry.)
*/ */
class GrCCPRCubicShader : public GrCCPRCoverageProcessor::Shader { class GrCCCubicShader : public GrCCCoverageProcessor::Shader {
protected: protected:
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID, void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
const char* wind, GeometryVars*) const final; const char* wind, GeometryVars*) const final;
@ -39,14 +39,14 @@ protected:
GrGLSLVarying fKLMD; GrGLSLVarying fKLMD;
}; };
class GrCCPRCubicHullShader : public GrCCPRCubicShader { class GrCCCubicHullShader : public GrCCCubicShader {
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override; void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override; void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
GrGLSLVarying fGradMatrix; GrGLSLVarying fGradMatrix;
}; };
class GrCCPRCubicCornerShader : public GrCCPRCubicShader { class GrCCCubicCornerShader : public GrCCCubicShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID, void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override; GeometryVars*) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override; void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;

View File

@ -5,7 +5,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRGeometry.h" #include "GrCCGeometry.h"
#include "GrTypes.h" #include "GrTypes.h"
#include "GrPathUtils.h" #include "GrPathUtils.h"
@ -18,12 +18,12 @@ GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
GR_STATIC_ASSERT(2 * sizeof(float) == sizeof(SkPoint)); GR_STATIC_ASSERT(2 * sizeof(float) == sizeof(SkPoint));
GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX)); GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX));
void GrCCPRGeometry::beginPath() { void GrCCGeometry::beginPath() {
SkASSERT(!fBuildingContour); SkASSERT(!fBuildingContour);
fVerbs.push_back(Verb::kBeginPath); fVerbs.push_back(Verb::kBeginPath);
} }
void GrCCPRGeometry::beginContour(const SkPoint& devPt) { void GrCCGeometry::beginContour(const SkPoint& devPt) {
SkASSERT(!fBuildingContour); SkASSERT(!fBuildingContour);
fCurrFanPoint = fCurrAnchorPoint = devPt; fCurrFanPoint = fCurrAnchorPoint = devPt;
@ -35,10 +35,10 @@ void GrCCPRGeometry::beginContour(const SkPoint& devPt) {
fPoints.push_back(devPt); fPoints.push_back(devPt);
fVerbs.push_back(Verb::kBeginContour); fVerbs.push_back(Verb::kBeginContour);
SkDEBUGCODE(fBuildingContour = true;) SkDEBUGCODE(fBuildingContour = true);
} }
void GrCCPRGeometry::lineTo(const SkPoint& devPt) { void GrCCGeometry::lineTo(const SkPoint& devPt) {
SkASSERT(fBuildingContour); SkASSERT(fBuildingContour);
SkASSERT(fCurrFanPoint == fPoints.back()); SkASSERT(fCurrFanPoint == fPoints.back());
fCurrFanPoint = devPt; fCurrFanPoint = devPt;
@ -90,7 +90,7 @@ static inline Sk2f lerp(const Sk2f& a, const Sk2f& b, const Sk2f& t) {
return SkNx_fma(t, b - a, a); return SkNx_fma(t, b - a, a);
} }
void GrCCPRGeometry::quadraticTo(const SkPoint& devP0, const SkPoint& devP1) { void GrCCGeometry::quadraticTo(const SkPoint& devP0, const SkPoint& devP1) {
SkASSERT(fBuildingContour); SkASSERT(fBuildingContour);
SkASSERT(fCurrFanPoint == fPoints.back()); SkASSERT(fCurrFanPoint == fPoints.back());
@ -102,8 +102,8 @@ void GrCCPRGeometry::quadraticTo(const SkPoint& devP0, const SkPoint& devP1) {
this->appendMonotonicQuadratics(p0, p1, p2); this->appendMonotonicQuadratics(p0, p1, p2);
} }
inline void GrCCPRGeometry::appendMonotonicQuadratics(const Sk2f& p0, const Sk2f& p1, inline void GrCCGeometry::appendMonotonicQuadratics(const Sk2f& p0, const Sk2f& p1,
const Sk2f& p2) { const Sk2f& p2) {
Sk2f tan0 = p1 - p0; Sk2f tan0 = p1 - p0;
Sk2f tan1 = p2 - p1; Sk2f tan1 = p2 - p1;
@ -141,8 +141,8 @@ inline void GrCCPRGeometry::appendMonotonicQuadratics(const Sk2f& p0, const Sk2f
this->appendSingleMonotonicQuadratic(p012, p12, p2); this->appendSingleMonotonicQuadratic(p012, p12, p2);
} }
inline void GrCCPRGeometry::appendSingleMonotonicQuadratic(const Sk2f& p0, const Sk2f& p1, inline void GrCCGeometry::appendSingleMonotonicQuadratic(const Sk2f& p0, const Sk2f& p1,
const Sk2f& p2) { const Sk2f& p2) {
SkASSERT(fPoints.back() == SkPoint::Make(p0[0], p0[1])); SkASSERT(fPoints.back() == SkPoint::Make(p0[0], p0[1]));
// Don't send curves to the GPU if we know they are nearly flat (or just very small). // Don't send curves to the GPU if we know they are nearly flat (or just very small).
@ -285,8 +285,8 @@ static inline bool is_cubic_nearly_quadratic(const Sk2f& p0, const Sk2f& p1, con
return ((c1 - c2).abs() <= 1).allTrue(); return ((c1 - c2).abs() <= 1).allTrue();
} }
void GrCCPRGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const SkPoint& devP3, void GrCCGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const SkPoint& devP3,
float inflectPad, float loopIntersectPad) { float inflectPad, float loopIntersectPad) {
SkASSERT(fBuildingContour); SkASSERT(fBuildingContour);
SkASSERT(fCurrFanPoint == fPoints.back()); SkASSERT(fCurrFanPoint == fPoints.back());
@ -390,15 +390,15 @@ void GrCCPRGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const S
// Next we chop the cubic up at all T0..T3 inside 0..1 and store the resulting segments. // Next we chop the cubic up at all T0..T3 inside 0..1 and store the resulting segments.
if (T1 >= 1) { if (T1 >= 1) {
// Only sections 1 & 2 can be in 0..1. // Only sections 1 & 2 can be in 0..1.
this->chopCubic<&GrCCPRGeometry::appendMonotonicCubics, this->chopCubic<&GrCCGeometry::appendMonotonicCubics,
&GrCCPRGeometry::appendCubicApproximation>(p0, p1, p2, p3, T0); &GrCCGeometry::appendCubicApproximation>(p0, p1, p2, p3, T0);
return; return;
} }
if (T2 <= 0) { if (T2 <= 0) {
// Only sections 4 & 5 can be in 0..1. // Only sections 4 & 5 can be in 0..1.
this->chopCubic<&GrCCPRGeometry::appendCubicApproximation, this->chopCubic<&GrCCGeometry::appendCubicApproximation,
&GrCCPRGeometry::appendMonotonicCubics>(p0, p1, p2, p3, T3); &GrCCGeometry::appendMonotonicCubics>(p0, p1, p2, p3, T3);
return; return;
} }
@ -414,8 +414,8 @@ void GrCCPRGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const S
Sk2f abcd1 = lerp(abc1, bcd1, T1T1); Sk2f abcd1 = lerp(abc1, bcd1, T1T1);
// Sections 1 & 2. // Sections 1 & 2.
this->chopCubic<&GrCCPRGeometry::appendMonotonicCubics, this->chopCubic<&GrCCGeometry::appendMonotonicCubics,
&GrCCPRGeometry::appendCubicApproximation>(p0, ab1, abc1, abcd1, T0/T1); &GrCCGeometry::appendCubicApproximation>(p0, ab1, abc1, abcd1, T0/T1);
if (T2 >= 1) { if (T2 >= 1) {
// The rest of the curve is Section 3 (middle section). // The rest of the curve is Section 3 (middle section).
@ -453,14 +453,14 @@ void GrCCPRGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const S
} }
// Sections 4 & 5. // Sections 4 & 5.
this->chopCubic<&GrCCPRGeometry::appendCubicApproximation, this->chopCubic<&GrCCGeometry::appendCubicApproximation,
&GrCCPRGeometry::appendMonotonicCubics>(abcd2, bcd2, cd2, p3, (T3-T2) / (1-T2)); &GrCCGeometry::appendMonotonicCubics>(abcd2, bcd2, cd2, p3, (T3-T2) / (1-T2));
} }
template<GrCCPRGeometry::AppendCubicFn AppendLeftRight> template<GrCCGeometry::AppendCubicFn AppendLeftRight>
inline void GrCCPRGeometry::chopCubicAtMidTangent(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, inline void GrCCGeometry::chopCubicAtMidTangent(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
const Sk2f& p3, const Sk2f& tan0, const Sk2f& p3, const Sk2f& tan0,
const Sk2f& tan3, int maxFutureSubdivisions) { const Sk2f& tan3, int maxFutureSubdivisions) {
// Find the T value whose tangent is perpendicular to the vector that bisects tan0 and -tan3. // Find the T value whose tangent is perpendicular to the vector that bisects tan0 and -tan3.
Sk2f n = normalize(tan0) - normalize(tan3); Sk2f n = normalize(tan0) - normalize(tan3);
@ -482,9 +482,9 @@ inline void GrCCPRGeometry::chopCubicAtMidTangent(const Sk2f& p0, const Sk2f& p1
this->chopCubic<AppendLeftRight, AppendLeftRight>(p0, p1, p2, p3, T, maxFutureSubdivisions); this->chopCubic<AppendLeftRight, AppendLeftRight>(p0, p1, p2, p3, T, maxFutureSubdivisions);
} }
template<GrCCPRGeometry::AppendCubicFn AppendLeft, GrCCPRGeometry::AppendCubicFn AppendRight> template<GrCCGeometry::AppendCubicFn AppendLeft, GrCCGeometry::AppendCubicFn AppendRight>
inline void GrCCPRGeometry::chopCubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, inline void GrCCGeometry::chopCubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
const Sk2f& p3, float T, int maxFutureSubdivisions) { const Sk2f& p3, float T, int maxFutureSubdivisions) {
if (T >= 1) { if (T >= 1) {
(this->*AppendLeft)(p0, p1, p2, p3, maxFutureSubdivisions); (this->*AppendLeft)(p0, p1, p2, p3, maxFutureSubdivisions);
return; return;
@ -506,8 +506,8 @@ inline void GrCCPRGeometry::chopCubic(const Sk2f& p0, const Sk2f& p1, const Sk2f
(this->*AppendRight)(abcd, bcd, cd, p3, maxFutureSubdivisions); (this->*AppendRight)(abcd, bcd, cd, p3, maxFutureSubdivisions);
} }
void GrCCPRGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, void GrCCGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
const Sk2f& p3, int maxSubdivisions) { const Sk2f& p3, int maxSubdivisions) {
SkASSERT(maxSubdivisions >= 0); SkASSERT(maxSubdivisions >= 0);
if ((p0 == p3).allTrue()) { if ((p0 == p3).allTrue()) {
return; return;
@ -518,9 +518,9 @@ void GrCCPRGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const
Sk2f tan3 = first_unless_nearly_zero(p3 - p2, p3 - p1); Sk2f tan3 = first_unless_nearly_zero(p3 - p2, p3 - p1);
if (!is_convex_curve_monotonic(p0, tan0, p3, tan3)) { if (!is_convex_curve_monotonic(p0, tan0, p3, tan3)) {
this->chopCubicAtMidTangent<&GrCCPRGeometry::appendMonotonicCubics>(p0, p1, p2, p3, this->chopCubicAtMidTangent<&GrCCGeometry::appendMonotonicCubics>(p0, p1, p2, p3,
tan0, tan3, tan0, tan3,
maxSubdivisions-1); maxSubdivisions - 1);
return; return;
} }
} }
@ -542,8 +542,8 @@ void GrCCPRGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const
++fCurrContourTallies.fCubics; ++fCurrContourTallies.fCubics;
} }
void GrCCPRGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, void GrCCGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
const Sk2f& p3, int maxSubdivisions) { const Sk2f& p3, int maxSubdivisions) {
SkASSERT(maxSubdivisions >= 0); SkASSERT(maxSubdivisions >= 0);
if ((p0 == p3).allTrue()) { if ((p0 == p3).allTrue()) {
return; return;
@ -561,9 +561,9 @@ void GrCCPRGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, co
Sk2f tan0, tan3, c; Sk2f tan0, tan3, c;
if (!is_cubic_nearly_quadratic(p0, p1, p2, p3, tan0, tan3, c) && maxSubdivisions) { if (!is_cubic_nearly_quadratic(p0, p1, p2, p3, tan0, tan3, c) && maxSubdivisions) {
this->chopCubicAtMidTangent<&GrCCPRGeometry::appendCubicApproximation>(p0, p1, p2, p3, this->chopCubicAtMidTangent<&GrCCGeometry::appendCubicApproximation>(p0, p1, p2, p3,
tan0, tan3, tan0, tan3,
maxSubdivisions - 1); maxSubdivisions - 1);
return; return;
} }
@ -574,7 +574,7 @@ void GrCCPRGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, co
} }
} }
GrCCPRGeometry::PrimitiveTallies GrCCPRGeometry::endContour() { GrCCGeometry::PrimitiveTallies GrCCGeometry::endContour() {
SkASSERT(fBuildingContour); SkASSERT(fBuildingContour);
SkASSERT(fVerbs.count() >= fCurrContourTallies.fTriangles); SkASSERT(fVerbs.count() >= fCurrContourTallies.fTriangles);
@ -590,6 +590,6 @@ GrCCPRGeometry::PrimitiveTallies GrCCPRGeometry::endContour() {
fCurrContourTallies.fTriangles = SkTMax(fanSize - 2, 0); fCurrContourTallies.fTriangles = SkTMax(fanSize - 2, 0);
SkDEBUGCODE(fBuildingContour = false;) SkDEBUGCODE(fBuildingContour = false);
return fCurrContourTallies; return fCurrContourTallies;
} }

View File

@ -5,8 +5,8 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrGrCCPRGeometry_DEFINED #ifndef GrGrCCGeometry_DEFINED
#define GrGrCCPRGeometry_DEFINED #define GrGrCCGeometry_DEFINED
#include "SkGeometry.h" #include "SkGeometry.h"
#include "SkNx.h" #include "SkNx.h"
@ -15,12 +15,12 @@
/** /**
* This class chops device-space contours up into a series of segments that CCPR knows how to * This class chops device-space contours up into a series of segments that CCPR knows how to
* render. (See GrCCPRGeometry::Verb.) * render. (See GrCCGeometry::Verb.)
* *
* NOTE: This must be done in device space, since an affine transformation can change whether a * NOTE: This must be done in device space, since an affine transformation can change whether a
* curve is monotonic. * curve is monotonic.
*/ */
class GrCCPRGeometry { class GrCCGeometry {
public: public:
// These are the verbs that CCPR knows how to draw. If a path has any segments that don't map to // These are the verbs that CCPR knows how to draw. If a path has any segments that don't map to
// this list, then they are chopped into smaller ones that do. A list of these comprise a // this list, then they are chopped into smaller ones that do. A list of these comprise a
@ -45,7 +45,7 @@ public:
PrimitiveTallies operator-(const PrimitiveTallies&) const; PrimitiveTallies operator-(const PrimitiveTallies&) const;
}; };
GrCCPRGeometry(int numSkPoints = 0, int numSkVerbs = 0) GrCCGeometry(int numSkPoints = 0, int numSkVerbs = 0)
: fPoints(numSkPoints * 3) // Reserve for a 3x expansion in points and verbs. : fPoints(numSkPoints * 3) // Reserve for a 3x expansion in points and verbs.
, fVerbs(numSkVerbs * 3) {} , fVerbs(numSkVerbs * 3) {}
@ -94,9 +94,9 @@ private:
inline void appendMonotonicQuadratics(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2); inline void appendMonotonicQuadratics(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2);
inline void appendSingleMonotonicQuadratic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2); inline void appendSingleMonotonicQuadratic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2);
using AppendCubicFn = void(GrCCPRGeometry::*)(const Sk2f& p0, const Sk2f& p1, using AppendCubicFn = void(GrCCGeometry::*)(const Sk2f& p0, const Sk2f& p1,
const Sk2f& p2, const Sk2f& p3, const Sk2f& p2, const Sk2f& p3,
int maxSubdivisions); int maxSubdivisions);
static constexpr int kMaxSubdivionsPerCubicSection = 2; static constexpr int kMaxSubdivionsPerCubicSection = 2;
template<AppendCubicFn AppendLeftRight> template<AppendCubicFn AppendLeftRight>
@ -125,14 +125,14 @@ private:
SkSTArray<128, Verb, true> fVerbs; SkSTArray<128, Verb, true> fVerbs;
}; };
inline void GrCCPRGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) { inline void GrCCGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) {
fTriangles += b.fTriangles; fTriangles += b.fTriangles;
fQuadratics += b.fQuadratics; fQuadratics += b.fQuadratics;
fCubics += b.fCubics; fCubics += b.fCubics;
} }
GrCCPRGeometry::PrimitiveTallies GrCCGeometry::PrimitiveTallies
inline GrCCPRGeometry::PrimitiveTallies::operator-(const PrimitiveTallies& b) const { inline GrCCGeometry::PrimitiveTallies::operator-(const PrimitiveTallies& b) const {
return {fTriangles - b.fTriangles, return {fTriangles - b.fTriangles,
fQuadratics - b.fQuadratics, fQuadratics - b.fQuadratics,
fCubics - b.fCubics}; fCubics - b.fCubics};

View File

@ -5,7 +5,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRPathProcessor.h" #include "GrCCPathProcessor.h"
#include "GrOnFlushResourceProvider.h" #include "GrOnFlushResourceProvider.h"
#include "GrTexture.h" #include "GrTexture.h"
@ -36,14 +36,14 @@ static constexpr float kOctoEdgeNorms[8 * 4] = {
GR_DECLARE_STATIC_UNIQUE_KEY(gVertexBufferKey); GR_DECLARE_STATIC_UNIQUE_KEY(gVertexBufferKey);
sk_sp<const GrBuffer> GrCCPRPathProcessor::FindVertexBuffer(GrOnFlushResourceProvider* onFlushRP) { sk_sp<const GrBuffer> GrCCPathProcessor::FindVertexBuffer(GrOnFlushResourceProvider* onFlushRP) {
GR_DEFINE_STATIC_UNIQUE_KEY(gVertexBufferKey); GR_DEFINE_STATIC_UNIQUE_KEY(gVertexBufferKey);
return onFlushRP->findOrMakeStaticBuffer(kVertex_GrBufferType, sizeof(kOctoEdgeNorms), return onFlushRP->findOrMakeStaticBuffer(kVertex_GrBufferType, sizeof(kOctoEdgeNorms),
kOctoEdgeNorms, gVertexBufferKey); kOctoEdgeNorms, gVertexBufferKey);
} }
// Index buffer for the octagon defined above. // Index buffer for the octagon defined above.
static uint16_t kOctoIndices[GrCCPRPathProcessor::kPerInstanceIndexCount] = { static uint16_t kOctoIndices[GrCCPathProcessor::kPerInstanceIndexCount] = {
0, 4, 2, 0, 4, 2,
0, 6, 4, 0, 6, 4,
0, 2, 1, 0, 2, 1,
@ -54,15 +54,15 @@ static uint16_t kOctoIndices[GrCCPRPathProcessor::kPerInstanceIndexCount] = {
GR_DECLARE_STATIC_UNIQUE_KEY(gIndexBufferKey); GR_DECLARE_STATIC_UNIQUE_KEY(gIndexBufferKey);
sk_sp<const GrBuffer> GrCCPRPathProcessor::FindIndexBuffer(GrOnFlushResourceProvider* onFlushRP) { sk_sp<const GrBuffer> GrCCPathProcessor::FindIndexBuffer(GrOnFlushResourceProvider* onFlushRP) {
GR_DEFINE_STATIC_UNIQUE_KEY(gIndexBufferKey); GR_DEFINE_STATIC_UNIQUE_KEY(gIndexBufferKey);
return onFlushRP->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kOctoIndices), return onFlushRP->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kOctoIndices),
kOctoIndices, gIndexBufferKey); kOctoIndices, gIndexBufferKey);
} }
GrCCPRPathProcessor::GrCCPRPathProcessor(GrResourceProvider* rp, sk_sp<GrTextureProxy> atlas, GrCCPathProcessor::GrCCPathProcessor(GrResourceProvider* rp, sk_sp<GrTextureProxy> atlas,
SkPath::FillType fillType, const GrShaderCaps& shaderCaps) SkPath::FillType fillType, const GrShaderCaps& shaderCaps)
: INHERITED(kGrCCPRPathProcessor_ClassID) : INHERITED(kGrCCPathProcessor_ClassID)
, fFillType(fillType) , fFillType(fillType)
, fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest, , fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest,
GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) { GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) {
@ -95,7 +95,7 @@ GrCCPRPathProcessor::GrCCPRPathProcessor(GrResourceProvider* rp, sk_sp<GrTexture
this->addTextureSampler(&fAtlasAccess); this->addTextureSampler(&fAtlasAccess);
} }
void GrCCPRPathProcessor::getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { void GrCCPathProcessor::getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
b->add32((fFillType << 16) | this->atlasProxy()->origin()); b->add32((fFillType << 16) | this->atlasProxy()->origin());
} }
@ -106,7 +106,7 @@ public:
private: private:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override { FPCoordTransformIter&& transformIter) override {
const GrCCPRPathProcessor& proc = primProc.cast<GrCCPRPathProcessor>(); const GrCCPathProcessor& proc = primProc.cast<GrCCPathProcessor>();
pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.atlas()->width(), pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.atlas()->width(),
1.0f / proc.atlas()->height()); 1.0f / proc.atlas()->height());
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
@ -117,13 +117,13 @@ private:
typedef GrGLSLGeometryProcessor INHERITED; typedef GrGLSLGeometryProcessor INHERITED;
}; };
GrGLSLPrimitiveProcessor* GrCCPRPathProcessor::createGLSLInstance(const GrShaderCaps&) const { GrGLSLPrimitiveProcessor* GrCCPathProcessor::createGLSLInstance(const GrShaderCaps&) const {
return new GLSLPathProcessor(); return new GLSLPathProcessor();
} }
void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
using InstanceAttribs = GrCCPRPathProcessor::InstanceAttribs; using InstanceAttribs = GrCCPathProcessor::InstanceAttribs;
const GrCCPRPathProcessor& proc = args.fGP.cast<GrCCPRPathProcessor>(); const GrCCPathProcessor& proc = args.fGP.cast<GrCCPathProcessor>();
GrGLSLUniformHandler* uniHandler = args.fUniformHandler; GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;

View File

@ -5,8 +5,8 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRPathProcessor_DEFINED #ifndef GrCCPathProcessor_DEFINED
#define GrCCPRPathProcessor_DEFINED #define GrCCPathProcessor_DEFINED
#include "GrGeometryProcessor.h" #include "GrGeometryProcessor.h"
#include "SkPath.h" #include "SkPath.h"
@ -16,7 +16,7 @@ class GrOnFlushResourceProvider;
class GrShaderCaps; class GrShaderCaps;
/** /**
* This class draws AA paths using the coverage count masks produced by GrCCPRCoverageProcessor. * This class draws AA paths using the coverage count masks produced by GrCCCoverageProcessor.
* *
* Paths are drawn as bloated octagons, and coverage is derived from the coverage count mask and * Paths are drawn as bloated octagons, and coverage is derived from the coverage count mask and
* fill rule. * fill rule.
@ -24,7 +24,7 @@ class GrShaderCaps;
* The caller must set up an instance buffer as detailed below, then draw indexed-instanced * The caller must set up an instance buffer as detailed below, then draw indexed-instanced
* triangles using the index and vertex buffers provided by this class. * triangles using the index and vertex buffers provided by this class.
*/ */
class GrCCPRPathProcessor : public GrGeometryProcessor { class GrCCPathProcessor : public GrGeometryProcessor {
public: public:
static constexpr int kPerInstanceIndexCount = 6 * 3; static constexpr int kPerInstanceIndexCount = 6 * 3;
@ -55,10 +55,10 @@ public:
static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*); static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*);
static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*); static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*);
GrCCPRPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas, SkPath::FillType, GrCCPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas, SkPath::FillType,
const GrShaderCaps&); const GrShaderCaps&);
const char* name() const override { return "GrCCPRPathProcessor"; } const char* name() const override { return "GrCCPathProcessor"; }
const GrSurfaceProxy* atlasProxy() const { return fAtlasAccess.proxy(); } const GrSurfaceProxy* atlasProxy() const { return fAtlasAccess.proxy(); }
const GrTexture* atlas() const { return fAtlasAccess.peekTexture(); } const GrTexture* atlas() const { return fAtlasAccess.peekTexture(); }
SkPath::FillType fillType() const { return fFillType; } SkPath::FillType fillType() const { return fFillType; }

View File

@ -5,17 +5,17 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRQuadraticShader.h" #include "GrCCQuadraticShader.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
using Shader = GrCCPRCoverageProcessor::Shader; using Shader = GrCCCoverageProcessor::Shader;
void GrCCPRQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, void GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
const char* repetitionID, const char* wind, const char* repetitionID, const char* wind,
GeometryVars* vars) const { GeometryVars* vars) const {
s->declareGlobal(fCanonicalMatrix); s->declareGlobal(fCanonicalMatrix);
s->codeAppendf("%s = float3x3(0.0, 0, 1, " s->codeAppendf("%s = float3x3(0.0, 0, 1, "
"0.5, 0, 1, " "0.5, 0, 1, "
@ -33,11 +33,11 @@ void GrCCPRQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char*
this->onEmitSetupCode(s, pts, repetitionID, vars); this->onEmitSetupCode(s, pts, repetitionID, vars);
} }
Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, Shader::WindHandling GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, GrGLSLVarying::Scope scope,
SkString* code, const char* position, SkString* code, const char* position,
const char* coverage, const char* coverage,
const char* /*wind*/) { const char* /*wind*/) {
SkASSERT(!coverage); SkASSERT(!coverage);
fXYD.reset(kFloat3_GrSLType, scope); fXYD.reset(kFloat3_GrSLType, scope);
@ -52,9 +52,9 @@ Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler*
return WindHandling::kNotHandled; return WindHandling::kNotHandled;
} }
void GrCCPRQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, void GrCCQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
const char* /*repetitionID*/, const char* /*repetitionID*/,
GeometryVars* vars) const { GeometryVars* vars) const {
// Find the T value whose tangent is halfway between the tangents at the endpionts. // Find the T value whose tangent is halfway between the tangents at the endpionts.
s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts); s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts);
s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts); s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts);
@ -71,30 +71,30 @@ void GrCCPRQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const
vars->fHullVars.fAlternatePoints = "quadratic_hull"; vars->fHullVars.fAlternatePoints = "quadratic_hull";
} }
void GrCCPRQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, void GrCCQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code) { GrGLSLVarying::Scope scope, SkString* code) {
fGrad.reset(kFloat2_GrSLType, scope); fGrad.reset(kFloat2_GrSLType, scope);
varyingHandler->addVarying("grad", &fGrad); varyingHandler->addVarying("grad", &fGrad);
code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);", code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str()); OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str());
} }
void GrCCPRQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, void GrCCQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));", f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGrad.fsIn(), fGrad.fsIn()); fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGrad.fsIn(), fGrad.fsIn());
f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage); f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYD.fsIn()); // Flat closing edge. f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYD.fsIn()); // Flat closing edge.
} }
void GrCCPRQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, void GrCCQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
const char* repetitionID, const char* repetitionID,
GeometryVars* vars) const { GeometryVars* vars) const {
s->codeAppendf("float2 corner = %s[%s * 2];", pts, repetitionID); s->codeAppendf("float2 corner = %s[%s * 2];", pts, repetitionID);
vars->fCornerVars.fPoint = "corner"; vars->fCornerVars.fPoint = "corner";
} }
void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, void GrCCQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code) { GrGLSLVarying::Scope scope, SkString* code) {
fdXYDdx.reset(kFloat3_GrSLType, scope); fdXYDdx.reset(kFloat3_GrSLType, scope);
varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx); varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx);
@ -109,8 +109,8 @@ void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHa
fEdgeDistanceEquation.c_str()); fEdgeDistanceEquation.c_str());
} }
void GrCCPRQuadraticCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, void GrCCQuadraticCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("float x = %s.x, y = %s.y, d = %s.z;", f->codeAppendf("float x = %s.x, y = %s.y, d = %s.z;",
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn()); fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn());
f->codeAppendf("float2x3 grad_xyd = float2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn()); f->codeAppendf("float2x3 grad_xyd = float2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn());

View File

@ -5,10 +5,10 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRQuadraticShader_DEFINED #ifndef GrCCQuadraticShader_DEFINED
#define GrCCPRQuadraticShader_DEFINED #define GrCCQuadraticShader_DEFINED
#include "ccpr/GrCCPRCoverageProcessor.h" #include "ccpr/GrCCCoverageProcessor.h"
/** /**
* This class renders the coverage of closed quadratic curves using the techniques outlined in * This class renders the coverage of closed quadratic curves using the techniques outlined in
@ -18,9 +18,9 @@
* https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf * https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf
* *
* The provided curves must be monotonic with respect to the vector of their closing edge [P2 - P0]. * The provided curves must be monotonic with respect to the vector of their closing edge [P2 - P0].
* (Use GrCCPRGeometry.) * (Use GrCCGeometry.)
*/ */
class GrCCPRQuadraticShader : public GrCCPRCoverageProcessor::Shader { class GrCCQuadraticShader : public GrCCCoverageProcessor::Shader {
protected: protected:
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID, void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
const char* wind, GeometryVars*) const final; const char* wind, GeometryVars*) const final;
@ -44,7 +44,7 @@ protected:
* uses simple distance-to-edge to subtract out coverage for the flat closing edge [P2 -> P0]. Since * uses simple distance-to-edge to subtract out coverage for the flat closing edge [P2 -> P0]. Since
* the provided curves are monotonic, this will get every pixel right except the two corners. * the provided curves are monotonic, this will get every pixel right except the two corners.
*/ */
class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader { class GrCCQuadraticHullShader : public GrCCQuadraticShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID, void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override; GeometryVars*) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override; void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
@ -56,7 +56,7 @@ class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader {
/** /**
* This pass fixes the corners of a closed quadratic segment with soft MSAA. * This pass fixes the corners of a closed quadratic segment with soft MSAA.
*/ */
class GrCCPRQuadraticCornerShader : public GrCCPRQuadraticShader { class GrCCQuadraticCornerShader : public GrCCQuadraticShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID, void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override; GeometryVars*) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override; void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;

View File

@ -5,17 +5,17 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrCCPRTriangleShader.h" #include "GrCCTriangleShader.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h"
using Shader = GrCCPRCoverageProcessor::Shader; using Shader = GrCCCoverageProcessor::Shader;
Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, Shader::WindHandling GrCCTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, GrGLSLVarying::Scope scope,
SkString* code, const char* /*position*/, SkString* code, const char* /*position*/,
const char* coverage, const char* wind) { const char* coverage, const char* wind) {
fCoverageTimesWind.reset(kHalf_GrSLType, scope); fCoverageTimesWind.reset(kHalf_GrSLType, scope);
if (!coverage) { if (!coverage) {
varyingHandler->addFlatVarying("wind", &fCoverageTimesWind); varyingHandler->addFlatVarying("wind", &fCoverageTimesWind);
@ -27,14 +27,14 @@ Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler*
return WindHandling::kHandled; return WindHandling::kHandled;
} }
void GrCCPRTriangleShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, void GrCCTriangleShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
f->codeAppendf("%s = %s;", outputCoverage, fCoverageTimesWind.fsIn()); f->codeAppendf("%s = %s;", outputCoverage, fCoverageTimesWind.fsIn());
} }
void GrCCPRTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, void GrCCTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
const char* repetitionID, const char* wind, const char* repetitionID, const char* wind,
GeometryVars* vars) const { GeometryVars* vars) const {
s->codeAppendf("float2 corner = %s[%s];", pts, repetitionID); s->codeAppendf("float2 corner = %s[%s];", pts, repetitionID);
vars->fCornerVars.fPoint = "corner"; vars->fCornerVars.fPoint = "corner";
@ -87,10 +87,10 @@ void GrCCPRTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const
} }
Shader::WindHandling Shader::WindHandling
GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, GrCCTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code, GrGLSLVarying::Scope scope, SkString* code,
const char* position, const char* coverage, const char* position, const char* coverage,
const char* /*wind*/) { const char* /*wind*/) {
SkASSERT(!coverage); SkASSERT(!coverage);
fCornerLocationInAABoxes.reset(kFloat2x2_GrSLType, scope); fCornerLocationInAABoxes.reset(kFloat2x2_GrSLType, scope);
@ -109,8 +109,8 @@ GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
return WindHandling::kNotHandled; return WindHandling::kNotHandled;
} }
void GrCCPRTriangleCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, void GrCCTriangleCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const { const char* outputCoverage) const {
// By the time we reach this shader, the pixel is in the following state: // By the time we reach this shader, the pixel is in the following state:
// //
// 1. The hull shader has emitted a coverage of 1. // 1. The hull shader has emitted a coverage of 1.

View File

@ -5,10 +5,10 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef GrCCPRTriangleShader_DEFINED #ifndef GrCCTriangleShader_DEFINED
#define GrCCPRTriangleShader_DEFINED #define GrCCTriangleShader_DEFINED
#include "ccpr/GrCCPRCoverageProcessor.h" #include "ccpr/GrCCCoverageProcessor.h"
/** /**
* Steps 1 & 2: Draw the triangle's conservative raster hull with a coverage of +1, then smooth the * Steps 1 & 2: Draw the triangle's conservative raster hull with a coverage of +1, then smooth the
@ -16,7 +16,7 @@
* coverage=-1 on the outside to coverage=0 on the inside. The Impl may choose to * coverage=-1 on the outside to coverage=0 on the inside. The Impl may choose to
* implement these steps in either one or two actual render passes. * implement these steps in either one or two actual render passes.
*/ */
class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader { class GrCCTriangleShader : public GrCCCoverageProcessor::Shader {
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code, WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage, const char* position, const char* coverage,
const char* wind) override; const char* wind) override;
@ -30,7 +30,7 @@ class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader {
* done previously so that it takes into account the region that is outside both edges at * done previously so that it takes into account the region that is outside both edges at
* the same time. * the same time.
*/ */
class GrCCPRTriangleCornerShader : public GrCCPRCoverageProcessor::Shader { class GrCCTriangleCornerShader : public GrCCCoverageProcessor::Shader {
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID, void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
const char* wind, GeometryVars*) const override; const char* wind, GeometryVars*) const override;
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code, WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,

View File

@ -11,14 +11,14 @@
#include "GrClip.h" #include "GrClip.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "GrGpuCommandBuffer.h" #include "GrGpuCommandBuffer.h"
#include "GrOpFlushState.h"
#include "GrRenderTargetOpList.h"
#include "GrStyle.h"
#include "GrTexture.h"
#include "SkMakeUnique.h" #include "SkMakeUnique.h"
#include "SkMatrix.h" #include "SkMatrix.h"
#include "SkPathOps.h" #include "SkPathOps.h"
#include "GrOpFlushState.h" #include "ccpr/GrCCClipProcessor.h"
#include "GrRenderTargetOpList.h"
#include "GrTexture.h"
#include "GrStyle.h"
#include "ccpr/GrCCPRClipProcessor.h"
// Shorthand for keeping line lengths under control with nested classes... // Shorthand for keeping line lengths under control with nested classes...
using CCPR = GrCoverageCountingPathRenderer; using CCPR = GrCoverageCountingPathRenderer;
@ -38,31 +38,27 @@ static void crop_path(const SkPath& path, const SkIRect& cropbox, SkPath* out) {
bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) { bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
const GrShaderCaps& shaderCaps = *caps.shaderCaps(); const GrShaderCaps& shaderCaps = *caps.shaderCaps();
return shaderCaps.integerSupport() && return shaderCaps.integerSupport() && shaderCaps.flatInterpolationSupport() &&
shaderCaps.flatInterpolationSupport() && caps.instanceAttribSupport() && GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
caps.instanceAttribSupport() &&
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) && caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) && caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) &&
!caps.blacklistCoverageCounting(); !caps.blacklistCoverageCounting();
} }
sk_sp<GrCoverageCountingPathRenderer> sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSupported(
GrCoverageCountingPathRenderer::CreateIfSupported(const GrCaps& caps, bool drawCachablePaths) { const GrCaps& caps, bool drawCachablePaths) {
auto ccpr = IsSupported(caps) ? new GrCoverageCountingPathRenderer(drawCachablePaths) : nullptr; auto ccpr = IsSupported(caps) ? new GrCoverageCountingPathRenderer(drawCachablePaths) : nullptr;
return sk_sp<GrCoverageCountingPathRenderer>(ccpr); return sk_sp<GrCoverageCountingPathRenderer>(ccpr);
} }
GrPathRenderer::CanDrawPath GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
GrCoverageCountingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { const CanDrawPathArgs& args) const {
if (args.fShape->hasUnstyledKey() && !fDrawCachablePaths) { if (args.fShape->hasUnstyledKey() && !fDrawCachablePaths) {
return CanDrawPath::kNo; return CanDrawPath::kNo;
} }
if (!args.fShape->style().isSimpleFill() || if (!args.fShape->style().isSimpleFill() || args.fShape->inverseFilled() ||
args.fShape->inverseFilled() || args.fViewMatrix->hasPerspective() || GrAAType::kCoverage != args.fAAType) {
args.fViewMatrix->hasPerspective() ||
GrAAType::kCoverage != args.fAAType) {
return CanDrawPath::kNo; return CanDrawPath::kNo;
} }
@ -113,8 +109,8 @@ CCPR::DrawPathsOp::DrawPathsOp(GrCoverageCountingPathRenderer* ccpr, const DrawP
, fOwningRTPendingPaths(nullptr) { , fOwningRTPendingPaths(nullptr) {
SkDEBUGCODE(++fCCPR->fPendingDrawOpsCount); SkDEBUGCODE(++fCCPR->fPendingDrawOpsCount);
SkDEBUGCODE(fBaseInstance = -1); SkDEBUGCODE(fBaseInstance = -1);
SkDEBUGCODE(fInstanceCount = 1;) SkDEBUGCODE(fInstanceCount = 1);
SkDEBUGCODE(fNumSkippedInstances = 0;) SkDEBUGCODE(fNumSkippedInstances = 0);
GrRenderTargetContext* const rtc = args.fRenderTargetContext; GrRenderTargetContext* const rtc = args.fRenderTargetContext;
SkRect devBounds; SkRect devBounds;
@ -133,7 +129,7 @@ CCPR::DrawPathsOp::DrawPathsOp(GrCoverageCountingPathRenderer* ccpr, const DrawP
fHeadDraw.fMatrix = *args.fViewMatrix; fHeadDraw.fMatrix = *args.fViewMatrix;
args.fShape->asPath(&fHeadDraw.fPath); args.fShape->asPath(&fHeadDraw.fPath);
} }
fHeadDraw.fColor = color; // Can't call args.fPaint.getColor() because it has been std::move'd. fHeadDraw.fColor = color; // Can't call args.fPaint.getColor() because it has been std::move'd.
// FIXME: intersect with clip bounds to (hopefully) improve batching. // FIXME: intersect with clip bounds to (hopefully) improve batching.
// (This is nontrivial due to assumptions in generating the octagon cover geometry.) // (This is nontrivial due to assumptions in generating the octagon cover geometry.)
@ -155,9 +151,9 @@ GrDrawOp::RequiresDstTexture CCPR::DrawPathsOp::finalize(const GrCaps& caps,
// There should only be one single path draw in this Op right now. // There should only be one single path draw in this Op right now.
SkASSERT(1 == fInstanceCount); SkASSERT(1 == fInstanceCount);
SkASSERT(&fHeadDraw == fTailDraw); SkASSERT(&fHeadDraw == fTailDraw);
GrProcessorSet::Analysis analysis = fProcessors.finalize( GrProcessorSet::Analysis analysis =
fHeadDraw.fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip, false, caps, fProcessors.finalize(fHeadDraw.fColor, GrProcessorAnalysisCoverage::kSingleChannel,
dstIsClamped, &fHeadDraw.fColor); clip, false, caps, dstIsClamped, &fHeadDraw.fColor);
return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo; return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
} }
@ -170,8 +166,7 @@ bool CCPR::DrawPathsOp::onCombineIfPossible(GrOp* op, const GrCaps& caps) {
SkASSERT(!that->fOwningRTPendingPaths || that->fOwningRTPendingPaths == fOwningRTPendingPaths); SkASSERT(!that->fOwningRTPendingPaths || that->fOwningRTPendingPaths == fOwningRTPendingPaths);
SkASSERT(that->fInstanceCount); SkASSERT(that->fInstanceCount);
if (this->getFillType() != that->getFillType() || if (this->getFillType() != that->getFillType() || fSRGBFlags != that->fSRGBFlags ||
fSRGBFlags != that->fSRGBFlags ||
fProcessors != that->fProcessors) { fProcessors != that->fProcessors) {
return false; return false;
} }
@ -181,7 +176,7 @@ bool CCPR::DrawPathsOp::onCombineIfPossible(GrOp* op, const GrCaps& caps) {
this->joinBounds(*that); this->joinBounds(*that);
SkDEBUGCODE(fInstanceCount += that->fInstanceCount;) SkDEBUGCODE(fInstanceCount += that->fInstanceCount);
SkDEBUGCODE(that->fInstanceCount = 0); SkDEBUGCODE(that->fInstanceCount = 0);
return true; return true;
} }
@ -205,11 +200,10 @@ bool GrCoverageCountingPathRenderer::canMakeClipProcessor(const SkPath& deviceSp
return true; return true;
} }
std::unique_ptr<GrFragmentProcessor> std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
GrCoverageCountingPathRenderer::makeClipProcessor(uint32_t opListID, const SkPath& deviceSpacePath, uint32_t opListID, const SkPath& deviceSpacePath, const SkIRect& accessRect, int rtWidth,
const SkIRect& accessRect, int rtWidth, int rtHeight) {
int rtHeight) { using MustCheckBounds = GrCCClipProcessor::MustCheckBounds;
using MustCheckBounds = GrCCPRClipProcessor::MustCheckBounds;
SkASSERT(!fFlushing); SkASSERT(!fFlushing);
SkASSERT(this->canMakeClipProcessor(deviceSpacePath)); SkASSERT(this->canMakeClipProcessor(deviceSpacePath));
@ -223,37 +217,39 @@ GrCoverageCountingPathRenderer::makeClipProcessor(uint32_t opListID, const SkPat
} }
bool mustCheckBounds = !clipPath.pathDevIBounds().contains(accessRect); bool mustCheckBounds = !clipPath.pathDevIBounds().contains(accessRect);
return skstd::make_unique<GrCCPRClipProcessor>(&clipPath, MustCheckBounds(mustCheckBounds), return skstd::make_unique<GrCCClipProcessor>(&clipPath, MustCheckBounds(mustCheckBounds),
deviceSpacePath.getFillType()); deviceSpacePath.getFillType());
} }
void CCPR::ClipPath::init(const SkPath& deviceSpacePath, const SkIRect& accessRect, int rtWidth, void CCPR::ClipPath::init(const SkPath& deviceSpacePath, const SkIRect& accessRect, int rtWidth,
int rtHeight) { int rtHeight) {
SkASSERT(this->isUninitialized()); SkASSERT(this->isUninitialized());
fAtlasLazyProxy = GrSurfaceProxy::MakeLazy([this](GrResourceProvider* resourceProvider, fAtlasLazyProxy = GrSurfaceProxy::MakeLazy(
GrSurfaceOrigin* outOrigin) { [this](GrResourceProvider* resourceProvider, GrSurfaceOrigin* outOrigin) {
SkASSERT(fHasAtlas); SkASSERT(fHasAtlas);
SkASSERT(!fHasAtlasTransform); SkASSERT(!fHasAtlasTransform);
GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr; GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr;
if (!textureProxy || !textureProxy->instantiate(resourceProvider)) { if (!textureProxy || !textureProxy->instantiate(resourceProvider)) {
fAtlasScale = fAtlasTranslate = {0, 0}; fAtlasScale = fAtlasTranslate = {0, 0};
SkDEBUGCODE(fHasAtlasTransform = true); SkDEBUGCODE(fHasAtlasTransform = true);
return sk_sp<GrTexture>(); return sk_sp<GrTexture>();
} }
fAtlasScale = {1.f / textureProxy->width(), 1.f / textureProxy->height()}; fAtlasScale = {1.f / textureProxy->width(), 1.f / textureProxy->height()};
fAtlasTranslate = {fAtlasOffsetX * fAtlasScale.x(), fAtlasOffsetY * fAtlasScale.y()}; fAtlasTranslate = {fAtlasOffsetX * fAtlasScale.x(),
if (kBottomLeft_GrSurfaceOrigin == textureProxy->origin()) { fAtlasOffsetY * fAtlasScale.y()};
fAtlasScale.fY = -fAtlasScale.y(); if (kBottomLeft_GrSurfaceOrigin == textureProxy->origin()) {
fAtlasTranslate.fY = 1 - fAtlasTranslate.y(); fAtlasScale.fY = -fAtlasScale.y();
} fAtlasTranslate.fY = 1 - fAtlasTranslate.y();
SkDEBUGCODE(fHasAtlasTransform = true); }
SkDEBUGCODE(fHasAtlasTransform = true);
*outOrigin = textureProxy->origin(); *outOrigin = textureProxy->origin();
return sk_ref_sp(textureProxy->priv().peekTexture()); return sk_ref_sp(textureProxy->priv().peekTexture());
}, GrSurfaceProxy::Renderable::kYes, kAlpha_half_GrPixelConfig); },
GrSurfaceProxy::Renderable::kYes, kAlpha_half_GrPixelConfig);
const SkRect& pathDevBounds = deviceSpacePath.getBounds(); const SkRect& pathDevBounds = deviceSpacePath.getBounds();
if (SkTMax(pathDevBounds.height(), pathDevBounds.width()) > kPathCropThreshold) { if (SkTMax(pathDevBounds.height(), pathDevBounds.width()) > kPathCropThreshold) {
@ -269,24 +265,24 @@ void CCPR::ClipPath::init(const SkPath& deviceSpacePath, const SkIRect& accessRe
void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP, void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP,
const uint32_t* opListIDs, int numOpListIDs, const uint32_t* opListIDs, int numOpListIDs,
SkTArray<sk_sp<GrRenderTargetContext>>* results) { SkTArray<sk_sp<GrRenderTargetContext>>* results) {
using PathInstance = GrCCPRPathProcessor::Instance; using PathInstance = GrCCPathProcessor::Instance;
SkASSERT(!fFlushing); SkASSERT(!fFlushing);
SkASSERT(!fPerFlushIndexBuffer); SkASSERT(!fPerFlushIndexBuffer);
SkASSERT(!fPerFlushVertexBuffer); SkASSERT(!fPerFlushVertexBuffer);
SkASSERT(!fPerFlushInstanceBuffer); SkASSERT(!fPerFlushInstanceBuffer);
SkASSERT(fPerFlushAtlases.empty()); SkASSERT(fPerFlushAtlases.empty());
SkDEBUGCODE(fFlushing = true;) SkDEBUGCODE(fFlushing = true);
if (fRTPendingPathsMap.empty()) { if (fRTPendingPathsMap.empty()) {
return; // Nothing to draw. return; // Nothing to draw.
} }
fPerFlushResourcesAreValid = false; fPerFlushResourcesAreValid = false;
// Count the paths that are being flushed. // Count the paths that are being flushed.
int maxTotalPaths = 0, maxPathPoints = 0, numSkPoints = 0, numSkVerbs = 0; int maxTotalPaths = 0, maxPathPoints = 0, numSkPoints = 0, numSkVerbs = 0;
SkDEBUGCODE(int numClipPaths = 0;) SkDEBUGCODE(int numClipPaths = 0);
for (int i = 0; i < numOpListIDs; ++i) { for (int i = 0; i < numOpListIDs; ++i) {
auto it = fRTPendingPathsMap.find(opListIDs[i]); auto it = fRTPendingPathsMap.find(opListIDs[i]);
if (fRTPendingPathsMap.end() == it) { if (fRTPendingPathsMap.end() == it) {
@ -318,24 +314,24 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
} }
if (!maxTotalPaths) { if (!maxTotalPaths) {
return; // Nothing to draw. return; // Nothing to draw.
} }
// Allocate GPU buffers. // Allocate GPU buffers.
fPerFlushIndexBuffer = GrCCPRPathProcessor::FindIndexBuffer(onFlushRP); fPerFlushIndexBuffer = GrCCPathProcessor::FindIndexBuffer(onFlushRP);
if (!fPerFlushIndexBuffer) { if (!fPerFlushIndexBuffer) {
SkDebugf("WARNING: failed to allocate ccpr path index buffer.\n"); SkDebugf("WARNING: failed to allocate ccpr path index buffer.\n");
return; return;
} }
fPerFlushVertexBuffer = GrCCPRPathProcessor::FindVertexBuffer(onFlushRP); fPerFlushVertexBuffer = GrCCPathProcessor::FindVertexBuffer(onFlushRP);
if (!fPerFlushVertexBuffer) { if (!fPerFlushVertexBuffer) {
SkDebugf("WARNING: failed to allocate ccpr path vertex buffer.\n"); SkDebugf("WARNING: failed to allocate ccpr path vertex buffer.\n");
return; return;
} }
fPerFlushInstanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType, fPerFlushInstanceBuffer =
maxTotalPaths * sizeof(PathInstance)); onFlushRP->makeBuffer(kVertex_GrBufferType, maxTotalPaths * sizeof(PathInstance));
if (!fPerFlushInstanceBuffer) { if (!fPerFlushInstanceBuffer) {
SkDebugf("WARNING: failed to allocate path instance buffer. No paths will be drawn.\n"); SkDebugf("WARNING: failed to allocate path instance buffer. No paths will be drawn.\n");
return; return;
@ -345,8 +341,8 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
SkASSERT(pathInstanceData); SkASSERT(pathInstanceData);
int pathInstanceIdx = 0; int pathInstanceIdx = 0;
GrCCPRCoverageOpsBuilder atlasOpsBuilder(maxTotalPaths, maxPathPoints, numSkPoints, numSkVerbs); GrCCCoverageOpsBuilder atlasOpsBuilder(maxTotalPaths, maxPathPoints, numSkPoints, numSkVerbs);
SkDEBUGCODE(int skippedTotalPaths = 0;) SkDEBUGCODE(int skippedTotalPaths = 0);
// Allocate atlas(es) and fill out GPU instance buffers. // Allocate atlas(es) and fill out GPU instance buffers.
for (int i = 0; i < numOpListIDs; ++i) { for (int i = 0; i < numOpListIDs; ++i) {
@ -363,7 +359,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
pathInstanceIdx = op->setupResources(onFlushRP, &atlasOpsBuilder, pathInstanceData, pathInstanceIdx = op->setupResources(onFlushRP, &atlasOpsBuilder, pathInstanceData,
pathInstanceIdx); pathInstanceIdx);
drawOpsIter.next(); drawOpsIter.next();
SkDEBUGCODE(skippedTotalPaths += op->numSkippedInstances_debugOnly();) SkDEBUGCODE(skippedTotalPaths += op->numSkippedInstances_debugOnly());
} }
for (auto& clipsIter : rtPendingPaths.fClipPaths) { for (auto& clipsIter : rtPendingPaths.fClipPaths) {
@ -379,7 +375,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
atlasOpsBuilder.emitOp(fPerFlushAtlases.back().drawBounds()); atlasOpsBuilder.emitOp(fPerFlushAtlases.back().drawBounds());
} }
SkSTArray<4, std::unique_ptr<GrCCPRCoverageOp>> atlasOps(fPerFlushAtlases.count()); SkSTArray<4, std::unique_ptr<GrCCCoverageOp>> atlasOps(fPerFlushAtlases.count());
if (!atlasOpsBuilder.finalize(onFlushRP, &atlasOps)) { if (!atlasOpsBuilder.finalize(onFlushRP, &atlasOps)) {
SkDebugf("WARNING: failed to allocate ccpr atlas buffers. No paths will be drawn.\n"); SkDebugf("WARNING: failed to allocate ccpr atlas buffers. No paths will be drawn.\n");
return; return;
@ -387,12 +383,12 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
SkASSERT(atlasOps.count() == fPerFlushAtlases.count()); SkASSERT(atlasOps.count() == fPerFlushAtlases.count());
// Draw the coverage ops into their respective atlases. // Draw the coverage ops into their respective atlases.
GrTAllocator<GrCCPRAtlas>::Iter atlasIter(&fPerFlushAtlases); GrTAllocator<GrCCAtlas>::Iter atlasIter(&fPerFlushAtlases);
for (std::unique_ptr<GrCCPRCoverageOp>& atlasOp : atlasOps) { for (std::unique_ptr<GrCCCoverageOp>& atlasOp : atlasOps) {
SkAssertResult(atlasIter.next()); SkAssertResult(atlasIter.next());
GrCCPRAtlas* atlas = atlasIter.get(); GrCCAtlas* atlas = atlasIter.get();
SkASSERT(atlasOp->bounds() == SkRect::MakeIWH(atlas->drawBounds().width(), SkASSERT(atlasOp->bounds() ==
atlas->drawBounds().height())); SkRect::MakeIWH(atlas->drawBounds().width(), atlas->drawBounds().height()));
if (auto rtc = atlas->finalize(onFlushRP, std::move(atlasOp))) { if (auto rtc = atlas->finalize(onFlushRP, std::move(atlasOp))) {
results->push_back(std::move(rtc)); results->push_back(std::move(rtc));
} }
@ -403,10 +399,10 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
} }
int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP, int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
GrCCPRCoverageOpsBuilder* atlasOpsBuilder, GrCCCoverageOpsBuilder* atlasOpsBuilder,
GrCCPRPathProcessor::Instance* pathInstanceData, GrCCPathProcessor::Instance* pathInstanceData,
int pathInstanceIdx) { int pathInstanceIdx) {
const GrCCPRAtlas* currentAtlas = nullptr; const GrCCAtlas* currentAtlas = nullptr;
SkASSERT(fInstanceCount > 0); SkASSERT(fInstanceCount > 0);
SkASSERT(-1 == fBaseInstance); SkASSERT(-1 == fBaseInstance);
fBaseInstance = pathInstanceIdx; fBaseInstance = pathInstanceIdx;
@ -422,9 +418,8 @@ int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
devBounds.roundOut(&devIBounds); devBounds.roundOut(&devIBounds);
int16_t offsetX, offsetY; int16_t offsetX, offsetY;
GrCCPRAtlas* atlas = fCCPR->placeParsedPathInAtlas(onFlushRP, draw->fClipIBounds, GrCCAtlas* atlas = fCCPR->placeParsedPathInAtlas(onFlushRP, draw->fClipIBounds, devIBounds,
devIBounds, &offsetX, &offsetY, &offsetX, &offsetY, atlasOpsBuilder);
atlasOpsBuilder);
if (!atlas) { if (!atlas) {
SkDEBUGCODE(++fNumSkippedInstances); SkDEBUGCODE(++fNumSkippedInstances);
continue; continue;
@ -438,13 +433,12 @@ int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
const SkMatrix& m = draw->fMatrix; const SkMatrix& m = draw->fMatrix;
pathInstanceData[pathInstanceIdx++] = { pathInstanceData[pathInstanceIdx++] = {
devBounds, devBounds,
devBounds45, devBounds45,
{{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()}}, {{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()}},
{{m.getTranslateX(), m.getTranslateY()}}, {{m.getTranslateX(), m.getTranslateY()}},
{{offsetX, offsetY}}, {{offsetX, offsetY}},
draw->fColor draw->fColor};
};
} }
SkASSERT(pathInstanceIdx == fBaseInstance + fInstanceCount - fNumSkippedInstances); SkASSERT(pathInstanceIdx == fBaseInstance + fInstanceCount - fNumSkippedInstances);
@ -457,7 +451,7 @@ int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
void CCPR::ClipPath::placePathInAtlas(GrCoverageCountingPathRenderer* ccpr, void CCPR::ClipPath::placePathInAtlas(GrCoverageCountingPathRenderer* ccpr,
GrOnFlushResourceProvider* onFlushRP, GrOnFlushResourceProvider* onFlushRP,
GrCCPRCoverageOpsBuilder* atlasOpsBuilder) { GrCCCoverageOpsBuilder* atlasOpsBuilder) {
SkASSERT(!this->isUninitialized()); SkASSERT(!this->isUninitialized());
SkASSERT(!fHasAtlas); SkASSERT(!fHasAtlas);
atlasOpsBuilder->parseDeviceSpacePath(fDeviceSpacePath); atlasOpsBuilder->parseDeviceSpacePath(fDeviceSpacePath);
@ -466,14 +460,14 @@ void CCPR::ClipPath::placePathInAtlas(GrCoverageCountingPathRenderer* ccpr,
SkDEBUGCODE(fHasAtlas = true); SkDEBUGCODE(fHasAtlas = true);
} }
GrCCPRAtlas* GrCCAtlas* GrCoverageCountingPathRenderer::placeParsedPathInAtlas(
GrCoverageCountingPathRenderer::placeParsedPathInAtlas(GrOnFlushResourceProvider* onFlushRP, GrOnFlushResourceProvider* onFlushRP,
const SkIRect& clipIBounds, const SkIRect& clipIBounds,
const SkIRect& pathIBounds, const SkIRect& pathIBounds,
int16_t* atlasOffsetX, int16_t* atlasOffsetX,
int16_t* atlasOffsetY, int16_t* atlasOffsetY,
GrCCPRCoverageOpsBuilder* atlasOpsBuilder) { GrCCCoverageOpsBuilder* atlasOpsBuilder) {
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode; using ScissorMode = GrCCCoverageOpsBuilder::ScissorMode;
ScissorMode scissorMode; ScissorMode scissorMode;
SkIRect clippedPathIBounds; SkIRect clippedPathIBounds;
@ -509,10 +503,10 @@ void CCPR::DrawPathsOp::onExecute(GrOpFlushState* flushState) {
SkASSERT(flushState->rtCommandBuffer()); SkASSERT(flushState->rtCommandBuffer());
if (!fCCPR->fPerFlushResourcesAreValid) { if (!fCCPR->fPerFlushResourcesAreValid) {
return; // Setup failed. return; // Setup failed.
} }
SkASSERT(fBaseInstance >= 0); // Make sure setupResources has been called. SkASSERT(fBaseInstance >= 0); // Make sure setupResources has been called.
GrPipeline::InitArgs initArgs; GrPipeline::InitArgs initArgs;
initArgs.fFlags = fSRGBFlags; initArgs.fFlags = fSRGBFlags;
@ -529,16 +523,16 @@ void CCPR::DrawPathsOp::onExecute(GrOpFlushState* flushState) {
SkASSERT(batch.fEndInstanceIdx > baseInstance); SkASSERT(batch.fEndInstanceIdx > baseInstance);
if (!batch.fAtlas->textureProxy()) { if (!batch.fAtlas->textureProxy()) {
continue; // Atlas failed to allocate. continue; // Atlas failed to allocate.
} }
GrCCPRPathProcessor coverProc(flushState->resourceProvider(), GrCCPathProcessor coverProc(flushState->resourceProvider(),
sk_ref_sp(batch.fAtlas->textureProxy()), this->getFillType(), sk_ref_sp(batch.fAtlas->textureProxy()), this->getFillType(),
*flushState->gpu()->caps()->shaderCaps()); *flushState->gpu()->caps()->shaderCaps());
GrMesh mesh(GrPrimitiveType::kTriangles); GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexedInstanced(fCCPR->fPerFlushIndexBuffer.get(), mesh.setIndexedInstanced(fCCPR->fPerFlushIndexBuffer.get(),
GrCCPRPathProcessor::kPerInstanceIndexCount, GrCCPathProcessor::kPerInstanceIndexCount,
fCCPR->fPerFlushInstanceBuffer.get(), fCCPR->fPerFlushInstanceBuffer.get(),
batch.fEndInstanceIdx - baseInstance, baseInstance); batch.fEndInstanceIdx - baseInstance, baseInstance);
mesh.setVertexData(fCCPR->fPerFlushVertexBuffer.get()); mesh.setVertexData(fCCPR->fPerFlushVertexBuffer.get());
@ -560,5 +554,5 @@ void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken, const uint
for (int i = 0; i < numOpListIDs; ++i) { for (int i = 0; i < numOpListIDs; ++i) {
fRTPendingPathsMap.erase(opListIDs[i]); fRTPendingPathsMap.erase(opListIDs[i]);
} }
SkDEBUGCODE(fFlushing = false;) SkDEBUGCODE(fFlushing = false);
} }

View File

@ -8,27 +8,24 @@
#ifndef GrCoverageCountingPathRenderer_DEFINED #ifndef GrCoverageCountingPathRenderer_DEFINED
#define GrCoverageCountingPathRenderer_DEFINED #define GrCoverageCountingPathRenderer_DEFINED
#include <map>
#include "GrAllocator.h" #include "GrAllocator.h"
#include "GrOnFlushResourceProvider.h" #include "GrOnFlushResourceProvider.h"
#include "GrPathRenderer.h" #include "GrPathRenderer.h"
#include "SkTInternalLList.h" #include "SkTInternalLList.h"
#include "ccpr/GrCCPRAtlas.h" #include "ccpr/GrCCAtlas.h"
#include "ccpr/GrCCPRCoverageOp.h" #include "ccpr/GrCCCoverageOp.h"
#include "ccpr/GrCCPRPathProcessor.h" #include "ccpr/GrCCPathProcessor.h"
#include "ops/GrDrawOp.h" #include "ops/GrDrawOp.h"
#include <map>
/** /**
* This is a path renderer that draws antialiased paths by counting coverage in an offscreen * This is a path renderer that draws antialiased paths by counting coverage in an offscreen
* buffer. (See GrCCPRCoverageProcessor, GrCCPRPathProcessor) * buffer. (See GrCCCoverageProcessor, GrCCPathProcessor)
* *
* It also serves as the per-render-target tracker for pending path draws, and at the start of * It also serves as the per-render-target tracker for pending path draws, and at the start of
* flush, it compiles GPU buffers and renders a "coverage count atlas" for the upcoming paths. * flush, it compiles GPU buffers and renders a "coverage count atlas" for the upcoming paths.
*/ */
class GrCoverageCountingPathRenderer class GrCoverageCountingPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject {
: public GrPathRenderer
, public GrOnFlushCallbackObject {
struct RTPendingPaths; struct RTPendingPaths;
public: public:
@ -52,7 +49,7 @@ public:
DrawPathsOp(GrCoverageCountingPathRenderer*, const DrawPathArgs&, GrColor); DrawPathsOp(GrCoverageCountingPathRenderer*, const DrawPathArgs&, GrColor);
~DrawPathsOp() override; ~DrawPathsOp() override;
struct SingleDraw { struct SingleDraw {
SkIRect fClipIBounds; SkIRect fClipIBounds;
SkMatrix fMatrix; SkMatrix fMatrix;
SkPath fPath; SkPath fPath;
@ -80,8 +77,8 @@ public:
void onPrepare(GrOpFlushState*) override {} void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState*) override; void onExecute(GrOpFlushState*) override;
int setupResources(GrOnFlushResourceProvider*, GrCCPRCoverageOpsBuilder*, int setupResources(GrOnFlushResourceProvider*, GrCCCoverageOpsBuilder*,
GrCCPRPathProcessor::Instance* pathInstanceData, int pathInstanceIdx); GrCCPathProcessor::Instance* pathInstanceData, int pathInstanceIdx);
private: private:
SkPath::FillType getFillType() const { SkPath::FillType getFillType() const {
@ -90,11 +87,11 @@ public:
} }
struct AtlasBatch { struct AtlasBatch {
const GrCCPRAtlas* fAtlas; const GrCCAtlas* fAtlas;
int fEndInstanceIdx; int fEndInstanceIdx;
}; };
void addAtlasBatch(const GrCCPRAtlas* atlas, int endInstanceIdx) { void addAtlasBatch(const GrCCAtlas* atlas, int endInstanceIdx) {
SkASSERT(endInstanceIdx > fBaseInstance); SkASSERT(endInstanceIdx > fBaseInstance);
SkASSERT(fAtlasBatches.empty() || SkASSERT(fAtlasBatches.empty() ||
endInstanceIdx > fAtlasBatches.back().fEndInstanceIdx); endInstanceIdx > fAtlasBatches.back().fEndInstanceIdx);
@ -108,8 +105,8 @@ public:
SingleDraw* fTailDraw; SingleDraw* fTailDraw;
RTPendingPaths* fOwningRTPendingPaths; RTPendingPaths* fOwningRTPendingPaths;
int fBaseInstance; int fBaseInstance;
SkDEBUGCODE(int fInstanceCount;) SkDEBUGCODE(int fInstanceCount);
SkDEBUGCODE(int fNumSkippedInstances;) SkDEBUGCODE(int fNumSkippedInstances);
SkSTArray<1, AtlasBatch, true> fAtlasBatches; SkSTArray<1, AtlasBatch, true> fAtlasBatches;
typedef GrDrawOp INHERITED; typedef GrDrawOp INHERITED;
@ -158,9 +155,12 @@ public:
return fPathDevIBounds; return fPathDevIBounds;
} }
void placePathInAtlas(GrCoverageCountingPathRenderer*, GrOnFlushResourceProvider*, void placePathInAtlas(GrCoverageCountingPathRenderer*, GrOnFlushResourceProvider*,
GrCCPRCoverageOpsBuilder*); GrCCCoverageOpsBuilder*);
const SkVector& atlasScale() const { SkASSERT(fHasAtlasTransform); return fAtlasScale; } const SkVector& atlasScale() const {
SkASSERT(fHasAtlasTransform);
return fAtlasScale;
}
const SkVector& atlasTranslate() const { const SkVector& atlasTranslate() const {
SkASSERT(fHasAtlasTransform); SkASSERT(fHasAtlasTransform);
return fAtlasTranslate; return fAtlasTranslate;
@ -172,7 +172,7 @@ public:
SkIRect fPathDevIBounds; SkIRect fPathDevIBounds;
SkIRect fAccessRect; SkIRect fAccessRect;
const GrCCPRAtlas* fAtlas = nullptr; const GrCCAtlas* fAtlas = nullptr;
int16_t fAtlasOffsetX; int16_t fAtlasOffsetX;
int16_t fAtlasOffsetY; int16_t fAtlasOffsetY;
SkDEBUGCODE(bool fHasAtlas = false); SkDEBUGCODE(bool fHasAtlas = false);
@ -186,8 +186,8 @@ public:
std::unique_ptr<GrFragmentProcessor> makeClipProcessor(uint32_t oplistID, std::unique_ptr<GrFragmentProcessor> makeClipProcessor(uint32_t oplistID,
const SkPath& deviceSpacePath, const SkPath& deviceSpacePath,
const SkIRect& accessRect, const SkIRect& accessRect, int rtWidth,
int rtWidth, int rtHeight); int rtHeight);
// GrOnFlushCallbackObject overrides. // GrOnFlushCallbackObject overrides.
void preFlush(GrOnFlushResourceProvider*, const uint32_t* opListIDs, int numOpListIDs, void preFlush(GrOnFlushResourceProvider*, const uint32_t* opListIDs, int numOpListIDs,
@ -198,9 +198,9 @@ private:
GrCoverageCountingPathRenderer(bool drawCachablePaths) GrCoverageCountingPathRenderer(bool drawCachablePaths)
: fDrawCachablePaths(drawCachablePaths) {} : fDrawCachablePaths(drawCachablePaths) {}
GrCCPRAtlas* placeParsedPathInAtlas(GrOnFlushResourceProvider*, const SkIRect& accessRect, GrCCAtlas* placeParsedPathInAtlas(GrOnFlushResourceProvider*, const SkIRect& accessRect,
const SkIRect& pathIBounds, int16_t* atlasOffsetX, const SkIRect& pathIBounds, int16_t* atlasOffsetX,
int16_t* atlasOffsetY, GrCCPRCoverageOpsBuilder*); int16_t* atlasOffsetY, GrCCCoverageOpsBuilder*);
struct RTPendingPaths { struct RTPendingPaths {
~RTPendingPaths() { ~RTPendingPaths() {
@ -215,14 +215,14 @@ private:
// A map from render target ID to the individual render target's pending paths. // A map from render target ID to the individual render target's pending paths.
std::map<uint32_t, RTPendingPaths> fRTPendingPathsMap; std::map<uint32_t, RTPendingPaths> fRTPendingPathsMap;
SkDEBUGCODE(int fPendingDrawOpsCount = 0;) SkDEBUGCODE(int fPendingDrawOpsCount = 0);
sk_sp<const GrBuffer> fPerFlushIndexBuffer; sk_sp<const GrBuffer> fPerFlushIndexBuffer;
sk_sp<const GrBuffer> fPerFlushVertexBuffer; sk_sp<const GrBuffer> fPerFlushVertexBuffer;
sk_sp<GrBuffer> fPerFlushInstanceBuffer; sk_sp<GrBuffer> fPerFlushInstanceBuffer;
GrSTAllocator<4, GrCCPRAtlas> fPerFlushAtlases; GrSTAllocator<4, GrCCAtlas> fPerFlushAtlases;
bool fPerFlushResourcesAreValid; bool fPerFlushResourcesAreValid;
SkDEBUGCODE(bool fFlushing = false;) SkDEBUGCODE(bool fFlushing = false);
const bool fDrawCachablePaths; const bool fDrawCachablePaths;
}; };