Revert "Revert "Add a new non-AA rect op that does not inherit from GrLegacyMeshDrawOp.""

This reverts commit 0f35332796.

Bug: skia:
Change-Id: I8def56fa55bfc70de4386bf0b7a7867f6e91c173
Reviewed-on: https://skia-review.googlesource.com/15251
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2017-05-03 17:06:09 -04:00 committed by Skia Commit-Bot
parent cc413b0cf1
commit 6d4b65e9da
12 changed files with 508 additions and 20 deletions

View File

@ -261,6 +261,8 @@ skia_gpu_sources = [
"$_src/gpu/ops/GrMSAAPathRenderer.h",
"$_src/gpu/ops/GrNonAAFillRectOp.h",
"$_src/gpu/ops/GrNonAAFillRectOp.cpp",
"$_src/gpu/ops/GrNewNonAAFillRectOp.h",
"$_src/gpu/ops/GrNewNonAAFillRectOp.cpp",
"$_src/gpu/ops/GrNonAAFillRectPerspectiveOp.cpp",
"$_src/gpu/ops/GrNonAAStrokeRectOp.cpp",
"$_src/gpu/ops/GrNonAAStrokeRectOp.h",
@ -278,6 +280,7 @@ skia_gpu_sources = [
"$_src/gpu/ops/GrSemaphoreOp.h",
"$_src/gpu/ops/GrShadowRRectOp.cpp",
"$_src/gpu/ops/GrShadowRRectOp.h",
"$_src/gpu/ops/GrSimpleMeshDrawOpHelper.h",
"$_src/gpu/ops/GrSmallPathRenderer.cpp",
"$_src/gpu/ops/GrSmallPathRenderer.h",
"$_src/gpu/ops/GrStencilAndCoverPathRenderer.cpp",

View File

@ -10,6 +10,7 @@
#include "GrBufferAllocPool.h"
#include "GrGpu.h"
#include "SkArenaAlloc.h"
#include "ops/GrMeshDrawOp.h"
class GrGpuCommandBuffer;
@ -94,6 +95,7 @@ public:
void reset() {
fVertexPool.reset();
fIndexPool.reset();
fPipelines.reset();
}
/** Additional data required on a per-op basis when executing GrDrawOps. */
@ -110,16 +112,22 @@ public:
return *fOpArgs;
}
template <typename... Args>
GrPipeline* allocPipeline(Args... args) {
return fPipelines.make<GrPipeline>(std::forward<Args>(args)...);
}
private:
GrGpu* fGpu;
GrResourceProvider* fResourceProvider;
GrGpuCommandBuffer* fCommandBuffer;
GrVertexBufferAllocPool fVertexPool;
GrIndexBufferAllocPool fIndexPool;
SkSTArray<4, GrDrawOp::DeferredUploadFn> fAsapUploads;
GrDrawOpUploadToken fLastIssuedToken;
GrDrawOpUploadToken fLastFlushedToken;
DrawOpArgs* fOpArgs;
GrGpu* fGpu;
GrResourceProvider* fResourceProvider;
GrGpuCommandBuffer* fCommandBuffer;
GrVertexBufferAllocPool fVertexPool;
GrIndexBufferAllocPool fIndexPool;
SkSTArray<4, GrDrawOp::DeferredUploadFn> fAsapUploads;
GrDrawOpUploadToken fLastIssuedToken;
GrDrawOpUploadToken fLastFlushedToken;
DrawOpArgs* fOpArgs;
SkArenaAlloc fPipelines{sizeof(GrPipeline) * 100};
};
/**
@ -182,6 +190,7 @@ public:
protected:
GrDrawOp* op() { return fOp; }
GrOpFlushState* state() { return fState; }
const GrOpFlushState* state() const { return fState; }
private:
GrOpFlushState* fState;
@ -211,6 +220,19 @@ public:
this->state()->putBackVertexSpace(vertices * vertexStride);
}
GrRenderTarget* renderTarget() const { return this->state()->drawOpArgs().fRenderTarget; }
const GrAppliedClip* clip() const { return this->state()->drawOpArgs().fAppliedClip; }
const GrXferProcessor::DstTexture& dstTexture() const {
return this->state()->drawOpArgs().fDstTexture;
}
template <typename... Args>
GrPipeline* allocPipeline(Args... args) {
return this->state()->allocPipeline(std::forward<Args>(args)...);
}
private:
GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); }
typedef GrDrawOp::Target INHERITED;

View File

@ -12,11 +12,11 @@
#include "effects/GrSimpleTextureEffect.h"
void GrPaint::setPorterDuffXPFactory(SkBlendMode mode) {
fXPFactory = GrPorterDuffXPFactory::Get(mode);
this->setXPFactory(GrPorterDuffXPFactory::Get(mode));
}
void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {
fXPFactory = GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
this->setXPFactory(GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage));
}
void GrPaint::addColorTextureProcessor(GrResourceProvider* resourceProvider,

View File

@ -79,11 +79,14 @@ public:
* as such (with linear blending), and sRGB inputs to be filtered and decoded correctly.
*/
void setGammaCorrect(bool gammaCorrect) {
setDisableOutputConversionToSRGB(!gammaCorrect);
setAllowSRGBInputs(gammaCorrect);
this->setDisableOutputConversionToSRGB(!gammaCorrect);
this->setAllowSRGBInputs(gammaCorrect);
}
void setXPFactory(const GrXPFactory* xpFactory) { fXPFactory = xpFactory; }
void setXPFactory(const GrXPFactory* xpFactory) {
fXPFactory = xpFactory;
fTrivial &= !SkToBool(xpFactory);
}
void setPorterDuffXPFactory(SkBlendMode mode);
@ -96,6 +99,7 @@ public:
SkASSERT(fp);
fUsesDistanceVectorField |= fp->usesDistanceVectorField();
fColorFragmentProcessors.push_back(std::move(fp));
fTrivial = false;
}
/**
@ -105,6 +109,7 @@ public:
SkASSERT(fp);
fUsesDistanceVectorField |= fp->usesDistanceVectorField();
fCoverageFragmentProcessors.push_back(std::move(fp));
fTrivial = false;
}
/**
@ -143,6 +148,12 @@ public:
*/
bool isConstantBlendedColor(GrColor* constantColor) const;
/**
* A trivial paint is one that uses src-over and has no fragment processors.
* It may have variable sRGB settings.
**/
bool isTrivial() const { return fTrivial; }
private:
template <bool> class MoveOrImpl;
@ -172,6 +183,7 @@ private:
bool fDisableOutputConversionToSRGB = false;
bool fAllowSRGBInputs = false;
bool fUsesDistanceVectorField = false;
bool fTrivial = true;
GrColor4f fColor = GrColor4f::OpaqueWhite();
};

View File

@ -90,6 +90,8 @@ public:
**/
GrPipeline(GrRenderTarget*, SkBlendMode);
GrPipeline(const InitArgs& args) { this->init(args); }
/** (Re)initializes a pipeline. After initialization the pipeline can be used. */
void init(const InitArgs&);

View File

@ -11,6 +11,8 @@
#include "GrXferProcessor.h"
#include "effects/GrPorterDuffXferProcessor.h"
const GrProcessorSet GrProcessorSet::gEmpty{GrProcessorSet::Empty::kEmpty};
GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
fFlags = 0;
if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {

View File

@ -18,6 +18,10 @@ class GrXferProcessor;
class GrXPFactory;
class GrProcessorSet : private SkNoncopyable {
private:
// Arbitrary constructor arg for empty set and analysis
enum class Empty { kEmpty };
public:
GrProcessorSet(GrPaint&& paint);
@ -80,6 +84,14 @@ public:
}
private:
constexpr Analysis(Empty)
: fUsesLocalCoords(false)
, fCompatibleWithCoverageAsAlpha(true)
, fRequiresDstTexture(false)
, fCanCombineOverlappedStencilAndCover(true)
, fRequiresBarrierBetweenOverlappingDraws(false)
, fIsInitialized(true)
, fInputColorType(kOriginal_InputColorType) {}
enum InputColorType : uint32_t {
kOriginal_InputColorType,
kOverridden_InputColorType,
@ -122,7 +134,13 @@ public:
bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }
static const GrProcessorSet& EmptySet() { return gEmpty; }
static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); }
private:
GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {}
static const GrProcessorSet gEmpty;
// This absurdly large limit allows Analysis and this to pack fields together.
static constexpr int kMaxColorProcessors = UINT8_MAX;
@ -130,6 +148,7 @@ private:
union XP {
XP(const GrXPFactory* factory) : fFactory(factory) {}
XP(const GrXferProcessor* processor) : fProcessor(processor) {}
const GrXPFactory* fFactory;
const GrXferProcessor* fProcessor;
};
@ -141,7 +160,7 @@ private:
SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
XP fXP;
uint8_t fColorFragmentProcessorCnt;
uint8_t fColorFragmentProcessorCnt = 0;
uint8_t fFragmentProcessorOffset = 0;
uint8_t fFlags;
};

View File

@ -6,6 +6,7 @@
*/
#include "GrRenderTargetContext.h"
#include "../private/GrAuditTrail.h"
#include "GrAppliedClip.h"
#include "GrColor.h"
#include "GrContextPriv.h"
@ -27,10 +28,11 @@
#include "ops/GrClearOp.h"
#include "ops/GrClearStencilClipOp.h"
#include "ops/GrDiscardOp.h"
#include "ops/GrDrawOp.h"
#include "ops/GrDrawAtlasOp.h"
#include "ops/GrDrawOp.h"
#include "ops/GrDrawVerticesOp.h"
#include "ops/GrLatticeOp.h"
#include "ops/GrNewNonAAFillRectOp.h"
#include "ops/GrOp.h"
#include "ops/GrOvalOpFactory.h"
#include "ops/GrRectOpFactory.h"
@ -39,7 +41,6 @@
#include "ops/GrStencilPathOp.h"
#include "text/GrAtlasTextContext.h"
#include "text/GrStencilAndCoverTextContext.h"
#include "../private/GrAuditTrail.h"
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
#define ASSERT_SINGLE_OWNER \
@ -1275,7 +1276,13 @@ void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
const GrUserStencilSettings* ss,
GrAAType hwOrNoneAAType) {
SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
SkASSERT(GrAAType::kNone == hwOrNoneAAType || this->isStencilBufferMultisampled());
if (!viewMatrix.hasPerspective() && (!localMatrix || !localMatrix->hasPerspective())) {
std::unique_ptr<GrDrawOp> op = GrNewNonAAFillRectOp::Make(
std::move(paint), viewMatrix, rect, localRect, localMatrix, hwOrNoneAAType, ss);
this->addDrawOp(clip, std::move(op));
return;
}
std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
paint.getColor(), viewMatrix, rect, localRect, localMatrix);
GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);

View File

@ -67,8 +67,6 @@ void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int qu
}
void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
SkASSERT(!state->drawOpArgs().fAppliedClip);
SkASSERT(!state->drawOpArgs().fDstTexture.texture());
int currUploadIdx = 0;
int currMeshIdx = 0;

View File

@ -0,0 +1,198 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrNewNonAAFillRectOp.h"
#include "GrAppliedClip.h"
#include "GrColor.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrMeshDrawOp.h"
#include "GrOpFlushState.h"
#include "GrPrimitiveProcessor.h"
#include "GrQuad.h"
#include "GrResourceProvider.h"
#include "GrSimpleMeshDrawOpHelper.h"
#include "SkMatrixPriv.h"
static const int kVertsPerRect = 4;
static const int kIndicesPerRect = 6;
/** We always use per-vertex colors so that rects can be combined across color changes. Sometimes
we have explicit local coords and sometimes not. We *could* always provide explicit local
coords and just duplicate the positions when the caller hasn't provided a local coord rect,
but we haven't seen a use case which frequently switches between local rect and no local
rect draws.
The vertex attrib order is always pos, color, [local coords].
*/
static sk_sp<GrGeometryProcessor> make_gp() {
using namespace GrDefaultGeoProcFactory;
return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
LocalCoords::kHasExplicit_Type, SkMatrix::I());
}
static void tesselate(intptr_t vertices,
size_t vertexStride,
GrColor color,
const SkMatrix* viewMatrix,
const SkRect& rect,
const GrQuad* localQuad) {
SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
positions->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
if (viewMatrix) {
SkMatrixPriv::MapPointsWithStride(*viewMatrix, positions, vertexStride, kVertsPerRect);
}
// Setup local coords
// TODO we should only do this if local coords are being read
if (localQuad) {
static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
for (int i = 0; i < kVertsPerRect; i++) {
SkPoint* coords =
reinterpret_cast<SkPoint*>(vertices + kLocalOffset + i * vertexStride);
*coords = localQuad->point(i);
}
}
static const int kColorOffset = sizeof(SkPoint);
GrColor* vertColor = reinterpret_cast<GrColor*>(vertices + kColorOffset);
for (int j = 0; j < 4; ++j) {
*vertColor = color;
vertColor = (GrColor*)((intptr_t)vertColor + vertexStride);
}
}
class NewNonAAFillRectOp final : public GrMeshDrawOp {
private:
using Helper = GrSimpleMeshDrawOpHelperWithStencil;
public:
DEFINE_OP_CLASS_ID
NewNonAAFillRectOp() = delete;
static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
const SkRect& rect, const SkRect* localRect,
const SkMatrix* localMatrix, GrAAType aaType,
const GrUserStencilSettings* stencilSettings) {
SkASSERT(GrAAType::kCoverage != aaType);
return Helper::FactoryHelper<NewNonAAFillRectOp>(std::move(paint), viewMatrix, rect,
localRect, localMatrix, aaType,
stencilSettings);
}
const char* name() const override { return "NonAAFillRectOp"; }
SkString dumpInfo() const override {
SkString str;
str.append(GrMeshDrawOp::dumpInfo());
str.appendf("# combined: %d\n", fRects.count());
for (int i = 0; i < fRects.count(); ++i) {
const RectInfo& info = fRects[i];
str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
info.fColor, info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight,
info.fRect.fBottom);
}
return str;
}
bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
GrColor* color = &fRects.front().fColor;
return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kNone, color);
}
FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
NewNonAAFillRectOp(const Helper::MakeArgs& args, GrColor color, const SkMatrix& viewMatrix,
const SkRect& rect, const SkRect* localRect, const SkMatrix* localMatrix,
GrAAType aaType, const GrUserStencilSettings* stencilSettings)
: INHERITED(ClassID()), fHelper(args, aaType, stencilSettings) {
SkASSERT(!viewMatrix.hasPerspective() && (!localMatrix || !localMatrix->hasPerspective()));
RectInfo& info = fRects.push_back();
info.fColor = color;
info.fViewMatrix = viewMatrix;
info.fRect = rect;
if (localRect && localMatrix) {
info.fLocalQuad.setFromMappedRect(*localRect, *localMatrix);
} else if (localRect) {
info.fLocalQuad.set(*localRect);
} else if (localMatrix) {
info.fLocalQuad.setFromMappedRect(rect, *localMatrix);
} else {
info.fLocalQuad.set(rect);
}
this->setTransformedBounds(fRects[0].fRect, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
}
private:
void onPrepareDraws(Target* target) const override {
sk_sp<GrGeometryProcessor> gp = make_gp();
if (!gp) {
SkDebugf("Couldn't create GrGeometryProcessor\n");
return;
}
SkASSERT(gp->getVertexStride() ==
sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
size_t vertexStride = gp->getVertexStride();
int rectCount = fRects.count();
sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
PatternHelper helper;
void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
indexBuffer.get(), kVertsPerRect, kIndicesPerRect, rectCount);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
for (int i = 0; i < rectCount; i++) {
intptr_t verts =
reinterpret_cast<intptr_t>(vertices) + i * kVertsPerRect * vertexStride;
tesselate(verts, vertexStride, fRects[i].fColor, &fRects[i].fViewMatrix,
fRects[i].fRect, &fRects[i].fLocalQuad);
}
helper.recordDraw(target, gp.get(), fHelper.makePipeline(target));
}
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
NewNonAAFillRectOp* that = t->cast<NewNonAAFillRectOp>();
if (!fHelper.isCompatible(that->fHelper)) {
return false;
}
fRects.push_back_n(that->fRects.count(), that->fRects.begin());
this->joinBounds(*that);
return true;
}
struct RectInfo {
GrColor fColor;
SkMatrix fViewMatrix;
SkRect fRect;
GrQuad fLocalQuad;
};
Helper fHelper;
SkSTArray<1, RectInfo, true> fRects;
typedef GrMeshDrawOp INHERITED;
};
namespace GrNewNonAAFillRectOp {
std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix,
GrAAType aaType,
const GrUserStencilSettings* stencilSettings) {
return NewNonAAFillRectOp::Make(std::move(paint), viewMatrix, rect, localRect, localMatrix,
aaType, stencilSettings);
}
}; // namespace GrNewNonAAFillRectOp
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,31 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrNewNonAAFillRectOp_DEFINED
#define GrNewNonAAFillRectOp_DEFINED
#include <memory>
#include "GrColor.h"
class GrDrawOp;
class GrPaint;
class SkMatrix;
struct SkRect;
struct GrUserStencilSettings;
enum class GrAAType : unsigned;
namespace GrNewNonAAFillRectOp {
std::unique_ptr<GrDrawOp> Make(GrPaint&&,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix,
GrAAType,
const GrUserStencilSettings* = nullptr);
};
#endif

View File

@ -0,0 +1,194 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrSimpleMeshDrawOpHelper_DEFINED
#define GrSimpleMeshDrawOpHelper_DEFINED
#include "GrAppliedClip.h"
#include "GrOpFlushState.h"
#include "GrPipeline.h"
#include "GrProcessorSet.h"
#include "GrUserStencilSettings.h"
/**
* This class can be used to help implement simple mesh draw ops. It reduces the amount of
* boilerplate code to type and also provides a mechanism for optionally allocating space for a
* GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
* GrPipeline for a uniform primitive color and a GrPaint.
*/
class GrSimpleMeshDrawOpHelper {
public:
struct MakeArgs;
/**
* This can be used by a Op class to perform allocation and initialization such that a
* GrProcessorSet (if required) is allocated at the same time as the Op instance. It requires
* that Op implements a constructor of the form:
* Op(MakeArgs, GrColor, OpArgs...)
* which is public or made accessible via 'friend'.
*/
template <typename Op, typename... OpArgs>
static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs);
GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType,
GrUserStencilSettings* stencilSettings = nullptr)
: fProcessors(args.fProcessorSet)
, fPipelineFlags(args.fSRGBFlags)
, fAAType((int)aaType) {
SkASSERT(!stencilSettings);
if (GrAATypeIsHW(aaType)) {
fPipelineFlags |= GrPipeline::kHWAntialias_Flag;
}
}
~GrSimpleMeshDrawOpHelper() {
if (fProcessors) {
fProcessors->~GrProcessorSet();
}
}
GrSimpleMeshDrawOpHelper() = delete;
GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const {
return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
: GrDrawOp::FixedFunctionFlags::kNone;
}
bool isCompatible(const GrSimpleMeshDrawOpHelper& that) const {
if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
return false;
}
if (SkToBool(fProcessors) && *fProcessors != *that.fProcessors) {
return false;
}
return fPipelineFlags == that.fPipelineFlags && fAAType == that.fAAType;
}
bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip,
GrProcessorAnalysisCoverage geometryCoverage, GrColor* color) {
if (fProcessors) {
GrProcessorAnalysisCoverage coverage = geometryCoverage;
if (GrProcessorAnalysisCoverage::kNone == coverage) {
coverage = clip->clipCoverageFragmentProcessor()
? GrProcessorAnalysisCoverage::kSingleChannel
: GrProcessorAnalysisCoverage::kNone;
}
bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples;
GrProcessorSet::Analysis analysis =
fProcessors->finalize(*color, coverage, clip, isMixedSamples, caps, color);
return analysis.requiresDstTexture();
} else {
return GrProcessorSet::EmptySetAnalysis().requiresDstTexture();
}
}
GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
return target->allocPipeline(this->pipelineInitArgs(target));
}
struct MakeArgs {
private:
MakeArgs() = default;
GrProcessorSet* fProcessorSet;
uint32_t fSRGBFlags;
friend class GrSimpleMeshDrawOpHelper;
};
protected:
GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
uint32_t pipelineFlags() const { return fPipelineFlags; }
const GrProcessorSet& processors() const {
return fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
}
GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const {
GrPipeline::InitArgs args;
args.fFlags = this->pipelineFlags();
args.fProcessors = &this->processors();
args.fRenderTarget = target->renderTarget();
args.fAppliedClip = target->clip();
args.fDstTexture = target->dstTexture();
args.fCaps = &target->caps();
return args;
}
private:
GrProcessorSet* fProcessors;
unsigned fPipelineFlags : 8;
unsigned fAAType : 2;
};
/**
* This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This
* uses private inheritance because it non-virtually overrides methods in the base class and should
* never be used with a GrSimpleMeshDrawOpHelper pointer or reference.
*/
class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
public:
using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
// using declarations can't be templated, so this is a pass through function instead.
template <typename Op, typename... OpArgs>
static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs) {
return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
std::move(paint), std::forward<OpArgs>(opArgs)...);
}
GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs& args, GrAAType aaType,
const GrUserStencilSettings* stencilSettings)
: INHERITED(args, aaType)
, fStencilSettings(stencilSettings ? stencilSettings
: &GrUserStencilSettings::kUnused) {}
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const {
GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags();
if (fStencilSettings != &GrUserStencilSettings::kUnused) {
flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil;
}
return flags;
}
using GrSimpleMeshDrawOpHelper::xpRequiresDstTexture;
bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that) const {
return INHERITED::isCompatible(that) && fStencilSettings == that.fStencilSettings;
}
GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
auto args = INHERITED::pipelineInitArgs(target);
args.fUserStencil = fStencilSettings;
return target->allocPipeline(args);
}
private:
const GrUserStencilSettings* fStencilSettings;
typedef GrSimpleMeshDrawOpHelper INHERITED;
};
template <typename Op, typename... OpArgs>
std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrPaint&& paint,
OpArgs... opArgs) {
MakeArgs makeArgs;
makeArgs.fSRGBFlags = GrPipeline::SRGBFlagsFromPaint(paint);
GrColor color = paint.getColor();
if (paint.isTrivial()) {
makeArgs.fProcessorSet = nullptr;
return std::unique_ptr<GrDrawOp>(new Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
} else {
char* mem = (char*)GrOp::operator new(sizeof(Op) + sizeof(GrProcessorSet));
char* setMem = mem + sizeof(Op);
makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
return std::unique_ptr<GrDrawOp>(
new (mem) Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
}
}
#endif