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:
parent
c35959f3cb
commit
383a2ef6ed
40
gn/gpu.gni
40
gn/gpu.gni
@ -296,26 +296,26 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/ops/GrTextureOp.h",
|
||||
|
||||
# coverage counting path renderer
|
||||
"$_src/gpu/ccpr/GrCCPRAtlas.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRAtlas.h",
|
||||
"$_src/gpu/ccpr/GrCCPRClipProcessor.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRClipProcessor.h",
|
||||
"$_src/gpu/ccpr/GrCCPRCoverageOp.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRCoverageOp.h",
|
||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.h",
|
||||
"$_src/gpu/ccpr/GrCCPRCubicShader.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRCubicShader.h",
|
||||
"$_src/gpu/ccpr/GrCCPRGeometry.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRGeometry.h",
|
||||
"$_src/gpu/ccpr/GrCCPRPathProcessor.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRPathProcessor.h",
|
||||
"$_src/gpu/ccpr/GrCCPRQuadraticShader.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRQuadraticShader.h",
|
||||
"$_src/gpu/ccpr/GrCCPRTriangleShader.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPRTriangleShader.h",
|
||||
"$_src/gpu/ccpr/GrCCAtlas.cpp",
|
||||
"$_src/gpu/ccpr/GrCCAtlas.h",
|
||||
"$_src/gpu/ccpr/GrCCClipProcessor.cpp",
|
||||
"$_src/gpu/ccpr/GrCCClipProcessor.h",
|
||||
"$_src/gpu/ccpr/GrCCCoverageOp.cpp",
|
||||
"$_src/gpu/ccpr/GrCCCoverageOp.h",
|
||||
"$_src/gpu/ccpr/GrCCCoverageProcessor.cpp",
|
||||
"$_src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp",
|
||||
"$_src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp",
|
||||
"$_src/gpu/ccpr/GrCCCoverageProcessor.h",
|
||||
"$_src/gpu/ccpr/GrCCCubicShader.cpp",
|
||||
"$_src/gpu/ccpr/GrCCCubicShader.h",
|
||||
"$_src/gpu/ccpr/GrCCGeometry.cpp",
|
||||
"$_src/gpu/ccpr/GrCCGeometry.h",
|
||||
"$_src/gpu/ccpr/GrCCPathProcessor.cpp",
|
||||
"$_src/gpu/ccpr/GrCCPathProcessor.h",
|
||||
"$_src/gpu/ccpr/GrCCQuadraticShader.cpp",
|
||||
"$_src/gpu/ccpr/GrCCQuadraticShader.h",
|
||||
"$_src/gpu/ccpr/GrCCTriangleShader.cpp",
|
||||
"$_src/gpu/ccpr/GrCCTriangleShader.h",
|
||||
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp",
|
||||
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h",
|
||||
|
||||
|
@ -21,18 +21,18 @@
|
||||
#include "SkPath.h"
|
||||
#include "SkRectPriv.h"
|
||||
#include "SkView.h"
|
||||
#include "ccpr/GrCCPRCoverageProcessor.h"
|
||||
#include "ccpr/GrCCPRGeometry.h"
|
||||
#include "ccpr/GrCCCoverageProcessor.h"
|
||||
#include "ccpr/GrCCGeometry.h"
|
||||
#include "gl/GrGLGpu.cpp"
|
||||
#include "ops/GrDrawOp.h"
|
||||
|
||||
using TriangleInstance = GrCCPRCoverageProcessor::TriangleInstance;
|
||||
using CubicInstance = GrCCPRCoverageProcessor::CubicInstance;
|
||||
using RenderPass = GrCCPRCoverageProcessor::RenderPass;
|
||||
using TriangleInstance = GrCCCoverageProcessor::TriangleInstance;
|
||||
using CubicInstance = GrCCCoverageProcessor::CubicInstance;
|
||||
using RenderPass = GrCCCoverageProcessor::RenderPass;
|
||||
|
||||
static constexpr float kDebugBloat = 40;
|
||||
|
||||
static int is_quadratic(RenderPass pass) {
|
||||
static int is_quadratic(RenderPass pass) {
|
||||
return pass == RenderPass::kQuadraticHulls || pass == RenderPass::kQuadraticCorners;
|
||||
}
|
||||
|
||||
@ -55,9 +55,7 @@ private:
|
||||
class Click;
|
||||
class Op;
|
||||
|
||||
void updateAndInval() {
|
||||
this->updateGpuData();
|
||||
}
|
||||
void updateAndInval() { this->updateGpuData(); }
|
||||
|
||||
void updateGpuData();
|
||||
|
||||
@ -66,11 +64,7 @@ private:
|
||||
SkMatrix fCubicKLM;
|
||||
|
||||
SkPoint fPoints[4] = {
|
||||
{100.05f, 100.05f},
|
||||
{400.75f, 100.05f},
|
||||
{400.75f, 300.95f},
|
||||
{100.05f, 300.95f}
|
||||
};
|
||||
{100.05f, 100.05f}, {400.75f, 100.05f}, {400.75f, 300.95f}, {100.05f, 300.95f}};
|
||||
|
||||
SkTArray<TriangleInstance> fTriangleInstances;
|
||||
SkTArray<CubicInstance> fCubicInstances;
|
||||
@ -82,9 +76,7 @@ class CCPRGeometryView::Op : public GrDrawOp {
|
||||
DEFINE_OP_CLASS_ID
|
||||
|
||||
public:
|
||||
Op(CCPRGeometryView* view)
|
||||
: INHERITED(ClassID())
|
||||
, fView(view) {
|
||||
Op(CCPRGeometryView* view) : INHERITED(ClassID()), fView(view) {
|
||||
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])) {
|
||||
// Draw from vertical edge to vertical edge.
|
||||
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 {
|
||||
// Draw from horizontal edge to horizontal edge.
|
||||
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;
|
||||
@ -132,7 +124,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
|
||||
|
||||
SkPath outline;
|
||||
outline.moveTo(fPoints[0]);
|
||||
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
outline.cubicTo(fPoints[1], fPoints[2], fPoints[3]);
|
||||
} else if (is_quadratic(fRenderPass)) {
|
||||
outline.quadTo(fPoints[1], fPoints[3]);
|
||||
@ -164,11 +156,10 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
|
||||
#endif
|
||||
|
||||
SkString caption;
|
||||
if (GrRenderTargetContext* rtc =
|
||||
canvas->internal_private_accessTopLayerRenderTargetContext()) {
|
||||
if (GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext()) {
|
||||
rtc->priv().testingOnly_addDrawOp(skstd::make_unique<Op>(this));
|
||||
caption.appendf("RenderPass_%s", GrCCPRCoverageProcessor::RenderPassName(fRenderPass));
|
||||
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
caption.appendf("RenderPass_%s", GrCCCoverageProcessor::RenderPassName(fRenderPass));
|
||||
if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
caption.appendf(" (%s)", SkCubicTypeName(fCubicType));
|
||||
}
|
||||
} else {
|
||||
@ -180,7 +171,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
|
||||
pointsPaint.setStrokeWidth(8);
|
||||
pointsPaint.setAntiAlias(true);
|
||||
|
||||
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
int w = this->width(), h = this->height();
|
||||
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
|
||||
draw_klm_line(w, h, canvas, &fCubicKLM[0], SK_ColorYELLOW);
|
||||
@ -202,46 +193,47 @@ void CCPRGeometryView::updateGpuData() {
|
||||
fTriangleInstances.reset();
|
||||
fCubicInstances.reset();
|
||||
|
||||
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) {
|
||||
double t[2], s[2];
|
||||
fCubicType = GrPathUtils::getCubicKLM(fPoints, &fCubicKLM, t, s);
|
||||
GrCCPRGeometry geometry;
|
||||
GrCCGeometry geometry;
|
||||
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();
|
||||
int ptsIdx = 0;
|
||||
for (GrCCPRGeometry::Verb verb : geometry.verbs()) {
|
||||
for (GrCCGeometry::Verb verb : geometry.verbs()) {
|
||||
switch (verb) {
|
||||
case GrCCPRGeometry::Verb::kLineTo:
|
||||
case GrCCGeometry::Verb::kLineTo:
|
||||
++ptsIdx;
|
||||
continue;
|
||||
case GrCCPRGeometry::Verb::kMonotonicQuadraticTo:
|
||||
case GrCCGeometry::Verb::kMonotonicQuadraticTo:
|
||||
ptsIdx += 2;
|
||||
continue;
|
||||
case GrCCPRGeometry::Verb::kMonotonicCubicTo:
|
||||
case GrCCGeometry::Verb::kMonotonicCubicTo:
|
||||
fCubicInstances.push_back().set(&geometry.points()[ptsIdx], 0, 0);
|
||||
ptsIdx += 3;
|
||||
continue;
|
||||
default: continue;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (is_quadratic(fRenderPass)) {
|
||||
GrCCPRGeometry geometry;
|
||||
GrCCGeometry geometry;
|
||||
geometry.beginContour(fPoints[0]);
|
||||
geometry.quadraticTo(fPoints[1], fPoints[3]);
|
||||
geometry.endContour();
|
||||
int ptsIdx = 0;
|
||||
for (GrCCPRGeometry::Verb verb : geometry.verbs()) {
|
||||
if (GrCCPRGeometry::Verb::kBeginContour == verb ||
|
||||
GrCCPRGeometry::Verb::kEndOpenContour == verb ||
|
||||
GrCCPRGeometry::Verb::kEndClosedContour == verb) {
|
||||
for (GrCCGeometry::Verb verb : geometry.verbs()) {
|
||||
if (GrCCGeometry::Verb::kBeginContour == verb ||
|
||||
GrCCGeometry::Verb::kEndOpenContour == verb ||
|
||||
GrCCGeometry::Verb::kEndClosedContour == verb) {
|
||||
continue;
|
||||
}
|
||||
if (GrCCPRGeometry::Verb::kLineTo == verb) {
|
||||
if (GrCCGeometry::Verb::kLineTo == verb) {
|
||||
++ptsIdx;
|
||||
continue;
|
||||
}
|
||||
SkASSERT(GrCCPRGeometry::Verb::kMonotonicQuadraticTo == verb);
|
||||
SkASSERT(GrCCGeometry::Verb::kMonotonicQuadraticTo == verb);
|
||||
fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0));
|
||||
ptsIdx += 2;
|
||||
}
|
||||
@ -253,34 +245,34 @@ void CCPRGeometryView::updateGpuData() {
|
||||
void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) {
|
||||
GrResourceProvider* rp = state->resourceProvider();
|
||||
GrContext* context = state->gpu()->getContext();
|
||||
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend() ?
|
||||
static_cast<GrGLGpu*>(state->gpu()) : nullptr;
|
||||
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend()
|
||||
? static_cast<GrGLGpu*>(state->gpu())
|
||||
: nullptr;
|
||||
|
||||
if (!GrCCPRCoverageProcessor::DoesRenderPass(fView->fRenderPass, *state->caps().shaderCaps())) {
|
||||
if (!GrCCCoverageProcessor::DoesRenderPass(fView->fRenderPass, *state->caps().shaderCaps())) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrCCPRCoverageProcessor proc(rp, fView->fRenderPass, *state->caps().shaderCaps());
|
||||
GrCCCoverageProcessor proc(rp, fView->fRenderPass, *state->caps().shaderCaps());
|
||||
SkDEBUGCODE(proc.enableDebugVisualizations(kDebugBloat);)
|
||||
|
||||
SkSTArray<1, GrMesh> mesh;
|
||||
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) {
|
||||
sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fCubicInstances.count() *
|
||||
sizeof(CubicInstance), kVertex_GrBufferType,
|
||||
kDynamic_GrAccessPattern,
|
||||
GrResourceProvider::kNoPendingIO_Flag |
|
||||
GrResourceProvider::kRequireGpuMemory_Flag,
|
||||
fView->fCubicInstances.begin()));
|
||||
SkSTArray<1, GrMesh>
|
||||
mesh;
|
||||
if (GrCCCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) {
|
||||
sk_sp<GrBuffer> instBuff(rp->createBuffer(
|
||||
fView->fCubicInstances.count() * sizeof(CubicInstance), kVertex_GrBufferType,
|
||||
kDynamic_GrAccessPattern,
|
||||
GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag,
|
||||
fView->fCubicInstances.begin()));
|
||||
if (!fView->fCubicInstances.empty() && instBuff) {
|
||||
proc.appendMesh(instBuff.get(), fView->fCubicInstances.count(), 0, &mesh);
|
||||
}
|
||||
} else {
|
||||
sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fTriangleInstances.count() *
|
||||
sizeof(TriangleInstance), kVertex_GrBufferType,
|
||||
kDynamic_GrAccessPattern,
|
||||
GrResourceProvider::kNoPendingIO_Flag |
|
||||
GrResourceProvider::kRequireGpuMemory_Flag,
|
||||
fView->fTriangleInstances.begin()));
|
||||
sk_sp<GrBuffer> instBuff(rp->createBuffer(
|
||||
fView->fTriangleInstances.count() * sizeof(TriangleInstance), kVertex_GrBufferType,
|
||||
kDynamic_GrAccessPattern,
|
||||
GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag,
|
||||
fView->fTriangleInstances.begin()));
|
||||
if (!fView->fTriangleInstances.empty() && instBuff) {
|
||||
proc.appendMesh(instBuff.get(), fView->fTriangleInstances.count(), 0, &mesh);
|
||||
}
|
||||
@ -320,7 +312,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void dragPoint(SkPoint points[], int idx) {
|
||||
void dragPoint(SkPoint points[], int idx) {
|
||||
SkIPoint delta = fICurr - fIPrev;
|
||||
points[idx] += SkPoint::Make(delta.x(), delta.y());
|
||||
}
|
||||
@ -330,7 +322,7 @@ private:
|
||||
|
||||
SkView::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, unsigned) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (!GrCCPRCoverageProcessor::RenderPassIsCubic(fRenderPass) && 2 == i) {
|
||||
if (!GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass) && 2 == i) {
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
Click* myClick = (Click*) click;
|
||||
Click* myClick = (Click*)click;
|
||||
myClick->doClick(fPoints);
|
||||
this->updateAndInval();
|
||||
return true;
|
||||
@ -372,6 +364,6 @@ bool CCPRGeometryView::onQuery(SkEvent* evt) {
|
||||
return this->INHERITED::onQuery(evt);
|
||||
}
|
||||
|
||||
DEF_SAMPLE( return new CCPRGeometryView; )
|
||||
DEF_SAMPLE(return new CCPRGeometryView;)
|
||||
|
||||
#endif // SK_SUPPORT_GPU
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
@ -67,7 +67,6 @@ public:
|
||||
enum ClassID {
|
||||
kBigKeyProcessor_ClassID,
|
||||
kBlockInputFragmentProcessor_ClassID,
|
||||
kCCPRClipProcessor_ClassID,
|
||||
kCircleGeometryProcessor_ClassID,
|
||||
kCircularRRectEffect_ClassID,
|
||||
kColorMatrixEffect_ClassID,
|
||||
@ -91,8 +90,9 @@ public:
|
||||
kGrBicubicEffect_ClassID,
|
||||
kGrBitmapTextGeoProc_ClassID,
|
||||
kGrBlurredEdgeFragmentProcessor_ClassID,
|
||||
kGrCCPRCoverageProcessor_ClassID,
|
||||
kGrCCPRPathProcessor_ClassID,
|
||||
kGrCCClipProcessor_ClassID,
|
||||
kGrCCCoverageProcessor_ClassID,
|
||||
kGrCCPathProcessor_ClassID,
|
||||
kGrCircleBlurFragmentProcessor_ClassID,
|
||||
kGrCircleEffect_ClassID,
|
||||
kGrColorSpaceXformEffect_ClassID,
|
||||
|
@ -409,7 +409,7 @@ private:
|
||||
friend class GrMSAAPathRenderer; // 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 GrCCPRAtlas; // for access to addDrawOp
|
||||
friend class GrCCAtlas; // for access to addDrawOp
|
||||
friend class GrCoverageCountingPathRenderer; // for access to addDrawOp
|
||||
// for a unit test
|
||||
friend void test_draw_op(GrRenderTargetContext*, std::unique_ptr<GrFragmentProcessor>,
|
||||
|
@ -5,24 +5,22 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRAtlas.h"
|
||||
#include "GrCCAtlas.h"
|
||||
|
||||
#include "GrOnFlushResourceProvider.h"
|
||||
#include "GrClip.h"
|
||||
#include "GrOnFlushResourceProvider.h"
|
||||
#include "GrRectanizer_skyline.h"
|
||||
#include "GrTextureProxy.h"
|
||||
#include "GrRenderTargetContext.h"
|
||||
#include "GrTextureProxy.h"
|
||||
#include "SkMakeUnique.h"
|
||||
#include "SkMathPriv.h"
|
||||
#include "ccpr/GrCCPRCoverageProcessor.h"
|
||||
#include "ccpr/GrCCCoverageProcessor.h"
|
||||
#include "ops/GrDrawOp.h"
|
||||
|
||||
class GrCCPRAtlas::Node {
|
||||
class GrCCAtlas::Node {
|
||||
public:
|
||||
Node(std::unique_ptr<Node> previous, int l, int t, int r, int b)
|
||||
: fPrevious(std::move(previous))
|
||||
, fX(l), fY(t)
|
||||
, fRectanizer(r - l, b - t) {}
|
||||
: fPrevious(std::move(previous)), fX(l), fY(t), fRectanizer(r - l, b - t) {}
|
||||
|
||||
Node* previous() const { return fPrevious.get(); }
|
||||
|
||||
@ -38,14 +36,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Node> fPrevious;
|
||||
const int fX, fY;
|
||||
GrRectanizerSkyline fRectanizer;
|
||||
const std::unique_ptr<Node> fPrevious;
|
||||
const int fX, fY;
|
||||
GrRectanizerSkyline fRectanizer;
|
||||
};
|
||||
|
||||
GrCCPRAtlas::GrCCPRAtlas(const GrCaps& caps, int minWidth, int minHeight)
|
||||
: fMaxAtlasSize(caps.maxRenderTargetSize())
|
||||
, fDrawBounds{0, 0} {
|
||||
GrCCAtlas::GrCCAtlas(const GrCaps& caps, int minWidth, int minHeight)
|
||||
: fMaxAtlasSize(caps.maxRenderTargetSize()), fDrawBounds{0, 0} {
|
||||
SkASSERT(fMaxAtlasSize <= caps.maxTextureSize());
|
||||
SkASSERT(SkTMax(minWidth, minHeight) <= fMaxAtlasSize);
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
SkASSERT(!fTextureProxy);
|
||||
|
||||
@ -71,7 +67,7 @@ bool GrCCPRAtlas::addRect(int w, int h, SkIPoint16* loc) {
|
||||
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);
|
||||
|
||||
for (Node* node = fTopNode.get(); node; node = node->previous()) {
|
||||
@ -100,8 +96,8 @@ bool GrCCPRAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
sk_sp<GrRenderTargetContext> GrCCPRAtlas::finalize(GrOnFlushResourceProvider* onFlushRP,
|
||||
std::unique_ptr<GrDrawOp> atlasOp) {
|
||||
sk_sp<GrRenderTargetContext> GrCCAtlas::finalize(
|
||||
GrOnFlushResourceProvider* onFlushRP, std::unique_ptr<GrDrawOp> atlasOp) {
|
||||
SkASSERT(!fTextureProxy);
|
||||
|
||||
GrSurfaceDesc desc;
|
@ -5,8 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRAtlas_DEFINED
|
||||
#define GrCCPRAtlas_DEFINED
|
||||
#ifndef GrCCAtlas_DEFINED
|
||||
#define GrCCAtlas_DEFINED
|
||||
|
||||
#include "SkRefCnt.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
|
||||
* underlying atlas.
|
||||
*/
|
||||
class GrCCPRAtlas {
|
||||
class GrCCAtlas {
|
||||
public:
|
||||
static constexpr int kMinSize = 1024;
|
||||
|
||||
GrCCPRAtlas(const GrCaps&, int minWidth, int minHeight);
|
||||
~GrCCPRAtlas();
|
||||
GrCCAtlas(const GrCaps&, int minWidth, int minHeight);
|
||||
~GrCCAtlas();
|
||||
|
||||
bool addRect(int devWidth, int devHeight, SkIPoint16* loc);
|
||||
const SkISize& drawBounds() { return fDrawBounds; }
|
||||
|
||||
sk_sp<GrRenderTargetContext> SK_WARN_UNUSED_RESULT finalize(GrOnFlushResourceProvider*,
|
||||
std::unique_ptr<GrDrawOp> atlasOp);
|
||||
sk_sp<GrRenderTargetContext> SK_WARN_UNUSED_RESULT
|
||||
finalize(GrOnFlushResourceProvider*, std::unique_ptr<GrDrawOp> atlasOp);
|
||||
|
||||
GrTextureProxy* textureProxy() const { return fTextureProxy.get(); }
|
||||
|
||||
@ -43,14 +43,14 @@ private:
|
||||
|
||||
bool internalPlaceRect(int w, int h, SkIPoint16* loc);
|
||||
|
||||
const int fMaxAtlasSize;
|
||||
const int fMaxAtlasSize;
|
||||
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
SkISize fDrawBounds;
|
||||
std::unique_ptr<Node> fTopNode;
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
SkISize fDrawBounds;
|
||||
std::unique_ptr<Node> fTopNode;
|
||||
|
||||
sk_sp<GrTextureProxy> fTextureProxy;
|
||||
sk_sp<GrTextureProxy> fTextureProxy;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRClipProcessor.h"
|
||||
#include "GrCCClipProcessor.h"
|
||||
|
||||
#include "GrTexture.h"
|
||||
#include "GrTextureProxy.h"
|
||||
@ -13,9 +13,9 @@
|
||||
#include "glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
|
||||
GrCCPRClipProcessor::GrCCPRClipProcessor(const ClipPath* clipPath, MustCheckBounds mustCheckBounds,
|
||||
GrCCClipProcessor::GrCCClipProcessor(const ClipPath* clipPath, MustCheckBounds mustCheckBounds,
|
||||
SkPath::FillType overrideFillType)
|
||||
: INHERITED(kCCPRClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
: INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
, fClipPath(clipPath)
|
||||
, fMustCheckBounds((bool)mustCheckBounds)
|
||||
, fOverrideFillType(overrideFillType)
|
||||
@ -24,18 +24,17 @@ GrCCPRClipProcessor::GrCCPRClipProcessor(const ClipPath* clipPath, MustCheckBoun
|
||||
this->addTextureSampler(&fAtlasAccess);
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrCCPRClipProcessor::clone() const {
|
||||
return skstd::make_unique<GrCCPRClipProcessor>(fClipPath, MustCheckBounds(fMustCheckBounds),
|
||||
std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
|
||||
return skstd::make_unique<GrCCClipProcessor>(fClipPath, MustCheckBounds(fMustCheckBounds),
|
||||
fOverrideFillType);
|
||||
}
|
||||
|
||||
void GrCCPRClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
|
||||
b->add32((fOverrideFillType << 1) | (int)fMustCheckBounds);
|
||||
}
|
||||
|
||||
bool GrCCPRClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
|
||||
const GrCCPRClipProcessor& that = fp.cast<GrCCPRClipProcessor>();
|
||||
bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
|
||||
const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>();
|
||||
// Each ClipPath path has a unique atlas proxy, so hasSameSamplersAndAccesses should have
|
||||
// already weeded out FPs with different ClipPaths.
|
||||
SkASSERT(that.fClipPath->deviceSpacePath().getGenerationID() ==
|
||||
@ -43,10 +42,10 @@ bool GrCCPRClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
|
||||
return that.fOverrideFillType == fOverrideFillType;
|
||||
}
|
||||
|
||||
class GrCCPRClipProcessor::Impl : public GrGLSLFragmentProcessor {
|
||||
class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
void emitCode(EmitArgs& args) override {
|
||||
const GrCCPRClipProcessor& proc = args.fFp.cast<GrCCPRClipProcessor>();
|
||||
const GrCCClipProcessor& proc = args.fFp.cast<GrCCClipProcessor>();
|
||||
GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
|
||||
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
|
||||
|
||||
@ -93,7 +92,7 @@ public:
|
||||
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& fp) override {
|
||||
const GrCCPRClipProcessor& proc = fp.cast<GrCCPRClipProcessor>();
|
||||
const GrCCClipProcessor& proc = fp.cast<GrCCClipProcessor>();
|
||||
if (proc.fMustCheckBounds) {
|
||||
const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds());
|
||||
pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(),
|
||||
@ -109,6 +108,6 @@ private:
|
||||
UniformHandle fAtlasTransformUniform;
|
||||
};
|
||||
|
||||
GrGLSLFragmentProcessor* GrCCPRClipProcessor::onCreateGLSLInstance() const {
|
||||
GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const {
|
||||
return new Impl();
|
||||
}
|
@ -5,13 +5,13 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRClipProcessor_DEFINED
|
||||
#define GrCCPRClipProcessor_DEFINED
|
||||
#ifndef GrCCClipProcessor_DEFINED
|
||||
#define GrCCClipProcessor_DEFINED
|
||||
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "ccpr/GrCoverageCountingPathRenderer.h"
|
||||
|
||||
class GrCCPRClipProcessor : public GrFragmentProcessor {
|
||||
class GrCCClipProcessor : public GrFragmentProcessor {
|
||||
public:
|
||||
using ClipPath = GrCoverageCountingPathRenderer::ClipPath;
|
||||
|
||||
@ -20,9 +20,9 @@ public:
|
||||
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;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRCoverageOp.h"
|
||||
#include "GrCCCoverageOp.h"
|
||||
|
||||
#include "GrCaps.h"
|
||||
#include "GrGpuCommandBuffer.h"
|
||||
@ -15,13 +15,13 @@
|
||||
#include "SkPath.h"
|
||||
#include "SkPathPriv.h"
|
||||
#include "SkPoint.h"
|
||||
#include "ccpr/GrCCPRGeometry.h"
|
||||
#include "ccpr/GrCCGeometry.h"
|
||||
|
||||
using TriangleInstance = GrCCPRCoverageProcessor::TriangleInstance;
|
||||
using CubicInstance = GrCCPRCoverageProcessor::CubicInstance;
|
||||
using TriangleInstance = GrCCCoverageProcessor::TriangleInstance;
|
||||
using CubicInstance = GrCCCoverageProcessor::CubicInstance;
|
||||
|
||||
void GrCCPRCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds,
|
||||
SkRect* devBounds45) {
|
||||
void GrCCCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds,
|
||||
SkRect* devBounds45) {
|
||||
const SkPoint* pts = SkPathPriv::PointData(path);
|
||||
int numPts = path.countPoints();
|
||||
SkASSERT(numPts + 1 <= fLocalDevPtsBuffer.count());
|
||||
@ -69,19 +69,19 @@ void GrCCPRCoverageOpsBuilder::parsePath(const SkMatrix& m, const SkPath& path,
|
||||
SkPoint topLeftPts[2], bottomRightPts[2];
|
||||
topLeft.store(topLeftPts);
|
||||
bottomRight.store(bottomRightPts);
|
||||
devBounds->setLTRB(topLeftPts[0].x(), topLeftPts[0].y(),
|
||||
bottomRightPts[0].x(), bottomRightPts[0].y());
|
||||
devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(),
|
||||
bottomRightPts[1].x(), bottomRightPts[1].y());
|
||||
devBounds->setLTRB(topLeftPts[0].x(), topLeftPts[0].y(), bottomRightPts[0].x(),
|
||||
bottomRightPts[0].y());
|
||||
devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(), bottomRightPts[1].x(),
|
||||
bottomRightPts[1].y());
|
||||
|
||||
this->parsePath(path, fLocalDevPtsBuffer.get());
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOpsBuilder::parseDeviceSpacePath(const SkPath& deviceSpacePath) {
|
||||
void GrCCCoverageOpsBuilder::parseDeviceSpacePath(const SkPath& 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);
|
||||
SkDEBUGCODE(fParsingPath = true);
|
||||
SkASSERT(path.isEmpty() || deviceSpacePts);
|
||||
@ -134,36 +134,30 @@ void GrCCPRCoverageOpsBuilder::parsePath(const SkPath& path, const SkPoint* devi
|
||||
this->endContourIfNeeded(insideContour);
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOpsBuilder::endContourIfNeeded(bool insideContour) {
|
||||
void GrCCCoverageOpsBuilder::endContourIfNeeded(bool insideContour) {
|
||||
if (insideContour) {
|
||||
fCurrPathTallies += fGeometry.endContour();
|
||||
}
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOpsBuilder::saveParsedPath(ScissorMode scissorMode,
|
||||
const SkIRect& clippedDevIBounds,
|
||||
int16_t atlasOffsetX, int16_t atlasOffsetY) {
|
||||
void GrCCCoverageOpsBuilder::saveParsedPath(ScissorMode scissorMode,
|
||||
const SkIRect& clippedDevIBounds, int16_t atlasOffsetX,
|
||||
int16_t atlasOffsetY) {
|
||||
SkASSERT(fParsingPath);
|
||||
|
||||
fPathsInfo.push_back() = {
|
||||
scissorMode,
|
||||
atlasOffsetX, atlasOffsetY,
|
||||
std::move(fTerminatingOp)
|
||||
};
|
||||
fPathsInfo.push_back() = {scissorMode, atlasOffsetX, atlasOffsetY, std::move(fTerminatingOp)};
|
||||
|
||||
fTallies[(int)scissorMode] += fCurrPathTallies;
|
||||
|
||||
if (ScissorMode::kScissored == scissorMode) {
|
||||
fScissorBatches.push_back() = {
|
||||
fCurrPathTallies,
|
||||
clippedDevIBounds.makeOffset(atlasOffsetX, atlasOffsetY)
|
||||
};
|
||||
fScissorBatches.push_back() = {fCurrPathTallies,
|
||||
clippedDevIBounds.makeOffset(atlasOffsetX, atlasOffsetY)};
|
||||
}
|
||||
|
||||
SkDEBUGCODE(fParsingPath = false);
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOpsBuilder::discardParsedPath() {
|
||||
void GrCCCoverageOpsBuilder::discardParsedPath() {
|
||||
SkASSERT(fParsingPath);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOpsBuilder::emitOp(SkISize drawBounds) {
|
||||
void GrCCCoverageOpsBuilder::emitOp(SkISize drawBounds) {
|
||||
SkASSERT(!fTerminatingOp);
|
||||
fTerminatingOp.reset(new GrCCPRCoverageOp(std::move(fScissorBatches), drawBounds));
|
||||
fTerminatingOp.reset(new GrCCCoverageOp(std::move(fScissorBatches), drawBounds));
|
||||
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 twoThirdsCount = (2 * indexCount) / 3;
|
||||
out++->set(pts[indices[firstIndex]],
|
||||
pts[indices[firstIndex + oneThirdCount]],
|
||||
out++->set(pts[indices[firstIndex]], pts[indices[firstIndex + oneThirdCount]],
|
||||
pts[indices[firstIndex + twoThirdsCount]], atlasOffset);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
|
||||
SkTArray<std::unique_ptr<GrCCPRCoverageOp>>* ops) {
|
||||
bool GrCCCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
|
||||
SkTArray<std::unique_ptr<GrCCCoverageOp>>* ops) {
|
||||
SkASSERT(!fParsingPath);
|
||||
|
||||
// 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[].
|
||||
// So, reinterpreting the instance data as CubicInstance[], we start them on the first index
|
||||
// that will not overwrite previous TriangleInstance data.
|
||||
int cubicBaseIdx = GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriangleInstance),
|
||||
sizeof(CubicInstance));
|
||||
int cubicBaseIdx =
|
||||
GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriangleInstance), sizeof(CubicInstance));
|
||||
baseInstances[0].fCubics = cubicBaseIdx;
|
||||
baseInstances[1].fCubics = baseInstances[0].fCubics + fTallies[0].fCubics;
|
||||
int cubicEndIdx = baseInstances[1].fCubics + fTallies[1].fCubics;
|
||||
|
||||
sk_sp<GrBuffer> instanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType,
|
||||
cubicEndIdx * sizeof(CubicInstance));
|
||||
sk_sp<GrBuffer> instanceBuffer =
|
||||
onFlushRP->makeBuffer(kVertex_GrBufferType, cubicEndIdx * sizeof(CubicInstance));
|
||||
if (!instanceBuffer) {
|
||||
return false;
|
||||
}
|
||||
@ -285,9 +278,9 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
|
||||
const SkTArray<SkPoint, true>& pts = fGeometry.points();
|
||||
|
||||
// Expand the ccpr verbs into GPU instance buffers.
|
||||
for (GrCCPRGeometry::Verb verb : fGeometry.verbs()) {
|
||||
for (GrCCGeometry::Verb verb : fGeometry.verbs()) {
|
||||
switch (verb) {
|
||||
case GrCCPRGeometry::Verb::kBeginPath:
|
||||
case GrCCGeometry::Verb::kBeginPath:
|
||||
SkASSERT(currFan.empty());
|
||||
currIndices = &instanceIndices[(int)currPathInfo->fScissorMode];
|
||||
atlasOffsetX = static_cast<float>(currPathInfo->fAtlasOffsetX);
|
||||
@ -308,42 +301,42 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
|
||||
++currPathInfo;
|
||||
continue;
|
||||
|
||||
case GrCCPRGeometry::Verb::kBeginContour:
|
||||
case GrCCGeometry::Verb::kBeginContour:
|
||||
SkASSERT(currFan.empty());
|
||||
currFan.push_back(++ptsIdx);
|
||||
continue;
|
||||
|
||||
case GrCCPRGeometry::Verb::kLineTo:
|
||||
case GrCCGeometry::Verb::kLineTo:
|
||||
SkASSERT(!currFan.empty());
|
||||
currFan.push_back(++ptsIdx);
|
||||
continue;
|
||||
|
||||
case GrCCPRGeometry::Verb::kMonotonicQuadraticTo:
|
||||
case GrCCGeometry::Verb::kMonotonicQuadraticTo:
|
||||
SkASSERT(!currFan.empty());
|
||||
triangleInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx], atlasOffset);
|
||||
currFan.push_back(ptsIdx += 2);
|
||||
continue;
|
||||
|
||||
case GrCCPRGeometry::Verb::kMonotonicCubicTo:
|
||||
case GrCCGeometry::Verb::kMonotonicCubicTo:
|
||||
SkASSERT(!currFan.empty());
|
||||
cubicInstanceData[currIndices->fCubics++].set(&pts[ptsIdx],
|
||||
atlasOffsetX, atlasOffsetY);
|
||||
cubicInstanceData[currIndices->fCubics++].set(&pts[ptsIdx], atlasOffsetX,
|
||||
atlasOffsetY);
|
||||
currFan.push_back(ptsIdx += 3);
|
||||
continue;
|
||||
|
||||
case GrCCPRGeometry::Verb::kEndClosedContour: // endPt == startPt.
|
||||
case GrCCGeometry::Verb::kEndClosedContour: // endPt == startPt.
|
||||
SkASSERT(!currFan.empty());
|
||||
currFan.pop_back();
|
||||
// fallthru.
|
||||
case GrCCPRGeometry::Verb::kEndOpenContour: // endPt != startPt.
|
||||
// fallthru.
|
||||
case GrCCGeometry::Verb::kEndOpenContour: // endPt != startPt.
|
||||
if (currFan.count() >= 3) {
|
||||
int fanSize = currFan.count();
|
||||
// Reserve space for emit_recursive_fan. Technically this can grow to
|
||||
// fanSize + log3(fanSize), but we approximate with log2.
|
||||
currFan.push_back_n(SkNextLog2(fanSize));
|
||||
SkDEBUGCODE(TriangleInstance* end =)
|
||||
emit_recursive_fan(pts, currFan, 0, fanSize, atlasOffset,
|
||||
triangleInstanceData + currIndices->fTriangles);
|
||||
emit_recursive_fan(pts, currFan, 0, fanSize, atlasOffset,
|
||||
triangleInstanceData + currIndices->fTriangles);
|
||||
currIndices->fTriangles += fanSize - 2;
|
||||
SkASSERT(triangleInstanceData + currIndices->fTriangles == end);
|
||||
}
|
||||
@ -372,9 +365,9 @@ bool GrCCPRCoverageOpsBuilder::finalize(GrOnFlushResourceProvider* onFlushRP,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
|
||||
const PrimitiveTallies baseInstances[kNumScissorModes],
|
||||
const PrimitiveTallies endInstances[kNumScissorModes]) {
|
||||
void GrCCCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
|
||||
const PrimitiveTallies baseInstances[kNumScissorModes],
|
||||
const PrimitiveTallies endInstances[kNumScissorModes]) {
|
||||
fInstanceBuffer = std::move(instanceBuffer);
|
||||
fBaseInstances[0] = baseInstances[0];
|
||||
fBaseInstances[1] = baseInstances[1];
|
||||
@ -382,8 +375,8 @@ void GrCCPRCoverageOp::setInstanceBuffer(sk_sp<GrBuffer> instanceBuffer,
|
||||
fInstanceCounts[1] = endInstances[1] - baseInstances[1];
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
|
||||
using RenderPass = GrCCPRCoverageProcessor::RenderPass;
|
||||
void GrCCCoverageOp::onExecute(GrOpFlushState* flushState) {
|
||||
using RenderPass = GrCCCoverageProcessor::RenderPass;
|
||||
|
||||
SkASSERT(fInstanceBuffer);
|
||||
|
||||
@ -397,7 +390,7 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
|
||||
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls,
|
||||
&PrimitiveTallies::fTriangles);
|
||||
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges,
|
||||
&PrimitiveTallies::fTriangles); // Might get skipped.
|
||||
&PrimitiveTallies::fTriangles); // Might get skipped.
|
||||
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners,
|
||||
&PrimitiveTallies::fTriangles);
|
||||
|
||||
@ -414,21 +407,21 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
|
||||
&PrimitiveTallies::fCubics);
|
||||
}
|
||||
|
||||
void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline,
|
||||
GrCCPRCoverageProcessor::RenderPass renderPass,
|
||||
int PrimitiveTallies::* instanceType) const {
|
||||
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
|
||||
void GrCCCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline,
|
||||
GrCCCoverageProcessor::RenderPass renderPass,
|
||||
int PrimitiveTallies::*instanceType) const {
|
||||
using ScissorMode = GrCCCoverageOpsBuilder::ScissorMode;
|
||||
SkASSERT(pipeline.getScissorState().enabled());
|
||||
|
||||
if (!GrCCPRCoverageProcessor::DoesRenderPass(renderPass, *flushState->caps().shaderCaps())) {
|
||||
if (!GrCCCoverageProcessor::DoesRenderPass(renderPass, *flushState->caps().shaderCaps())) {
|
||||
return;
|
||||
}
|
||||
|
||||
fMeshesScratchBuffer.reset();
|
||||
fDynamicStatesScratchBuffer.reset();
|
||||
|
||||
GrCCPRCoverageProcessor proc(flushState->resourceProvider(), renderPass,
|
||||
*flushState->caps().shaderCaps());
|
||||
GrCCCoverageProcessor proc(flushState->resourceProvider(), renderPass,
|
||||
*flushState->caps().shaderCaps());
|
||||
|
||||
if (int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
|
||||
SkASSERT(instanceCount > 0);
|
@ -5,23 +5,23 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRCoverageOp_DEFINED
|
||||
#define GrCCPRCoverageOp_DEFINED
|
||||
#ifndef GrCCCoverageOp_DEFINED
|
||||
#define GrCCCoverageOp_DEFINED
|
||||
|
||||
#include "GrMesh.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "ccpr/GrCCPRCoverageProcessor.h"
|
||||
#include "ccpr/GrCCPRGeometry.h"
|
||||
#include "ccpr/GrCCCoverageProcessor.h"
|
||||
#include "ccpr/GrCCGeometry.h"
|
||||
#include "ops/GrDrawOp.h"
|
||||
|
||||
class GrCCPRCoverageOp;
|
||||
class GrCCCoverageOp;
|
||||
class GrOnFlushResourceProvider;
|
||||
class SkMatrix;
|
||||
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:
|
||||
*
|
||||
* 1) parsePath(ScissorMode, viewMatrix, path, &devBounds, &devBounds45);
|
||||
@ -30,28 +30,25 @@ class SkPath;
|
||||
*
|
||||
* 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().
|
||||
*/
|
||||
class GrCCPRCoverageOpsBuilder {
|
||||
class GrCCCoverageOpsBuilder {
|
||||
public:
|
||||
// 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.)
|
||||
enum class ScissorMode : int {
|
||||
kNonScissored = 0,
|
||||
kScissored = 1
|
||||
};
|
||||
enum class ScissorMode : int { kNonScissored = 0, kScissored = 1 };
|
||||
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)
|
||||
, fLocalDevPtsBuffer(maxPathPoints + 1) // Overallocate by one point to accomodate for
|
||||
// overflow with Sk4f. (See parsePath.)
|
||||
, fLocalDevPtsBuffer(maxPathPoints + 1) // Overallocate by one point to accomodate for
|
||||
// overflow with Sk4f. (See parsePath.)
|
||||
, fGeometry(numSkPoints, numSkVerbs)
|
||||
, fTallies{PrimitiveTallies(), PrimitiveTallies()}
|
||||
, fScissorBatches(maxTotalPaths) {}
|
||||
|
||||
~GrCCPRCoverageOpsBuilder() {
|
||||
~GrCCCoverageOpsBuilder() {
|
||||
// Enforce the contract that the client always calls saveParsedPath or discardParsedPath.
|
||||
SkASSERT(!fParsingPath);
|
||||
}
|
||||
@ -72,27 +69,27 @@ public:
|
||||
// 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
|
||||
// translate for placement in an atlas.
|
||||
void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds,
|
||||
int16_t atlasOffsetX, int16_t atlasOffsetY);
|
||||
void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds, int16_t atlasOffsetX,
|
||||
int16_t atlasOffsetY);
|
||||
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
|
||||
// may still call saveParsedPath to include it in a future Op.
|
||||
void emitOp(SkISize drawBounds);
|
||||
|
||||
// Builds GPU buffers and returns the list of GrCCPRCoverageOps as specified by calls to emitOp.
|
||||
bool finalize(GrOnFlushResourceProvider*, SkTArray<std::unique_ptr<GrCCPRCoverageOp>>*);
|
||||
// Builds GPU buffers and returns the list of GrCCCoverageOps as specified by calls to emitOp.
|
||||
bool finalize(GrOnFlushResourceProvider*, SkTArray<std::unique_ptr<GrCCCoverageOp>>*);
|
||||
|
||||
private:
|
||||
using PrimitiveTallies = GrCCPRGeometry::PrimitiveTallies;
|
||||
using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;
|
||||
|
||||
// Every kBeginPath verb has a corresponding PathInfo entry.
|
||||
struct PathInfo {
|
||||
ScissorMode fScissorMode;
|
||||
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.
|
||||
@ -113,25 +110,25 @@ private:
|
||||
SkSTArray<32, PathInfo, true> fPathsInfo;
|
||||
|
||||
const SkAutoSTArray<32, SkPoint> fLocalDevPtsBuffer;
|
||||
GrCCPRGeometry fGeometry;
|
||||
GrCCGeometry fGeometry;
|
||||
|
||||
PrimitiveTallies fTallies[kNumScissorModes];
|
||||
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:
|
||||
DEFINE_OP_CLASS_ID
|
||||
|
||||
// GrDrawOp interface.
|
||||
const char* name() const override { return "GrCCPRCoverageOp"; }
|
||||
const char* name() const override { return "GrCCCoverageOp"; }
|
||||
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
|
||||
RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
|
||||
GrPixelConfigIsClamped) override {
|
||||
@ -142,14 +139,14 @@ public:
|
||||
void onExecute(GrOpFlushState*) override;
|
||||
|
||||
private:
|
||||
static constexpr int kNumScissorModes = GrCCPRCoverageOpsBuilder::kNumScissorModes;
|
||||
using PrimitiveTallies = GrCCPRGeometry::PrimitiveTallies;
|
||||
using ScissorBatch = GrCCPRCoverageOpsBuilder::ScissorBatch;
|
||||
static constexpr int kNumScissorModes = GrCCCoverageOpsBuilder::kNumScissorModes;
|
||||
using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;
|
||||
using ScissorBatch = GrCCCoverageOpsBuilder::ScissorBatch;
|
||||
|
||||
GrCCPRCoverageOp(SkTArray<ScissorBatch, true>&& scissorBatches, const SkISize& drawBounds)
|
||||
: INHERITED(ClassID())
|
||||
, fScissorBatches(std::move(scissorBatches))
|
||||
, fDrawBounds(drawBounds) {
|
||||
GrCCCoverageOp(SkTArray<ScissorBatch, true>&& scissorBatches, const SkISize& drawBounds)
|
||||
: INHERITED(ClassID())
|
||||
, fScissorBatches(std::move(scissorBatches))
|
||||
, fDrawBounds(drawBounds) {
|
||||
this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()),
|
||||
GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
|
||||
}
|
||||
@ -158,8 +155,8 @@ private:
|
||||
const PrimitiveTallies baseInstances[kNumScissorModes],
|
||||
const PrimitiveTallies endInstances[kNumScissorModes]);
|
||||
|
||||
void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&, GrCCPRCoverageProcessor::RenderPass,
|
||||
int PrimitiveTallies::* instanceType) const;
|
||||
void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&, GrCCCoverageProcessor::RenderPass,
|
||||
int PrimitiveTallies::*instanceType) const;
|
||||
|
||||
sk_sp<GrBuffer> fInstanceBuffer;
|
||||
PrimitiveTallies fBaseInstances[kNumScissorModes];
|
||||
@ -170,7 +167,7 @@ private:
|
||||
mutable SkTArray<GrMesh> fMeshesScratchBuffer;
|
||||
mutable SkTArray<GrPipeline::DynamicState, true> fDynamicStatesScratchBuffer;
|
||||
|
||||
friend class GrCCPRCoverageOpsBuilder;
|
||||
friend class GrCCCoverageOpsBuilder;
|
||||
|
||||
typedef GrDrawOp INHERITED;
|
||||
};
|
@ -5,20 +5,20 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRCoverageProcessor.h"
|
||||
#include "GrCCCoverageProcessor.h"
|
||||
|
||||
#include "SkMakeUnique.h"
|
||||
#include "ccpr/GrCCPRCubicShader.h"
|
||||
#include "ccpr/GrCCPRQuadraticShader.h"
|
||||
#include "ccpr/GrCCPRTriangleShader.h"
|
||||
#include "ccpr/GrCCCubicShader.h"
|
||||
#include "ccpr/GrCCQuadraticShader.h"
|
||||
#include "ccpr/GrCCTriangleShader.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code,
|
||||
const char* position, const char* coverage,
|
||||
const char* wind) {
|
||||
void GrCCCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code,
|
||||
const char* position, const char* coverage,
|
||||
const char* wind) {
|
||||
SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
|
||||
WindHandling windHandling = this->onEmitVaryings(varyingHandler, scope, code, position,
|
||||
coverage, wind);
|
||||
@ -29,10 +29,10 @@ void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varying
|
||||
}
|
||||
}
|
||||
|
||||
void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProcessor& proc,
|
||||
GrGLSLPPFragmentBuilder* f,
|
||||
const char* skOutputColor,
|
||||
const char* skOutputCoverage) const {
|
||||
void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
|
||||
GrGLSLPPFragmentBuilder* f,
|
||||
const char* skOutputColor,
|
||||
const char* skOutputCoverage) const {
|
||||
f->codeAppendf("half coverage = 0;");
|
||||
this->onEmitFragmentCode(f, "coverage");
|
||||
if (fWind.fsIn()) {
|
||||
@ -49,10 +49,10 @@ void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProce
|
||||
#endif
|
||||
}
|
||||
|
||||
void GrCCPRCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s,
|
||||
const char* leftPt,
|
||||
const char* rightPt,
|
||||
const char* outputDistanceEquation) {
|
||||
void GrCCCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s,
|
||||
const char* leftPt,
|
||||
const char* rightPt,
|
||||
const char* outputDistanceEquation) {
|
||||
s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
|
||||
rightPt, leftPt, leftPt, rightPt);
|
||||
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);
|
||||
}
|
||||
|
||||
int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
|
||||
const char* samplesName) {
|
||||
int GrCCCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
|
||||
const char* samplesName) {
|
||||
// Standard DX11 sample locations.
|
||||
#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
|
||||
f->defineConstant("float2[8]", samplesName, "float2[8]("
|
||||
@ -82,8 +82,8 @@ int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentB
|
||||
#endif
|
||||
}
|
||||
|
||||
void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
void GrCCCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
int key = (int)fRenderPass << 1;
|
||||
if (Impl::kGeometryShader == fImpl) {
|
||||
key |= 1;
|
||||
@ -96,27 +96,27 @@ void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
|
||||
b->add32(key);
|
||||
}
|
||||
|
||||
GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
|
||||
GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
|
||||
std::unique_ptr<Shader> shader;
|
||||
switch (fRenderPass) {
|
||||
case RenderPass::kTriangleHulls:
|
||||
case RenderPass::kTriangleEdges:
|
||||
shader = skstd::make_unique<GrCCPRTriangleShader>();
|
||||
shader = skstd::make_unique<GrCCTriangleShader>();
|
||||
break;
|
||||
case RenderPass::kTriangleCorners:
|
||||
shader = skstd::make_unique<GrCCPRTriangleCornerShader>();
|
||||
shader = skstd::make_unique<GrCCTriangleCornerShader>();
|
||||
break;
|
||||
case RenderPass::kQuadraticHulls:
|
||||
shader = skstd::make_unique<GrCCPRQuadraticHullShader>();
|
||||
shader = skstd::make_unique<GrCCQuadraticHullShader>();
|
||||
break;
|
||||
case RenderPass::kQuadraticCorners:
|
||||
shader = skstd::make_unique<GrCCPRQuadraticCornerShader>();
|
||||
shader = skstd::make_unique<GrCCQuadraticCornerShader>();
|
||||
break;
|
||||
case RenderPass::kCubicHulls:
|
||||
shader = skstd::make_unique<GrCCPRCubicHullShader>();
|
||||
shader = skstd::make_unique<GrCCCubicHullShader>();
|
||||
break;
|
||||
case RenderPass::kCubicCorners:
|
||||
shader = skstd::make_unique<GrCCPRCubicCornerShader>();
|
||||
shader = skstd::make_unique<GrCCCubicCornerShader>();
|
||||
break;
|
||||
}
|
||||
return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))
|
@ -5,8 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRCoverageProcessor_DEFINED
|
||||
#define GrCCPRCoverageProcessor_DEFINED
|
||||
#ifndef GrCCCoverageProcessor_DEFINED
|
||||
#define GrCCCoverageProcessor_DEFINED
|
||||
|
||||
#include "GrGeometryProcessor.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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
class GrCCPRCoverageProcessor : public GrGeometryProcessor {
|
||||
class GrCCCoverageProcessor : public GrGeometryProcessor {
|
||||
public:
|
||||
// Defines a single triangle or closed quadratic bezier, with transposed x,y point values.
|
||||
struct TriangleInstance {
|
||||
@ -91,8 +91,8 @@ public:
|
||||
return RenderPass::kTriangleEdges != renderPass || caps.geometryShaderSupport();
|
||||
}
|
||||
|
||||
GrCCPRCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrShaderCaps& caps)
|
||||
: INHERITED(kGrCCPRCoverageProcessor_ClassID)
|
||||
GrCCCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrShaderCaps& caps)
|
||||
: INHERITED(kGrCCCoverageProcessor_ClassID)
|
||||
, fRenderPass(pass)
|
||||
, fImpl(caps.geometryShaderSupport() ? Impl::kGeometryShader : Impl::kVertexShader) {
|
||||
SkASSERT(DoesRenderPass(pass, caps));
|
||||
@ -162,7 +162,7 @@ public:
|
||||
void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||
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;
|
||||
|
||||
// Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
|
||||
@ -246,31 +246,31 @@ private:
|
||||
const Impl fImpl;
|
||||
sk_sp<const GrBuffer> fVertexBuffer; // Used by VSImpl.
|
||||
sk_sp<const GrBuffer> fIndexBuffer; // Used by VSImpl.
|
||||
SkDEBUGCODE(float fDebugBloat = 0;)
|
||||
SkDEBUGCODE(float fDebugBloat = 0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
|
||||
const SkPoint& p2, const Sk2f& trans) {
|
||||
inline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
|
||||
const SkPoint& p2, const Sk2f& trans) {
|
||||
Sk2f P0 = Sk2f::Load(&p0) + trans;
|
||||
Sk2f P1 = Sk2f::Load(&p1) + trans;
|
||||
Sk2f P2 = Sk2f::Load(&p2) + trans;
|
||||
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::Load2(p, &X, &Y);
|
||||
(X + dx).store(&fX);
|
||||
(Y + dy).store(&fY);
|
||||
}
|
||||
|
||||
inline bool GrCCPRCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
|
||||
inline bool GrCCCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
|
||||
switch (pass) {
|
||||
case RenderPass::kTriangleHulls:
|
||||
case RenderPass::kTriangleEdges:
|
||||
@ -286,7 +286,7 @@ inline bool GrCCPRCoverageProcessor::RenderPassIsCubic(RenderPass pass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline const char* GrCCPRCoverageProcessor::RenderPassName(RenderPass pass) {
|
||||
inline const char* GrCCCoverageProcessor::RenderPassName(RenderPass pass) {
|
||||
switch (pass) {
|
||||
case RenderPass::kTriangleHulls: return "kTriangleHulls";
|
||||
case RenderPass::kTriangleEdges: return "kTriangleEdges";
|
@ -5,19 +5,19 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRCoverageProcessor.h"
|
||||
#include "GrCCCoverageProcessor.h"
|
||||
|
||||
#include "GrMesh.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
using InputType = GrGLSLGeometryBuilder::InputType;
|
||||
using OutputType = GrGLSLGeometryBuilder::OutputType;
|
||||
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||
using Shader = GrCCCoverageProcessor::Shader;
|
||||
|
||||
/**
|
||||
* This class and its subclasses implement the coverage processor with geometry shaders.
|
||||
*/
|
||||
class GrCCPRCoverageProcessor::GSImpl : public GrGLSLGeometryProcessor {
|
||||
class GrCCCoverageProcessor::GSImpl : public GrGLSLGeometryProcessor {
|
||||
protected:
|
||||
GSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
|
||||
|
||||
@ -27,7 +27,7 @@ protected:
|
||||
}
|
||||
|
||||
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.
|
||||
SkASSERT(1 == proc.numAttribs());
|
||||
@ -45,7 +45,7 @@ protected:
|
||||
fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
|
||||
}
|
||||
|
||||
void emitGeometryShader(const GrCCPRCoverageProcessor& proc,
|
||||
void emitGeometryShader(const GrCCCoverageProcessor& proc,
|
||||
GrGLSLVaryingHandler* varyingHandler, GrGLSLGeometryBuilder* g,
|
||||
const char* rtAdjust) const {
|
||||
int numInputPoints = proc.numInputPoints();
|
||||
@ -102,7 +102,7 @@ protected:
|
||||
/**
|
||||
* Generates a conservative raster hull around a triangle. (See comments for RenderPass)
|
||||
*/
|
||||
class GSHull3Impl : public GrCCPRCoverageProcessor::GSImpl {
|
||||
class GSHull3Impl : public GrCCCoverageProcessor::GSImpl {
|
||||
public:
|
||||
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)
|
||||
*/
|
||||
class GSHull4Impl : public GrCCPRCoverageProcessor::GSImpl {
|
||||
class GSHull4Impl : public GrCCCoverageProcessor::GSImpl {
|
||||
public:
|
||||
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)
|
||||
*/
|
||||
class GSEdgeImpl : public GrCCPRCoverageProcessor::GSImpl {
|
||||
class GSEdgeImpl : public GrCCCoverageProcessor::GSImpl {
|
||||
public:
|
||||
GSEdgeImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
|
||||
|
||||
@ -295,7 +295,7 @@ public:
|
||||
/**
|
||||
* Generates conservative rasters around corners. (See comments for RenderPass)
|
||||
*/
|
||||
class GSCornerImpl : public GrCCPRCoverageProcessor::GSImpl {
|
||||
class GSCornerImpl : public GrCCCoverageProcessor::GSImpl {
|
||||
public:
|
||||
GSCornerImpl(std::unique_ptr<Shader> shader, int numCorners)
|
||||
: GSImpl(std::move(shader)), fNumCorners(numCorners) {}
|
||||
@ -320,7 +320,7 @@ private:
|
||||
const int fNumCorners;
|
||||
};
|
||||
|
||||
void GrCCPRCoverageProcessor::initGS() {
|
||||
void GrCCCoverageProcessor::initGS() {
|
||||
SkASSERT(Impl::kGeometryShader == fImpl);
|
||||
if (RenderPassIsCubic(fRenderPass)) {
|
||||
this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.)
|
||||
@ -332,8 +332,8 @@ void GrCCPRCoverageProcessor::initGS() {
|
||||
this->setWillUseGeoShader();
|
||||
}
|
||||
|
||||
void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, SkTArray<GrMesh>* out) const {
|
||||
void GrCCCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, SkTArray<GrMesh>* out) const {
|
||||
// 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
|
||||
// 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);
|
||||
}
|
||||
|
||||
GrGLSLPrimitiveProcessor*
|
||||
GrCCPRCoverageProcessor::createGSImpl(std::unique_ptr<Shader> shader) const {
|
||||
GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGSImpl(std::unique_ptr<Shader> shadr) const {
|
||||
switch (fRenderPass) {
|
||||
case RenderPass::kTriangleHulls:
|
||||
return new GSHull3Impl(std::move(shader));
|
||||
return new GSHull3Impl(std::move(shadr));
|
||||
case RenderPass::kQuadraticHulls:
|
||||
case RenderPass::kCubicHulls:
|
||||
return new GSHull4Impl(std::move(shader));
|
||||
return new GSHull4Impl(std::move(shadr));
|
||||
case RenderPass::kTriangleEdges:
|
||||
return new GSEdgeImpl(std::move(shader));
|
||||
return new GSEdgeImpl(std::move(shadr));
|
||||
case RenderPass::kTriangleCorners:
|
||||
return new GSCornerImpl(std::move(shader), 3);
|
||||
return new GSCornerImpl(std::move(shadr), 3);
|
||||
case RenderPass::kQuadraticCorners:
|
||||
case RenderPass::kCubicCorners:
|
||||
return new GSCornerImpl(std::move(shader), 2);
|
||||
return new GSCornerImpl(std::move(shadr), 2);
|
||||
}
|
||||
SK_ABORT("Invalid RenderPass");
|
||||
return nullptr;
|
@ -5,12 +5,12 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRCoverageProcessor.h"
|
||||
#include "GrCCCoverageProcessor.h"
|
||||
|
||||
#include "GrMesh.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||
using Shader = GrCCCoverageProcessor::Shader;
|
||||
|
||||
static constexpr int kAttribIdx_X = 0;
|
||||
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.
|
||||
*/
|
||||
class GrCCPRCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
|
||||
class GrCCCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
|
||||
protected:
|
||||
VSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
|
||||
|
||||
@ -29,7 +29,7 @@ protected:
|
||||
}
|
||||
|
||||
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
|
||||
const GrCCPRCoverageProcessor& proc = args.fGP.cast<GrCCPRCoverageProcessor>();
|
||||
const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();
|
||||
|
||||
// Vertex shader.
|
||||
GrGLSLVertexBuilder* v = args.fVertBuilder;
|
||||
@ -69,7 +69,7 @@ protected:
|
||||
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;
|
||||
|
||||
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
|
||||
* independent conservative rasters around each edge. (See comments for RenderPass)
|
||||
*/
|
||||
class VSHullAndEdgeImpl : public GrCCPRCoverageProcessor::VSImpl {
|
||||
class VSHullAndEdgeImpl : public GrCCCoverageProcessor::VSImpl {
|
||||
public:
|
||||
VSHullAndEdgeImpl(std::unique_ptr<Shader> shader, int 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 {
|
||||
Shader::GeometryVars 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)
|
||||
*/
|
||||
class VSCornerImpl : public GrCCPRCoverageProcessor::VSImpl {
|
||||
class VSCornerImpl : public GrCCCoverageProcessor::VSImpl {
|
||||
public:
|
||||
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 {
|
||||
Shader::GeometryVars vars;
|
||||
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);
|
||||
|
||||
GrVertexAttribType inputPtsType = RenderPassIsCubic(fRenderPass) ?
|
||||
@ -388,9 +388,9 @@ void GrCCPRCoverageProcessor::initVS(GrResourceProvider* rp) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int num_indices_per_instance(GrCCPRCoverageProcessor::RenderPass pass) {
|
||||
static int num_indices_per_instance(GrCCCoverageProcessor::RenderPass pass) {
|
||||
switch (pass) {
|
||||
using RenderPass = GrCCPRCoverageProcessor::RenderPass;
|
||||
using RenderPass = GrCCCoverageProcessor::RenderPass;
|
||||
case RenderPass::kTriangleHulls:
|
||||
return SK_ARRAY_COUNT(kHull3AndEdgeIndices);
|
||||
case RenderPass::kQuadraticHulls:
|
||||
@ -409,8 +409,8 @@ static int num_indices_per_instance(GrCCPRCoverageProcessor::RenderPass pass) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GrCCPRCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, SkTArray<GrMesh>* out) const {
|
||||
void GrCCCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, SkTArray<GrMesh>* out) const {
|
||||
SkASSERT(Impl::kVertexShader == fImpl);
|
||||
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangles);
|
||||
mesh.setIndexedInstanced(fIndexBuffer.get(), num_indices_per_instance(fRenderPass),
|
||||
@ -420,21 +420,20 @@ void GrCCPRCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanc
|
||||
}
|
||||
}
|
||||
|
||||
GrGLSLPrimitiveProcessor*
|
||||
GrCCPRCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shader) const {
|
||||
GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const {
|
||||
switch (fRenderPass) {
|
||||
case RenderPass::kTriangleHulls:
|
||||
return new VSHullAndEdgeImpl(std::move(shader), 3);
|
||||
return new VSHullAndEdgeImpl(std::move(shadr), 3);
|
||||
case RenderPass::kQuadraticHulls:
|
||||
case RenderPass::kCubicHulls:
|
||||
return new VSHullAndEdgeImpl(std::move(shader), 4);
|
||||
return new VSHullAndEdgeImpl(std::move(shadr), 4);
|
||||
case RenderPass::kTriangleEdges:
|
||||
SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
|
||||
return nullptr;
|
||||
case RenderPass::kTriangleCorners:
|
||||
case RenderPass::kQuadraticCorners:
|
||||
case RenderPass::kCubicCorners:
|
||||
return new VSCornerImpl(std::move(shader));
|
||||
return new VSCornerImpl(std::move(shadr));
|
||||
}
|
||||
SK_ABORT("Invalid RenderPass");
|
||||
return nullptr;
|
@ -5,16 +5,16 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRCubicShader.h"
|
||||
#include "GrCCCubicShader.h"
|
||||
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||
using Shader = GrCCCoverageProcessor::Shader;
|
||||
|
||||
void GrCCPRCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, const char* wind,
|
||||
GeometryVars* vars) const {
|
||||
void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, const char* wind,
|
||||
GeometryVars* vars) const {
|
||||
// Find the cubic's power basis coefficients.
|
||||
s->codeAppendf("float2x4 C = float4x4(-1, 3, -3, 1, "
|
||||
" 3, -6, 3, 0, "
|
||||
@ -75,10 +75,10 @@ void GrCCPRCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts
|
||||
this->onEmitSetupCode(s, pts, repetitionID, vars);
|
||||
}
|
||||
|
||||
Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope,
|
||||
SkString* code, const char* position,
|
||||
const char* coverage, const char* /*wind*/) {
|
||||
Shader::WindHandling GrCCCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope,
|
||||
SkString* code, const char* position,
|
||||
const char* coverage, const char* /*wind*/) {
|
||||
SkASSERT(!coverage);
|
||||
|
||||
fKLMD.reset(kFloat4_GrSLType, scope);
|
||||
@ -91,8 +91,8 @@ Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* var
|
||||
return WindHandling::kNotHandled;
|
||||
}
|
||||
|
||||
void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
void GrCCCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
fGradMatrix.reset(kFloat2x2_GrSLType, scope);
|
||||
varyingHandler->addVarying("grad_matrix", &fGradMatrix);
|
||||
// "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());
|
||||
}
|
||||
|
||||
void GrCCPRCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
void GrCCCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
|
||||
fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
|
||||
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.
|
||||
}
|
||||
|
||||
void GrCCPRCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, GeometryVars* vars) const {
|
||||
void GrCCCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, GeometryVars* vars) const {
|
||||
s->codeAppendf("float2 corner = %s[%s * 3];", pts, repetitionID);
|
||||
vars->fCornerVars.fPoint = "corner";
|
||||
}
|
||||
|
||||
void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
void GrCCCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
fdKLMDdx.reset(kFloat4_GrSLType, scope);
|
||||
varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx);
|
||||
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());
|
||||
}
|
||||
|
||||
void GrCCPRCubicCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
void GrCCCubicCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
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
|
@ -5,10 +5,10 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRCubicShader_DEFINED
|
||||
#define GrCCPRCubicShader_DEFINED
|
||||
#ifndef GrCCCubicShader_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
|
||||
@ -19,9 +19,9 @@
|
||||
*
|
||||
* 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.
|
||||
* (Use GrCCPRGeometry.)
|
||||
* (Use GrCCGeometry.)
|
||||
*/
|
||||
class GrCCPRCubicShader : public GrCCPRCoverageProcessor::Shader {
|
||||
class GrCCCubicShader : public GrCCCoverageProcessor::Shader {
|
||||
protected:
|
||||
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||
const char* wind, GeometryVars*) const final;
|
||||
@ -39,14 +39,14 @@ protected:
|
||||
GrGLSLVarying fKLMD;
|
||||
};
|
||||
|
||||
class GrCCPRCubicHullShader : public GrCCPRCubicShader {
|
||||
class GrCCCubicHullShader : public GrCCCubicShader {
|
||||
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
||||
|
||||
GrGLSLVarying fGradMatrix;
|
||||
};
|
||||
|
||||
class GrCCPRCubicCornerShader : public GrCCPRCubicShader {
|
||||
class GrCCCubicCornerShader : public GrCCCubicShader {
|
||||
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||
GeometryVars*) const override;
|
||||
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRGeometry.h"
|
||||
#include "GrCCGeometry.h"
|
||||
|
||||
#include "GrTypes.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(0 == offsetof(SkPoint, fX));
|
||||
|
||||
void GrCCPRGeometry::beginPath() {
|
||||
void GrCCGeometry::beginPath() {
|
||||
SkASSERT(!fBuildingContour);
|
||||
fVerbs.push_back(Verb::kBeginPath);
|
||||
}
|
||||
|
||||
void GrCCPRGeometry::beginContour(const SkPoint& devPt) {
|
||||
void GrCCGeometry::beginContour(const SkPoint& devPt) {
|
||||
SkASSERT(!fBuildingContour);
|
||||
|
||||
fCurrFanPoint = fCurrAnchorPoint = devPt;
|
||||
@ -35,10 +35,10 @@ void GrCCPRGeometry::beginContour(const SkPoint& devPt) {
|
||||
fPoints.push_back(devPt);
|
||||
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(fCurrFanPoint == fPoints.back());
|
||||
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);
|
||||
}
|
||||
|
||||
void GrCCPRGeometry::quadraticTo(const SkPoint& devP0, const SkPoint& devP1) {
|
||||
void GrCCGeometry::quadraticTo(const SkPoint& devP0, const SkPoint& devP1) {
|
||||
SkASSERT(fBuildingContour);
|
||||
SkASSERT(fCurrFanPoint == fPoints.back());
|
||||
|
||||
@ -102,8 +102,8 @@ void GrCCPRGeometry::quadraticTo(const SkPoint& devP0, const SkPoint& devP1) {
|
||||
this->appendMonotonicQuadratics(p0, p1, p2);
|
||||
}
|
||||
|
||||
inline void GrCCPRGeometry::appendMonotonicQuadratics(const Sk2f& p0, const Sk2f& p1,
|
||||
const Sk2f& p2) {
|
||||
inline void GrCCGeometry::appendMonotonicQuadratics(const Sk2f& p0, const Sk2f& p1,
|
||||
const Sk2f& p2) {
|
||||
Sk2f tan0 = p1 - p0;
|
||||
Sk2f tan1 = p2 - p1;
|
||||
|
||||
@ -141,8 +141,8 @@ inline void GrCCPRGeometry::appendMonotonicQuadratics(const Sk2f& p0, const Sk2f
|
||||
this->appendSingleMonotonicQuadratic(p012, p12, p2);
|
||||
}
|
||||
|
||||
inline void GrCCPRGeometry::appendSingleMonotonicQuadratic(const Sk2f& p0, const Sk2f& p1,
|
||||
const Sk2f& p2) {
|
||||
inline void GrCCGeometry::appendSingleMonotonicQuadratic(const Sk2f& p0, const Sk2f& p1,
|
||||
const Sk2f& p2) {
|
||||
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).
|
||||
@ -285,8 +285,8 @@ static inline bool is_cubic_nearly_quadratic(const Sk2f& p0, const Sk2f& p1, con
|
||||
return ((c1 - c2).abs() <= 1).allTrue();
|
||||
}
|
||||
|
||||
void GrCCPRGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const SkPoint& devP3,
|
||||
float inflectPad, float loopIntersectPad) {
|
||||
void GrCCGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const SkPoint& devP3,
|
||||
float inflectPad, float loopIntersectPad) {
|
||||
SkASSERT(fBuildingContour);
|
||||
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.
|
||||
if (T1 >= 1) {
|
||||
// Only sections 1 & 2 can be in 0..1.
|
||||
this->chopCubic<&GrCCPRGeometry::appendMonotonicCubics,
|
||||
&GrCCPRGeometry::appendCubicApproximation>(p0, p1, p2, p3, T0);
|
||||
this->chopCubic<&GrCCGeometry::appendMonotonicCubics,
|
||||
&GrCCGeometry::appendCubicApproximation>(p0, p1, p2, p3, T0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (T2 <= 0) {
|
||||
// Only sections 4 & 5 can be in 0..1.
|
||||
this->chopCubic<&GrCCPRGeometry::appendCubicApproximation,
|
||||
&GrCCPRGeometry::appendMonotonicCubics>(p0, p1, p2, p3, T3);
|
||||
this->chopCubic<&GrCCGeometry::appendCubicApproximation,
|
||||
&GrCCGeometry::appendMonotonicCubics>(p0, p1, p2, p3, T3);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -414,8 +414,8 @@ void GrCCPRGeometry::cubicTo(const SkPoint& devP1, const SkPoint& devP2, const S
|
||||
Sk2f abcd1 = lerp(abc1, bcd1, T1T1);
|
||||
|
||||
// Sections 1 & 2.
|
||||
this->chopCubic<&GrCCPRGeometry::appendMonotonicCubics,
|
||||
&GrCCPRGeometry::appendCubicApproximation>(p0, ab1, abc1, abcd1, T0/T1);
|
||||
this->chopCubic<&GrCCGeometry::appendMonotonicCubics,
|
||||
&GrCCGeometry::appendCubicApproximation>(p0, ab1, abc1, abcd1, T0/T1);
|
||||
|
||||
if (T2 >= 1) {
|
||||
// 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.
|
||||
this->chopCubic<&GrCCPRGeometry::appendCubicApproximation,
|
||||
&GrCCPRGeometry::appendMonotonicCubics>(abcd2, bcd2, cd2, p3, (T3-T2) / (1-T2));
|
||||
this->chopCubic<&GrCCGeometry::appendCubicApproximation,
|
||||
&GrCCGeometry::appendMonotonicCubics>(abcd2, bcd2, cd2, p3, (T3-T2) / (1-T2));
|
||||
}
|
||||
|
||||
template<GrCCPRGeometry::AppendCubicFn AppendLeftRight>
|
||||
inline void GrCCPRGeometry::chopCubicAtMidTangent(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, const Sk2f& tan0,
|
||||
const Sk2f& tan3, int maxFutureSubdivisions) {
|
||||
template<GrCCGeometry::AppendCubicFn AppendLeftRight>
|
||||
inline void GrCCGeometry::chopCubicAtMidTangent(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, const Sk2f& tan0,
|
||||
const Sk2f& tan3, int maxFutureSubdivisions) {
|
||||
// Find the T value whose tangent is perpendicular to the vector that bisects tan0 and -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);
|
||||
}
|
||||
|
||||
template<GrCCPRGeometry::AppendCubicFn AppendLeft, GrCCPRGeometry::AppendCubicFn AppendRight>
|
||||
inline void GrCCPRGeometry::chopCubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, float T, int maxFutureSubdivisions) {
|
||||
template<GrCCGeometry::AppendCubicFn AppendLeft, GrCCGeometry::AppendCubicFn AppendRight>
|
||||
inline void GrCCGeometry::chopCubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, float T, int maxFutureSubdivisions) {
|
||||
if (T >= 1) {
|
||||
(this->*AppendLeft)(p0, p1, p2, p3, maxFutureSubdivisions);
|
||||
return;
|
||||
@ -506,8 +506,8 @@ inline void GrCCPRGeometry::chopCubic(const Sk2f& p0, const Sk2f& p1, const Sk2f
|
||||
(this->*AppendRight)(abcd, bcd, cd, p3, maxFutureSubdivisions);
|
||||
}
|
||||
|
||||
void GrCCPRGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, int maxSubdivisions) {
|
||||
void GrCCGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, int maxSubdivisions) {
|
||||
SkASSERT(maxSubdivisions >= 0);
|
||||
if ((p0 == p3).allTrue()) {
|
||||
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);
|
||||
|
||||
if (!is_convex_curve_monotonic(p0, tan0, p3, tan3)) {
|
||||
this->chopCubicAtMidTangent<&GrCCPRGeometry::appendMonotonicCubics>(p0, p1, p2, p3,
|
||||
tan0, tan3,
|
||||
maxSubdivisions-1);
|
||||
this->chopCubicAtMidTangent<&GrCCGeometry::appendMonotonicCubics>(p0, p1, p2, p3,
|
||||
tan0, tan3,
|
||||
maxSubdivisions - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -542,8 +542,8 @@ void GrCCPRGeometry::appendMonotonicCubics(const Sk2f& p0, const Sk2f& p1, const
|
||||
++fCurrContourTallies.fCubics;
|
||||
}
|
||||
|
||||
void GrCCPRGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, int maxSubdivisions) {
|
||||
void GrCCGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
|
||||
const Sk2f& p3, int maxSubdivisions) {
|
||||
SkASSERT(maxSubdivisions >= 0);
|
||||
if ((p0 == p3).allTrue()) {
|
||||
return;
|
||||
@ -561,9 +561,9 @@ void GrCCPRGeometry::appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, co
|
||||
|
||||
Sk2f tan0, tan3, c;
|
||||
if (!is_cubic_nearly_quadratic(p0, p1, p2, p3, tan0, tan3, c) && maxSubdivisions) {
|
||||
this->chopCubicAtMidTangent<&GrCCPRGeometry::appendCubicApproximation>(p0, p1, p2, p3,
|
||||
tan0, tan3,
|
||||
maxSubdivisions - 1);
|
||||
this->chopCubicAtMidTangent<&GrCCGeometry::appendCubicApproximation>(p0, p1, p2, p3,
|
||||
tan0, tan3,
|
||||
maxSubdivisions - 1);
|
||||
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(fVerbs.count() >= fCurrContourTallies.fTriangles);
|
||||
|
||||
@ -590,6 +590,6 @@ GrCCPRGeometry::PrimitiveTallies GrCCPRGeometry::endContour() {
|
||||
|
||||
fCurrContourTallies.fTriangles = SkTMax(fanSize - 2, 0);
|
||||
|
||||
SkDEBUGCODE(fBuildingContour = false;)
|
||||
SkDEBUGCODE(fBuildingContour = false);
|
||||
return fCurrContourTallies;
|
||||
}
|
@ -5,8 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrGrCCPRGeometry_DEFINED
|
||||
#define GrGrCCPRGeometry_DEFINED
|
||||
#ifndef GrGrCCGeometry_DEFINED
|
||||
#define GrGrCCGeometry_DEFINED
|
||||
|
||||
#include "SkGeometry.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
|
||||
* render. (See GrCCPRGeometry::Verb.)
|
||||
* render. (See GrCCGeometry::Verb.)
|
||||
*
|
||||
* NOTE: This must be done in device space, since an affine transformation can change whether a
|
||||
* curve is monotonic.
|
||||
*/
|
||||
class GrCCPRGeometry {
|
||||
class GrCCGeometry {
|
||||
public:
|
||||
// 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
|
||||
@ -45,7 +45,7 @@ public:
|
||||
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.
|
||||
, fVerbs(numSkVerbs * 3) {}
|
||||
|
||||
@ -94,9 +94,9 @@ private:
|
||||
inline void appendMonotonicQuadratics(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,
|
||||
const Sk2f& p2, const Sk2f& p3,
|
||||
int maxSubdivisions);
|
||||
using AppendCubicFn = void(GrCCGeometry::*)(const Sk2f& p0, const Sk2f& p1,
|
||||
const Sk2f& p2, const Sk2f& p3,
|
||||
int maxSubdivisions);
|
||||
static constexpr int kMaxSubdivionsPerCubicSection = 2;
|
||||
|
||||
template<AppendCubicFn AppendLeftRight>
|
||||
@ -125,14 +125,14 @@ private:
|
||||
SkSTArray<128, Verb, true> fVerbs;
|
||||
};
|
||||
|
||||
inline void GrCCPRGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) {
|
||||
inline void GrCCGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) {
|
||||
fTriangles += b.fTriangles;
|
||||
fQuadratics += b.fQuadratics;
|
||||
fCubics += b.fCubics;
|
||||
}
|
||||
|
||||
GrCCPRGeometry::PrimitiveTallies
|
||||
inline GrCCPRGeometry::PrimitiveTallies::operator-(const PrimitiveTallies& b) const {
|
||||
GrCCGeometry::PrimitiveTallies
|
||||
inline GrCCGeometry::PrimitiveTallies::operator-(const PrimitiveTallies& b) const {
|
||||
return {fTriangles - b.fTriangles,
|
||||
fQuadratics - b.fQuadratics,
|
||||
fCubics - b.fCubics};
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRPathProcessor.h"
|
||||
#include "GrCCPathProcessor.h"
|
||||
|
||||
#include "GrOnFlushResourceProvider.h"
|
||||
#include "GrTexture.h"
|
||||
@ -36,14 +36,14 @@ static constexpr float kOctoEdgeNorms[8 * 4] = {
|
||||
|
||||
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);
|
||||
return onFlushRP->findOrMakeStaticBuffer(kVertex_GrBufferType, sizeof(kOctoEdgeNorms),
|
||||
kOctoEdgeNorms, gVertexBufferKey);
|
||||
}
|
||||
|
||||
// Index buffer for the octagon defined above.
|
||||
static uint16_t kOctoIndices[GrCCPRPathProcessor::kPerInstanceIndexCount] = {
|
||||
static uint16_t kOctoIndices[GrCCPathProcessor::kPerInstanceIndexCount] = {
|
||||
0, 4, 2,
|
||||
0, 6, 4,
|
||||
0, 2, 1,
|
||||
@ -54,15 +54,15 @@ static uint16_t kOctoIndices[GrCCPRPathProcessor::kPerInstanceIndexCount] = {
|
||||
|
||||
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);
|
||||
return onFlushRP->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kOctoIndices),
|
||||
kOctoIndices, gIndexBufferKey);
|
||||
}
|
||||
|
||||
GrCCPRPathProcessor::GrCCPRPathProcessor(GrResourceProvider* rp, sk_sp<GrTextureProxy> atlas,
|
||||
SkPath::FillType fillType, const GrShaderCaps& shaderCaps)
|
||||
: INHERITED(kGrCCPRPathProcessor_ClassID)
|
||||
GrCCPathProcessor::GrCCPathProcessor(GrResourceProvider* rp, sk_sp<GrTextureProxy> atlas,
|
||||
SkPath::FillType fillType, const GrShaderCaps& shaderCaps)
|
||||
: INHERITED(kGrCCPathProcessor_ClassID)
|
||||
, fFillType(fillType)
|
||||
, fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) {
|
||||
@ -95,7 +95,7 @@ GrCCPRPathProcessor::GrCCPRPathProcessor(GrResourceProvider* rp, sk_sp<GrTexture
|
||||
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());
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ public:
|
||||
private:
|
||||
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
|
||||
FPCoordTransformIter&& transformIter) override {
|
||||
const GrCCPRPathProcessor& proc = primProc.cast<GrCCPRPathProcessor>();
|
||||
const GrCCPathProcessor& proc = primProc.cast<GrCCPathProcessor>();
|
||||
pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.atlas()->width(),
|
||||
1.0f / proc.atlas()->height());
|
||||
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
|
||||
@ -117,13 +117,13 @@ private:
|
||||
typedef GrGLSLGeometryProcessor INHERITED;
|
||||
};
|
||||
|
||||
GrGLSLPrimitiveProcessor* GrCCPRPathProcessor::createGLSLInstance(const GrShaderCaps&) const {
|
||||
GrGLSLPrimitiveProcessor* GrCCPathProcessor::createGLSLInstance(const GrShaderCaps&) const {
|
||||
return new GLSLPathProcessor();
|
||||
}
|
||||
|
||||
void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
using InstanceAttribs = GrCCPRPathProcessor::InstanceAttribs;
|
||||
const GrCCPRPathProcessor& proc = args.fGP.cast<GrCCPRPathProcessor>();
|
||||
using InstanceAttribs = GrCCPathProcessor::InstanceAttribs;
|
||||
const GrCCPathProcessor& proc = args.fGP.cast<GrCCPathProcessor>();
|
||||
GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
|
||||
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
|
||||
|
@ -5,8 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRPathProcessor_DEFINED
|
||||
#define GrCCPRPathProcessor_DEFINED
|
||||
#ifndef GrCCPathProcessor_DEFINED
|
||||
#define GrCCPathProcessor_DEFINED
|
||||
|
||||
#include "GrGeometryProcessor.h"
|
||||
#include "SkPath.h"
|
||||
@ -16,7 +16,7 @@ class GrOnFlushResourceProvider;
|
||||
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
|
||||
* fill rule.
|
||||
@ -24,7 +24,7 @@ class GrShaderCaps;
|
||||
* 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.
|
||||
*/
|
||||
class GrCCPRPathProcessor : public GrGeometryProcessor {
|
||||
class GrCCPathProcessor : public GrGeometryProcessor {
|
||||
public:
|
||||
static constexpr int kPerInstanceIndexCount = 6 * 3;
|
||||
|
||||
@ -55,10 +55,10 @@ public:
|
||||
static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*);
|
||||
static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*);
|
||||
|
||||
GrCCPRPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas, SkPath::FillType,
|
||||
const GrShaderCaps&);
|
||||
GrCCPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas, SkPath::FillType,
|
||||
const GrShaderCaps&);
|
||||
|
||||
const char* name() const override { return "GrCCPRPathProcessor"; }
|
||||
const char* name() const override { return "GrCCPathProcessor"; }
|
||||
const GrSurfaceProxy* atlasProxy() const { return fAtlasAccess.proxy(); }
|
||||
const GrTexture* atlas() const { return fAtlasAccess.peekTexture(); }
|
||||
SkPath::FillType fillType() const { return fFillType; }
|
@ -5,17 +5,17 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRQuadraticShader.h"
|
||||
#include "GrCCQuadraticShader.h"
|
||||
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||
using Shader = GrCCCoverageProcessor::Shader;
|
||||
|
||||
void GrCCPRQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, const char* wind,
|
||||
GeometryVars* vars) const {
|
||||
void GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, const char* wind,
|
||||
GeometryVars* vars) const {
|
||||
s->declareGlobal(fCanonicalMatrix);
|
||||
s->codeAppendf("%s = float3x3(0.0, 0, 1, "
|
||||
"0.5, 0, 1, "
|
||||
@ -33,11 +33,11 @@ void GrCCPRQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char*
|
||||
this->onEmitSetupCode(s, pts, repetitionID, vars);
|
||||
}
|
||||
|
||||
Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope,
|
||||
SkString* code, const char* position,
|
||||
const char* coverage,
|
||||
const char* /*wind*/) {
|
||||
Shader::WindHandling GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope,
|
||||
SkString* code, const char* position,
|
||||
const char* coverage,
|
||||
const char* /*wind*/) {
|
||||
SkASSERT(!coverage);
|
||||
|
||||
fXYD.reset(kFloat3_GrSLType, scope);
|
||||
@ -52,9 +52,9 @@ Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler*
|
||||
return WindHandling::kNotHandled;
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* /*repetitionID*/,
|
||||
GeometryVars* vars) const {
|
||||
void GrCCQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* /*repetitionID*/,
|
||||
GeometryVars* vars) const {
|
||||
// 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 tan1 = %s[2] - %s[1];", pts, pts);
|
||||
@ -71,30 +71,30 @@ void GrCCPRQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const
|
||||
vars->fHullVars.fAlternatePoints = "quadratic_hull";
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
void GrCCQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
fGrad.reset(kFloat2_GrSLType, scope);
|
||||
varyingHandler->addVarying("grad", &fGrad);
|
||||
code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
|
||||
OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str());
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
void GrCCQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
|
||||
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGrad.fsIn(), fGrad.fsIn());
|
||||
f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
|
||||
f->codeAppendf("%s += min(%s.z, 0);", outputCoverage, fXYD.fsIn()); // Flat closing edge.
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID,
|
||||
GeometryVars* vars) const {
|
||||
void GrCCQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID,
|
||||
GeometryVars* vars) const {
|
||||
s->codeAppendf("float2 corner = %s[%s * 2];", pts, repetitionID);
|
||||
vars->fCornerVars.fPoint = "corner";
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
void GrCCQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code) {
|
||||
fdXYDdx.reset(kFloat3_GrSLType, scope);
|
||||
varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx);
|
||||
@ -109,8 +109,8 @@ void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHa
|
||||
fEdgeDistanceEquation.c_str());
|
||||
}
|
||||
|
||||
void GrCCPRQuadraticCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
void GrCCQuadraticCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
f->codeAppendf("float x = %s.x, y = %s.y, d = %s.z;",
|
||||
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn());
|
||||
f->codeAppendf("float2x3 grad_xyd = float2x3(%s, %s);", fdXYDdx.fsIn(), fdXYDdy.fsIn());
|
@ -5,10 +5,10 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRQuadraticShader_DEFINED
|
||||
#define GrCCPRQuadraticShader_DEFINED
|
||||
#ifndef GrCCQuadraticShader_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
|
||||
@ -18,9 +18,9 @@
|
||||
* 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].
|
||||
* (Use GrCCPRGeometry.)
|
||||
* (Use GrCCGeometry.)
|
||||
*/
|
||||
class GrCCPRQuadraticShader : public GrCCPRCoverageProcessor::Shader {
|
||||
class GrCCQuadraticShader : public GrCCCoverageProcessor::Shader {
|
||||
protected:
|
||||
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||
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
|
||||
* 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,
|
||||
GeometryVars*) const 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.
|
||||
*/
|
||||
class GrCCPRQuadraticCornerShader : public GrCCPRQuadraticShader {
|
||||
class GrCCQuadraticCornerShader : public GrCCQuadraticShader {
|
||||
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||
GeometryVars*) const override;
|
||||
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
@ -5,17 +5,17 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCCPRTriangleShader.h"
|
||||
#include "GrCCTriangleShader.h"
|
||||
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||
|
||||
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||
using Shader = GrCCCoverageProcessor::Shader;
|
||||
|
||||
Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope,
|
||||
SkString* code, const char* /*position*/,
|
||||
const char* coverage, const char* wind) {
|
||||
Shader::WindHandling GrCCTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope,
|
||||
SkString* code, const char* /*position*/,
|
||||
const char* coverage, const char* wind) {
|
||||
fCoverageTimesWind.reset(kHalf_GrSLType, scope);
|
||||
if (!coverage) {
|
||||
varyingHandler->addFlatVarying("wind", &fCoverageTimesWind);
|
||||
@ -27,14 +27,14 @@ Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler*
|
||||
return WindHandling::kHandled;
|
||||
}
|
||||
|
||||
void GrCCPRTriangleShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
void GrCCTriangleShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
f->codeAppendf("%s = %s;", outputCoverage, fCoverageTimesWind.fsIn());
|
||||
}
|
||||
|
||||
void GrCCPRTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, const char* wind,
|
||||
GeometryVars* vars) const {
|
||||
void GrCCTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
|
||||
const char* repetitionID, const char* wind,
|
||||
GeometryVars* vars) const {
|
||||
s->codeAppendf("float2 corner = %s[%s];", pts, repetitionID);
|
||||
vars->fCornerVars.fPoint = "corner";
|
||||
|
||||
@ -87,10 +87,10 @@ void GrCCPRTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const
|
||||
}
|
||||
|
||||
Shader::WindHandling
|
||||
GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code,
|
||||
const char* position, const char* coverage,
|
||||
const char* /*wind*/) {
|
||||
GrCCTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
GrGLSLVarying::Scope scope, SkString* code,
|
||||
const char* position, const char* coverage,
|
||||
const char* /*wind*/) {
|
||||
SkASSERT(!coverage);
|
||||
|
||||
fCornerLocationInAABoxes.reset(kFloat2x2_GrSLType, scope);
|
||||
@ -109,8 +109,8 @@ GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||
return WindHandling::kNotHandled;
|
||||
}
|
||||
|
||||
void GrCCPRTriangleCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
void GrCCTriangleCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||
const char* outputCoverage) const {
|
||||
// By the time we reach this shader, the pixel is in the following state:
|
||||
//
|
||||
// 1. The hull shader has emitted a coverage of 1.
|
@ -5,10 +5,10 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCCPRTriangleShader_DEFINED
|
||||
#define GrCCPRTriangleShader_DEFINED
|
||||
#ifndef GrCCTriangleShader_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
|
||||
@ -16,7 +16,7 @@
|
||||
* 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.
|
||||
*/
|
||||
class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader {
|
||||
class GrCCTriangleShader : public GrCCCoverageProcessor::Shader {
|
||||
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||
const char* position, const char* coverage,
|
||||
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
|
||||
* the same time.
|
||||
*/
|
||||
class GrCCPRTriangleCornerShader : public GrCCPRCoverageProcessor::Shader {
|
||||
class GrCCTriangleCornerShader : public GrCCCoverageProcessor::Shader {
|
||||
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||
const char* wind, GeometryVars*) const override;
|
||||
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
@ -11,14 +11,14 @@
|
||||
#include "GrClip.h"
|
||||
#include "GrGpu.h"
|
||||
#include "GrGpuCommandBuffer.h"
|
||||
#include "GrOpFlushState.h"
|
||||
#include "GrRenderTargetOpList.h"
|
||||
#include "GrStyle.h"
|
||||
#include "GrTexture.h"
|
||||
#include "SkMakeUnique.h"
|
||||
#include "SkMatrix.h"
|
||||
#include "SkPathOps.h"
|
||||
#include "GrOpFlushState.h"
|
||||
#include "GrRenderTargetOpList.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrStyle.h"
|
||||
#include "ccpr/GrCCPRClipProcessor.h"
|
||||
#include "ccpr/GrCCClipProcessor.h"
|
||||
|
||||
// Shorthand for keeping line lengths under control with nested classes...
|
||||
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) {
|
||||
const GrShaderCaps& shaderCaps = *caps.shaderCaps();
|
||||
return shaderCaps.integerSupport() &&
|
||||
shaderCaps.flatInterpolationSupport() &&
|
||||
caps.instanceAttribSupport() &&
|
||||
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
|
||||
return shaderCaps.integerSupport() && shaderCaps.flatInterpolationSupport() &&
|
||||
caps.instanceAttribSupport() && GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
|
||||
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
|
||||
caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) &&
|
||||
!caps.blacklistCoverageCounting();
|
||||
}
|
||||
|
||||
sk_sp<GrCoverageCountingPathRenderer>
|
||||
GrCoverageCountingPathRenderer::CreateIfSupported(const GrCaps& caps, bool drawCachablePaths) {
|
||||
sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSupported(
|
||||
const GrCaps& caps, bool drawCachablePaths) {
|
||||
auto ccpr = IsSupported(caps) ? new GrCoverageCountingPathRenderer(drawCachablePaths) : nullptr;
|
||||
return sk_sp<GrCoverageCountingPathRenderer>(ccpr);
|
||||
}
|
||||
|
||||
GrPathRenderer::CanDrawPath
|
||||
GrCoverageCountingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
|
||||
GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
|
||||
const CanDrawPathArgs& args) const {
|
||||
if (args.fShape->hasUnstyledKey() && !fDrawCachablePaths) {
|
||||
return CanDrawPath::kNo;
|
||||
}
|
||||
|
||||
if (!args.fShape->style().isSimpleFill() ||
|
||||
args.fShape->inverseFilled() ||
|
||||
args.fViewMatrix->hasPerspective() ||
|
||||
GrAAType::kCoverage != args.fAAType) {
|
||||
if (!args.fShape->style().isSimpleFill() || args.fShape->inverseFilled() ||
|
||||
args.fViewMatrix->hasPerspective() || GrAAType::kCoverage != args.fAAType) {
|
||||
return CanDrawPath::kNo;
|
||||
}
|
||||
|
||||
@ -113,8 +109,8 @@ CCPR::DrawPathsOp::DrawPathsOp(GrCoverageCountingPathRenderer* ccpr, const DrawP
|
||||
, fOwningRTPendingPaths(nullptr) {
|
||||
SkDEBUGCODE(++fCCPR->fPendingDrawOpsCount);
|
||||
SkDEBUGCODE(fBaseInstance = -1);
|
||||
SkDEBUGCODE(fInstanceCount = 1;)
|
||||
SkDEBUGCODE(fNumSkippedInstances = 0;)
|
||||
SkDEBUGCODE(fInstanceCount = 1);
|
||||
SkDEBUGCODE(fNumSkippedInstances = 0);
|
||||
GrRenderTargetContext* const rtc = args.fRenderTargetContext;
|
||||
|
||||
SkRect devBounds;
|
||||
@ -133,7 +129,7 @@ CCPR::DrawPathsOp::DrawPathsOp(GrCoverageCountingPathRenderer* ccpr, const DrawP
|
||||
fHeadDraw.fMatrix = *args.fViewMatrix;
|
||||
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.
|
||||
// (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.
|
||||
SkASSERT(1 == fInstanceCount);
|
||||
SkASSERT(&fHeadDraw == fTailDraw);
|
||||
GrProcessorSet::Analysis analysis = fProcessors.finalize(
|
||||
fHeadDraw.fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip, false, caps,
|
||||
dstIsClamped, &fHeadDraw.fColor);
|
||||
GrProcessorSet::Analysis analysis =
|
||||
fProcessors.finalize(fHeadDraw.fColor, GrProcessorAnalysisCoverage::kSingleChannel,
|
||||
clip, false, caps, dstIsClamped, &fHeadDraw.fColor);
|
||||
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->fInstanceCount);
|
||||
|
||||
if (this->getFillType() != that->getFillType() ||
|
||||
fSRGBFlags != that->fSRGBFlags ||
|
||||
if (this->getFillType() != that->getFillType() || fSRGBFlags != that->fSRGBFlags ||
|
||||
fProcessors != that->fProcessors) {
|
||||
return false;
|
||||
}
|
||||
@ -181,7 +176,7 @@ bool CCPR::DrawPathsOp::onCombineIfPossible(GrOp* op, const GrCaps& caps) {
|
||||
|
||||
this->joinBounds(*that);
|
||||
|
||||
SkDEBUGCODE(fInstanceCount += that->fInstanceCount;)
|
||||
SkDEBUGCODE(fInstanceCount += that->fInstanceCount);
|
||||
SkDEBUGCODE(that->fInstanceCount = 0);
|
||||
return true;
|
||||
}
|
||||
@ -205,11 +200,10 @@ bool GrCoverageCountingPathRenderer::canMakeClipProcessor(const SkPath& deviceSp
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor>
|
||||
GrCoverageCountingPathRenderer::makeClipProcessor(uint32_t opListID, const SkPath& deviceSpacePath,
|
||||
const SkIRect& accessRect, int rtWidth,
|
||||
int rtHeight) {
|
||||
using MustCheckBounds = GrCCPRClipProcessor::MustCheckBounds;
|
||||
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
|
||||
uint32_t opListID, const SkPath& deviceSpacePath, const SkIRect& accessRect, int rtWidth,
|
||||
int rtHeight) {
|
||||
using MustCheckBounds = GrCCClipProcessor::MustCheckBounds;
|
||||
|
||||
SkASSERT(!fFlushing);
|
||||
SkASSERT(this->canMakeClipProcessor(deviceSpacePath));
|
||||
@ -223,37 +217,39 @@ GrCoverageCountingPathRenderer::makeClipProcessor(uint32_t opListID, const SkPat
|
||||
}
|
||||
|
||||
bool mustCheckBounds = !clipPath.pathDevIBounds().contains(accessRect);
|
||||
return skstd::make_unique<GrCCPRClipProcessor>(&clipPath, MustCheckBounds(mustCheckBounds),
|
||||
deviceSpacePath.getFillType());
|
||||
return skstd::make_unique<GrCCClipProcessor>(&clipPath, MustCheckBounds(mustCheckBounds),
|
||||
deviceSpacePath.getFillType());
|
||||
}
|
||||
|
||||
void CCPR::ClipPath::init(const SkPath& deviceSpacePath, const SkIRect& accessRect, int rtWidth,
|
||||
int rtHeight) {
|
||||
SkASSERT(this->isUninitialized());
|
||||
|
||||
fAtlasLazyProxy = GrSurfaceProxy::MakeLazy([this](GrResourceProvider* resourceProvider,
|
||||
GrSurfaceOrigin* outOrigin) {
|
||||
SkASSERT(fHasAtlas);
|
||||
SkASSERT(!fHasAtlasTransform);
|
||||
fAtlasLazyProxy = GrSurfaceProxy::MakeLazy(
|
||||
[this](GrResourceProvider* resourceProvider, GrSurfaceOrigin* outOrigin) {
|
||||
SkASSERT(fHasAtlas);
|
||||
SkASSERT(!fHasAtlasTransform);
|
||||
|
||||
GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr;
|
||||
if (!textureProxy || !textureProxy->instantiate(resourceProvider)) {
|
||||
fAtlasScale = fAtlasTranslate = {0, 0};
|
||||
SkDEBUGCODE(fHasAtlasTransform = true);
|
||||
return sk_sp<GrTexture>();
|
||||
}
|
||||
GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr;
|
||||
if (!textureProxy || !textureProxy->instantiate(resourceProvider)) {
|
||||
fAtlasScale = fAtlasTranslate = {0, 0};
|
||||
SkDEBUGCODE(fHasAtlasTransform = true);
|
||||
return sk_sp<GrTexture>();
|
||||
}
|
||||
|
||||
fAtlasScale = {1.f / textureProxy->width(), 1.f / textureProxy->height()};
|
||||
fAtlasTranslate = {fAtlasOffsetX * fAtlasScale.x(), fAtlasOffsetY * fAtlasScale.y()};
|
||||
if (kBottomLeft_GrSurfaceOrigin == textureProxy->origin()) {
|
||||
fAtlasScale.fY = -fAtlasScale.y();
|
||||
fAtlasTranslate.fY = 1 - fAtlasTranslate.y();
|
||||
}
|
||||
SkDEBUGCODE(fHasAtlasTransform = true);
|
||||
fAtlasScale = {1.f / textureProxy->width(), 1.f / textureProxy->height()};
|
||||
fAtlasTranslate = {fAtlasOffsetX * fAtlasScale.x(),
|
||||
fAtlasOffsetY * fAtlasScale.y()};
|
||||
if (kBottomLeft_GrSurfaceOrigin == textureProxy->origin()) {
|
||||
fAtlasScale.fY = -fAtlasScale.y();
|
||||
fAtlasTranslate.fY = 1 - fAtlasTranslate.y();
|
||||
}
|
||||
SkDEBUGCODE(fHasAtlasTransform = true);
|
||||
|
||||
*outOrigin = textureProxy->origin();
|
||||
return sk_ref_sp(textureProxy->priv().peekTexture());
|
||||
}, GrSurfaceProxy::Renderable::kYes, kAlpha_half_GrPixelConfig);
|
||||
*outOrigin = textureProxy->origin();
|
||||
return sk_ref_sp(textureProxy->priv().peekTexture());
|
||||
},
|
||||
GrSurfaceProxy::Renderable::kYes, kAlpha_half_GrPixelConfig);
|
||||
|
||||
const SkRect& pathDevBounds = deviceSpacePath.getBounds();
|
||||
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,
|
||||
const uint32_t* opListIDs, int numOpListIDs,
|
||||
SkTArray<sk_sp<GrRenderTargetContext>>* results) {
|
||||
using PathInstance = GrCCPRPathProcessor::Instance;
|
||||
using PathInstance = GrCCPathProcessor::Instance;
|
||||
|
||||
SkASSERT(!fFlushing);
|
||||
SkASSERT(!fPerFlushIndexBuffer);
|
||||
SkASSERT(!fPerFlushVertexBuffer);
|
||||
SkASSERT(!fPerFlushInstanceBuffer);
|
||||
SkASSERT(fPerFlushAtlases.empty());
|
||||
SkDEBUGCODE(fFlushing = true;)
|
||||
SkDEBUGCODE(fFlushing = true);
|
||||
|
||||
if (fRTPendingPathsMap.empty()) {
|
||||
return; // Nothing to draw.
|
||||
return; // Nothing to draw.
|
||||
}
|
||||
|
||||
fPerFlushResourcesAreValid = false;
|
||||
|
||||
// Count the paths that are being flushed.
|
||||
int maxTotalPaths = 0, maxPathPoints = 0, numSkPoints = 0, numSkVerbs = 0;
|
||||
SkDEBUGCODE(int numClipPaths = 0;)
|
||||
SkDEBUGCODE(int numClipPaths = 0);
|
||||
for (int i = 0; i < numOpListIDs; ++i) {
|
||||
auto it = fRTPendingPathsMap.find(opListIDs[i]);
|
||||
if (fRTPendingPathsMap.end() == it) {
|
||||
@ -318,24 +314,24 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
}
|
||||
|
||||
if (!maxTotalPaths) {
|
||||
return; // Nothing to draw.
|
||||
return; // Nothing to draw.
|
||||
}
|
||||
|
||||
// Allocate GPU buffers.
|
||||
fPerFlushIndexBuffer = GrCCPRPathProcessor::FindIndexBuffer(onFlushRP);
|
||||
fPerFlushIndexBuffer = GrCCPathProcessor::FindIndexBuffer(onFlushRP);
|
||||
if (!fPerFlushIndexBuffer) {
|
||||
SkDebugf("WARNING: failed to allocate ccpr path index buffer.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fPerFlushVertexBuffer = GrCCPRPathProcessor::FindVertexBuffer(onFlushRP);
|
||||
fPerFlushVertexBuffer = GrCCPathProcessor::FindVertexBuffer(onFlushRP);
|
||||
if (!fPerFlushVertexBuffer) {
|
||||
SkDebugf("WARNING: failed to allocate ccpr path vertex buffer.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fPerFlushInstanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType,
|
||||
maxTotalPaths * sizeof(PathInstance));
|
||||
fPerFlushInstanceBuffer =
|
||||
onFlushRP->makeBuffer(kVertex_GrBufferType, maxTotalPaths * sizeof(PathInstance));
|
||||
if (!fPerFlushInstanceBuffer) {
|
||||
SkDebugf("WARNING: failed to allocate path instance buffer. No paths will be drawn.\n");
|
||||
return;
|
||||
@ -345,8 +341,8 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
SkASSERT(pathInstanceData);
|
||||
int pathInstanceIdx = 0;
|
||||
|
||||
GrCCPRCoverageOpsBuilder atlasOpsBuilder(maxTotalPaths, maxPathPoints, numSkPoints, numSkVerbs);
|
||||
SkDEBUGCODE(int skippedTotalPaths = 0;)
|
||||
GrCCCoverageOpsBuilder atlasOpsBuilder(maxTotalPaths, maxPathPoints, numSkPoints, numSkVerbs);
|
||||
SkDEBUGCODE(int skippedTotalPaths = 0);
|
||||
|
||||
// Allocate atlas(es) and fill out GPU instance buffers.
|
||||
for (int i = 0; i < numOpListIDs; ++i) {
|
||||
@ -363,7 +359,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
pathInstanceIdx = op->setupResources(onFlushRP, &atlasOpsBuilder, pathInstanceData,
|
||||
pathInstanceIdx);
|
||||
drawOpsIter.next();
|
||||
SkDEBUGCODE(skippedTotalPaths += op->numSkippedInstances_debugOnly();)
|
||||
SkDEBUGCODE(skippedTotalPaths += op->numSkippedInstances_debugOnly());
|
||||
}
|
||||
|
||||
for (auto& clipsIter : rtPendingPaths.fClipPaths) {
|
||||
@ -379,7 +375,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
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)) {
|
||||
SkDebugf("WARNING: failed to allocate ccpr atlas buffers. No paths will be drawn.\n");
|
||||
return;
|
||||
@ -387,12 +383,12 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
SkASSERT(atlasOps.count() == fPerFlushAtlases.count());
|
||||
|
||||
// Draw the coverage ops into their respective atlases.
|
||||
GrTAllocator<GrCCPRAtlas>::Iter atlasIter(&fPerFlushAtlases);
|
||||
for (std::unique_ptr<GrCCPRCoverageOp>& atlasOp : atlasOps) {
|
||||
GrTAllocator<GrCCAtlas>::Iter atlasIter(&fPerFlushAtlases);
|
||||
for (std::unique_ptr<GrCCCoverageOp>& atlasOp : atlasOps) {
|
||||
SkAssertResult(atlasIter.next());
|
||||
GrCCPRAtlas* atlas = atlasIter.get();
|
||||
SkASSERT(atlasOp->bounds() == SkRect::MakeIWH(atlas->drawBounds().width(),
|
||||
atlas->drawBounds().height()));
|
||||
GrCCAtlas* atlas = atlasIter.get();
|
||||
SkASSERT(atlasOp->bounds() ==
|
||||
SkRect::MakeIWH(atlas->drawBounds().width(), atlas->drawBounds().height()));
|
||||
if (auto rtc = atlas->finalize(onFlushRP, std::move(atlasOp))) {
|
||||
results->push_back(std::move(rtc));
|
||||
}
|
||||
@ -403,10 +399,10 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
}
|
||||
|
||||
int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
|
||||
GrCCPRCoverageOpsBuilder* atlasOpsBuilder,
|
||||
GrCCPRPathProcessor::Instance* pathInstanceData,
|
||||
GrCCCoverageOpsBuilder* atlasOpsBuilder,
|
||||
GrCCPathProcessor::Instance* pathInstanceData,
|
||||
int pathInstanceIdx) {
|
||||
const GrCCPRAtlas* currentAtlas = nullptr;
|
||||
const GrCCAtlas* currentAtlas = nullptr;
|
||||
SkASSERT(fInstanceCount > 0);
|
||||
SkASSERT(-1 == fBaseInstance);
|
||||
fBaseInstance = pathInstanceIdx;
|
||||
@ -422,9 +418,8 @@ int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
|
||||
devBounds.roundOut(&devIBounds);
|
||||
|
||||
int16_t offsetX, offsetY;
|
||||
GrCCPRAtlas* atlas = fCCPR->placeParsedPathInAtlas(onFlushRP, draw->fClipIBounds,
|
||||
devIBounds, &offsetX, &offsetY,
|
||||
atlasOpsBuilder);
|
||||
GrCCAtlas* atlas = fCCPR->placeParsedPathInAtlas(onFlushRP, draw->fClipIBounds, devIBounds,
|
||||
&offsetX, &offsetY, atlasOpsBuilder);
|
||||
if (!atlas) {
|
||||
SkDEBUGCODE(++fNumSkippedInstances);
|
||||
continue;
|
||||
@ -438,13 +433,12 @@ int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
|
||||
|
||||
const SkMatrix& m = draw->fMatrix;
|
||||
pathInstanceData[pathInstanceIdx++] = {
|
||||
devBounds,
|
||||
devBounds45,
|
||||
{{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()}},
|
||||
{{m.getTranslateX(), m.getTranslateY()}},
|
||||
{{offsetX, offsetY}},
|
||||
draw->fColor
|
||||
};
|
||||
devBounds,
|
||||
devBounds45,
|
||||
{{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()}},
|
||||
{{m.getTranslateX(), m.getTranslateY()}},
|
||||
{{offsetX, offsetY}},
|
||||
draw->fColor};
|
||||
}
|
||||
|
||||
SkASSERT(pathInstanceIdx == fBaseInstance + fInstanceCount - fNumSkippedInstances);
|
||||
@ -457,7 +451,7 @@ int CCPR::DrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP,
|
||||
|
||||
void CCPR::ClipPath::placePathInAtlas(GrCoverageCountingPathRenderer* ccpr,
|
||||
GrOnFlushResourceProvider* onFlushRP,
|
||||
GrCCPRCoverageOpsBuilder* atlasOpsBuilder) {
|
||||
GrCCCoverageOpsBuilder* atlasOpsBuilder) {
|
||||
SkASSERT(!this->isUninitialized());
|
||||
SkASSERT(!fHasAtlas);
|
||||
atlasOpsBuilder->parseDeviceSpacePath(fDeviceSpacePath);
|
||||
@ -466,14 +460,14 @@ void CCPR::ClipPath::placePathInAtlas(GrCoverageCountingPathRenderer* ccpr,
|
||||
SkDEBUGCODE(fHasAtlas = true);
|
||||
}
|
||||
|
||||
GrCCPRAtlas*
|
||||
GrCoverageCountingPathRenderer::placeParsedPathInAtlas(GrOnFlushResourceProvider* onFlushRP,
|
||||
const SkIRect& clipIBounds,
|
||||
const SkIRect& pathIBounds,
|
||||
int16_t* atlasOffsetX,
|
||||
int16_t* atlasOffsetY,
|
||||
GrCCPRCoverageOpsBuilder* atlasOpsBuilder) {
|
||||
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
|
||||
GrCCAtlas* GrCoverageCountingPathRenderer::placeParsedPathInAtlas(
|
||||
GrOnFlushResourceProvider* onFlushRP,
|
||||
const SkIRect& clipIBounds,
|
||||
const SkIRect& pathIBounds,
|
||||
int16_t* atlasOffsetX,
|
||||
int16_t* atlasOffsetY,
|
||||
GrCCCoverageOpsBuilder* atlasOpsBuilder) {
|
||||
using ScissorMode = GrCCCoverageOpsBuilder::ScissorMode;
|
||||
|
||||
ScissorMode scissorMode;
|
||||
SkIRect clippedPathIBounds;
|
||||
@ -509,10 +503,10 @@ void CCPR::DrawPathsOp::onExecute(GrOpFlushState* flushState) {
|
||||
SkASSERT(flushState->rtCommandBuffer());
|
||||
|
||||
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;
|
||||
initArgs.fFlags = fSRGBFlags;
|
||||
@ -529,16 +523,16 @@ void CCPR::DrawPathsOp::onExecute(GrOpFlushState* flushState) {
|
||||
SkASSERT(batch.fEndInstanceIdx > baseInstance);
|
||||
|
||||
if (!batch.fAtlas->textureProxy()) {
|
||||
continue; // Atlas failed to allocate.
|
||||
continue; // Atlas failed to allocate.
|
||||
}
|
||||
|
||||
GrCCPRPathProcessor coverProc(flushState->resourceProvider(),
|
||||
sk_ref_sp(batch.fAtlas->textureProxy()), this->getFillType(),
|
||||
*flushState->gpu()->caps()->shaderCaps());
|
||||
GrCCPathProcessor coverProc(flushState->resourceProvider(),
|
||||
sk_ref_sp(batch.fAtlas->textureProxy()), this->getFillType(),
|
||||
*flushState->gpu()->caps()->shaderCaps());
|
||||
|
||||
GrMesh mesh(GrPrimitiveType::kTriangles);
|
||||
mesh.setIndexedInstanced(fCCPR->fPerFlushIndexBuffer.get(),
|
||||
GrCCPRPathProcessor::kPerInstanceIndexCount,
|
||||
GrCCPathProcessor::kPerInstanceIndexCount,
|
||||
fCCPR->fPerFlushInstanceBuffer.get(),
|
||||
batch.fEndInstanceIdx - baseInstance, baseInstance);
|
||||
mesh.setVertexData(fCCPR->fPerFlushVertexBuffer.get());
|
||||
@ -560,5 +554,5 @@ void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken, const uint
|
||||
for (int i = 0; i < numOpListIDs; ++i) {
|
||||
fRTPendingPathsMap.erase(opListIDs[i]);
|
||||
}
|
||||
SkDEBUGCODE(fFlushing = false;)
|
||||
SkDEBUGCODE(fFlushing = false);
|
||||
}
|
||||
|
@ -8,27 +8,24 @@
|
||||
#ifndef GrCoverageCountingPathRenderer_DEFINED
|
||||
#define GrCoverageCountingPathRenderer_DEFINED
|
||||
|
||||
#include <map>
|
||||
#include "GrAllocator.h"
|
||||
#include "GrOnFlushResourceProvider.h"
|
||||
#include "GrPathRenderer.h"
|
||||
#include "SkTInternalLList.h"
|
||||
#include "ccpr/GrCCPRAtlas.h"
|
||||
#include "ccpr/GrCCPRCoverageOp.h"
|
||||
#include "ccpr/GrCCPRPathProcessor.h"
|
||||
#include "ccpr/GrCCAtlas.h"
|
||||
#include "ccpr/GrCCCoverageOp.h"
|
||||
#include "ccpr/GrCCPathProcessor.h"
|
||||
#include "ops/GrDrawOp.h"
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* 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
|
||||
* flush, it compiles GPU buffers and renders a "coverage count atlas" for the upcoming paths.
|
||||
*/
|
||||
class GrCoverageCountingPathRenderer
|
||||
: public GrPathRenderer
|
||||
, public GrOnFlushCallbackObject {
|
||||
|
||||
class GrCoverageCountingPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject {
|
||||
struct RTPendingPaths;
|
||||
|
||||
public:
|
||||
@ -52,7 +49,7 @@ public:
|
||||
DrawPathsOp(GrCoverageCountingPathRenderer*, const DrawPathArgs&, GrColor);
|
||||
~DrawPathsOp() override;
|
||||
|
||||
struct SingleDraw {
|
||||
struct SingleDraw {
|
||||
SkIRect fClipIBounds;
|
||||
SkMatrix fMatrix;
|
||||
SkPath fPath;
|
||||
@ -80,8 +77,8 @@ public:
|
||||
void onPrepare(GrOpFlushState*) override {}
|
||||
void onExecute(GrOpFlushState*) override;
|
||||
|
||||
int setupResources(GrOnFlushResourceProvider*, GrCCPRCoverageOpsBuilder*,
|
||||
GrCCPRPathProcessor::Instance* pathInstanceData, int pathInstanceIdx);
|
||||
int setupResources(GrOnFlushResourceProvider*, GrCCCoverageOpsBuilder*,
|
||||
GrCCPathProcessor::Instance* pathInstanceData, int pathInstanceIdx);
|
||||
|
||||
private:
|
||||
SkPath::FillType getFillType() const {
|
||||
@ -90,11 +87,11 @@ public:
|
||||
}
|
||||
|
||||
struct AtlasBatch {
|
||||
const GrCCPRAtlas* fAtlas;
|
||||
const GrCCAtlas* fAtlas;
|
||||
int fEndInstanceIdx;
|
||||
};
|
||||
|
||||
void addAtlasBatch(const GrCCPRAtlas* atlas, int endInstanceIdx) {
|
||||
void addAtlasBatch(const GrCCAtlas* atlas, int endInstanceIdx) {
|
||||
SkASSERT(endInstanceIdx > fBaseInstance);
|
||||
SkASSERT(fAtlasBatches.empty() ||
|
||||
endInstanceIdx > fAtlasBatches.back().fEndInstanceIdx);
|
||||
@ -108,8 +105,8 @@ public:
|
||||
SingleDraw* fTailDraw;
|
||||
RTPendingPaths* fOwningRTPendingPaths;
|
||||
int fBaseInstance;
|
||||
SkDEBUGCODE(int fInstanceCount;)
|
||||
SkDEBUGCODE(int fNumSkippedInstances;)
|
||||
SkDEBUGCODE(int fInstanceCount);
|
||||
SkDEBUGCODE(int fNumSkippedInstances);
|
||||
SkSTArray<1, AtlasBatch, true> fAtlasBatches;
|
||||
|
||||
typedef GrDrawOp INHERITED;
|
||||
@ -158,9 +155,12 @@ public:
|
||||
return fPathDevIBounds;
|
||||
}
|
||||
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 {
|
||||
SkASSERT(fHasAtlasTransform);
|
||||
return fAtlasTranslate;
|
||||
@ -172,7 +172,7 @@ public:
|
||||
SkIRect fPathDevIBounds;
|
||||
SkIRect fAccessRect;
|
||||
|
||||
const GrCCPRAtlas* fAtlas = nullptr;
|
||||
const GrCCAtlas* fAtlas = nullptr;
|
||||
int16_t fAtlasOffsetX;
|
||||
int16_t fAtlasOffsetY;
|
||||
SkDEBUGCODE(bool fHasAtlas = false);
|
||||
@ -186,8 +186,8 @@ public:
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> makeClipProcessor(uint32_t oplistID,
|
||||
const SkPath& deviceSpacePath,
|
||||
const SkIRect& accessRect,
|
||||
int rtWidth, int rtHeight);
|
||||
const SkIRect& accessRect, int rtWidth,
|
||||
int rtHeight);
|
||||
|
||||
// GrOnFlushCallbackObject overrides.
|
||||
void preFlush(GrOnFlushResourceProvider*, const uint32_t* opListIDs, int numOpListIDs,
|
||||
@ -198,9 +198,9 @@ private:
|
||||
GrCoverageCountingPathRenderer(bool drawCachablePaths)
|
||||
: fDrawCachablePaths(drawCachablePaths) {}
|
||||
|
||||
GrCCPRAtlas* placeParsedPathInAtlas(GrOnFlushResourceProvider*, const SkIRect& accessRect,
|
||||
const SkIRect& pathIBounds, int16_t* atlasOffsetX,
|
||||
int16_t* atlasOffsetY, GrCCPRCoverageOpsBuilder*);
|
||||
GrCCAtlas* placeParsedPathInAtlas(GrOnFlushResourceProvider*, const SkIRect& accessRect,
|
||||
const SkIRect& pathIBounds, int16_t* atlasOffsetX,
|
||||
int16_t* atlasOffsetY, GrCCCoverageOpsBuilder*);
|
||||
|
||||
struct RTPendingPaths {
|
||||
~RTPendingPaths() {
|
||||
@ -215,14 +215,14 @@ private:
|
||||
|
||||
// A map from render target ID to the individual render target's pending paths.
|
||||
std::map<uint32_t, RTPendingPaths> fRTPendingPathsMap;
|
||||
SkDEBUGCODE(int fPendingDrawOpsCount = 0;)
|
||||
SkDEBUGCODE(int fPendingDrawOpsCount = 0);
|
||||
|
||||
sk_sp<const GrBuffer> fPerFlushIndexBuffer;
|
||||
sk_sp<const GrBuffer> fPerFlushVertexBuffer;
|
||||
sk_sp<GrBuffer> fPerFlushInstanceBuffer;
|
||||
GrSTAllocator<4, GrCCPRAtlas> fPerFlushAtlases;
|
||||
GrSTAllocator<4, GrCCAtlas> fPerFlushAtlases;
|
||||
bool fPerFlushResourcesAreValid;
|
||||
SkDEBUGCODE(bool fFlushing = false;)
|
||||
SkDEBUGCODE(bool fFlushing = false);
|
||||
|
||||
const bool fDrawCachablePaths;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user