Revert of Begin weaning GrClipMaskManager off of GrDrawTarget (take 2) (patchset #7 id:120001 of https://codereview.chromium.org/1754563003/ )

Reason for revert:
fAuditTrail

Original issue's description:
> Begin weaning GrClipMaskManager off of GrDrawTarget (take 2)
>
> GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1754563003
>
> Committed: https://skia.googlesource.com/skia/+/86c60758e9e4f9e203d7462cb22b2a245a0f51bd

TBR=joshualitt@chromium.org,bsalomon@google.com,joshualitt@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1754353002
This commit is contained in:
robertphillips 2016-03-02 08:53:12 -08:00 committed by Commit bot
parent 86c60758e9
commit 8b8f36fc49
19 changed files with 266 additions and 473 deletions

View File

@ -12,7 +12,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrContext.h" #include "GrContext.h"
#include "GrPathUtils.h" #include "GrPathUtils.h"
#include "GrTest.h" #include "GrTest.h"
@ -226,7 +226,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, klmSigns[c])); BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, klmSigns[c]));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
} }
++col; ++col;
if (numCols == col) { if (numCols == col) {
@ -367,7 +367,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, 1.f)); BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, 1.f));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
} }
++col; ++col;
if (numCols == col) { if (numCols == col) {
@ -603,7 +603,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch(BezierQuadTestBatch::Create(gp, geometry, SkAutoTUnref<GrDrawBatch> batch(BezierQuadTestBatch::Create(gp, geometry,
DevToUV)); DevToUV));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
} }
++col; ++col;
if (numCols == col) { if (numCols == col) {

View File

@ -8,7 +8,7 @@
#include "gm.h" #include "gm.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrContext.h" #include "GrContext.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrPipelineBuilder.h" #include "GrPipelineBuilder.h"
#include "SkDevice.h" #include "SkDevice.h"
#include "SkRRect.h" #include "SkRRect.h"
@ -99,7 +99,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds, GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
nullptr, nullptr)); nullptr, nullptr));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
} }
canvas->restore(); canvas->restore();
x = x + fTestOffsetX; x = x + fTestOffsetX;

View File

@ -13,7 +13,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrContext.h" #include "GrContext.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrPipelineBuilder.h" #include "GrPipelineBuilder.h"
#include "SkGrPriv.h" #include "SkGrPriv.h"
#include "SkGradientShader.h" #include "SkGradientShader.h"
@ -118,7 +118,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateNonAAFill(grPaint.getColor(), viewMatrix, GrRectBatchFactory::CreateNonAAFill(grPaint.getColor(), viewMatrix,
renderRect, nullptr, nullptr)); renderRect, nullptr, nullptr));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
// Draw labels for the input to the processor and the processor to the right of // Draw labels for the input to the processor and the processor to the right of
// the test rect. The input label appears above the processor label. // the test rect. The input label appears above the processor label.

View File

@ -14,7 +14,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "GrDefaultGeoProcFactory.h" #include "GrDefaultGeoProcFactory.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrPathUtils.h" #include "GrPathUtils.h"
#include "GrTest.h" #include "GrTest.h"
#include "SkColorPriv.h" #include "SkColorPriv.h"
@ -205,7 +205,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch(ConvexPolyTestBatch::Create(gp, geometry)); SkAutoTUnref<GrDrawBatch> batch(ConvexPolyTestBatch::Create(gp, geometry));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
x += SkScalarCeilToScalar(path->getBounds().width() + 10.f); x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
} }
@ -252,7 +252,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch(ConvexPolyTestBatch::Create(gp, geometry)); SkAutoTUnref<GrDrawBatch> batch(ConvexPolyTestBatch::Create(gp, geometry));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
x += SkScalarCeilToScalar(rect.width() + 10.f); x += SkScalarCeilToScalar(rect.width() + 10.f);
} }

View File

@ -8,7 +8,7 @@
#include "gm.h" #include "gm.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrContext.h" #include "GrContext.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "batches/GrDrawBatch.h" #include "batches/GrDrawBatch.h"
#include "batches/GrRectBatchFactory.h" #include "batches/GrRectBatchFactory.h"
#include "effects/GrRRectEffect.h" #include "effects/GrRRectEffect.h"
@ -137,8 +137,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(),
bounds, nullptr, nullptr)); bounds, nullptr, nullptr));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, drawContext->internal_drawBatch(pipelineBuilder, batch);
batch);
} else { } else {
drew = false; drew = false;
} }

View File

@ -12,7 +12,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrContext.h" #include "GrContext.h"
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkGr.h" #include "SkGr.h"
@ -135,7 +135,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateNonAAFill(GrColor_WHITE, viewMatrix, GrRectBatchFactory::CreateNonAAFill(GrColor_WHITE, viewMatrix,
renderRect, nullptr, nullptr)); renderRect, nullptr, nullptr));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
x += renderRect.width() + kTestPad; x += renderRect.width() + kTestPad;
} }
y += renderRect.height() + kTestPad; y += renderRect.height() + kTestPad;

View File

@ -13,7 +13,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrContext.h" #include "GrContext.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrPipelineBuilder.h" #include "GrPipelineBuilder.h"
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkGr.h" #include "SkGr.h"
@ -132,7 +132,7 @@ protected:
SkAutoTUnref<GrDrawBatch> batch( SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateNonAAFill(GrColor_WHITE, viewMatrix, GrRectBatchFactory::CreateNonAAFill(GrColor_WHITE, viewMatrix,
renderRect, nullptr, nullptr)); renderRect, nullptr, nullptr));
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
} }
x += renderRect.width() + kTestPad; x += renderRect.width() + kTestPad;
} }

View File

@ -82,7 +82,6 @@
'<(skia_src_path)/gpu/GrDefaultGeoProcFactory.cpp', '<(skia_src_path)/gpu/GrDefaultGeoProcFactory.cpp',
'<(skia_src_path)/gpu/GrDefaultGeoProcFactory.h', '<(skia_src_path)/gpu/GrDefaultGeoProcFactory.h',
'<(skia_src_path)/gpu/GrDrawContext.cpp', '<(skia_src_path)/gpu/GrDrawContext.cpp',
'<(skia_src_path)/gpu/GrDrawContextPriv.h',
'<(skia_src_path)/gpu/GrPathRenderingDrawContext.cpp', '<(skia_src_path)/gpu/GrPathRenderingDrawContext.cpp',
'<(skia_src_path)/gpu/GrPathRenderingDrawContext.h', '<(skia_src_path)/gpu/GrPathRenderingDrawContext.h',
'<(skia_src_path)/gpu/GrDrawingManager.cpp', '<(skia_src_path)/gpu/GrDrawingManager.cpp',

View File

@ -114,13 +114,6 @@ public:
} }
} }
void setIRect(const SkIRect& irect) {
this->reset();
fClipType = kIRect_ClipType;
fOrigin.setZero();
fClip.fIRect = irect;
}
const SkIRect& irect() const { const SkIRect& irect() const {
SkASSERT(kIRect_ClipType == fClipType); SkASSERT(kIRect_ClipType == fClipType);
return fClip.fIRect; return fClip.fIRect;

View File

@ -11,7 +11,6 @@
#include "GrColor.h" #include "GrColor.h"
#include "GrRenderTarget.h" #include "GrRenderTarget.h"
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "SkRegion.h"
#include "SkSurfaceProps.h" #include "SkSurfaceProps.h"
#include "../private/GrSingleOwner.h" #include "../private/GrSingleOwner.h"
@ -20,7 +19,6 @@ class GrAuditTrail;
class GrClip; class GrClip;
class GrContext; class GrContext;
class GrDrawBatch; class GrDrawBatch;
class GrDrawContextPriv;
class GrDrawPathBatchBase; class GrDrawPathBatchBase;
class GrDrawingManager; class GrDrawingManager;
class GrDrawTarget; class GrDrawTarget;
@ -279,9 +277,9 @@ public:
GrRenderTarget* accessRenderTarget() { return fRenderTarget; } GrRenderTarget* accessRenderTarget() { return fRenderTarget; }
// Provides access to functions that aren't part of the public API. ///////////////////////////////////////////////////////////////////////////////////////////////
GrDrawContextPriv drawContextPriv(); // Functions intended for internal use only.
const GrDrawContextPriv drawContextPriv() const; void internal_drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch);
protected: protected:
GrDrawContext(GrContext*, GrDrawingManager*, GrRenderTarget*, GrDrawContext(GrContext*, GrDrawingManager*, GrRenderTarget*,
@ -297,7 +295,6 @@ protected:
private: private:
friend class GrAtlasTextBlob; // for access to drawBatch friend class GrAtlasTextBlob; // for access to drawBatch
friend class GrDrawingManager; // for ctor friend class GrDrawingManager; // for ctor
friend class GrDrawContextPriv;
bool drawFilledDRRect(const GrClip& clip, bool drawFilledDRRect(const GrClip& clip,
const GrPaint& paint, const GrPaint& paint,
@ -305,10 +302,6 @@ private:
const SkRRect& origOuter, const SkRRect& origOuter,
const SkRRect& origInner); const SkRRect& origInner);
GrDrawBatch* getFillRectBatch(const GrPaint& paint,
const SkMatrix& viewMatrix,
const SkRect& rect);
void internalDrawPath(const GrClip& clip, void internalDrawPath(const GrClip& clip,
const GrPaint& paint, const GrPaint& paint,
const SkMatrix& viewMatrix, const SkMatrix& viewMatrix,

View File

@ -8,7 +8,7 @@
#include "GrClipMaskManager.h" #include "GrClipMaskManager.h"
#include "GrCaps.h" #include "GrCaps.h"
#include "GrDrawingManager.h" #include "GrDrawingManager.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrDrawTarget.h" #include "GrDrawTarget.h"
#include "GrGpuResourcePriv.h" #include "GrGpuResourcePriv.h"
#include "GrPaint.h" #include "GrPaint.h"
@ -159,8 +159,7 @@ GrResourceProvider* GrClipMaskManager::resourceProvider() {
* will be used on any element. If so, it returns true to indicate that the * will be used on any element. If so, it returns true to indicate that the
* entire clip should be rendered in SW and then uploaded en masse to the gpu. * entire clip should be rendered in SW and then uploaded en masse to the gpu.
*/ */
bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder,
const GrPipelineBuilder& pipelineBuilder,
const GrRenderTarget* rt, const GrRenderTarget* rt,
const SkVector& clipToMaskOffset, const SkVector& clipToMaskOffset,
const GrReducedClip::ElementList& elements) { const GrReducedClip::ElementList& elements) {
@ -180,7 +179,7 @@ bool GrClipMaskManager::UseSWOnlyPath(GrContext* context,
bool needsStencil = invert || bool needsStencil = invert ||
SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op; SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op;
if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled(), if (PathNeedsSWRenderer(this->getContext(), pipelineBuilder.getStencil().isDisabled(),
rt, translate, element, nullptr, needsStencil)) { rt, translate, element, nullptr, needsStencil)) {
return true; return true;
} }
@ -317,42 +316,6 @@ static void add_rect_to_clip(const GrClip& clip, const SkRect& devRect, GrClip*
} }
} }
bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilder,
GrPipelineBuilder::AutoRestoreStencil* ars,
const SkIRect& clipScissor,
const SkRect* devBounds,
GrAppliedClip* out) {
if (kRespectClip_StencilClipMode == fClipMode) {
fClipMode = kIgnoreClip_StencilClipMode;
}
GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
SkIRect devBoundsScissor;
const SkIRect* scissor = &clipScissor;
bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds;
if (doDevBoundsClip) {
devBounds->roundOut(&devBoundsScissor);
if (devBoundsScissor.intersect(clipScissor)) {
scissor = &devBoundsScissor;
}
}
if (scissor->contains(clipSpaceRTIBounds)) {
// This counts as wide open
this->setPipelineBuilderStencil(pipelineBuilder, ars);
return true;
}
if (clipSpaceRTIBounds.intersect(*scissor)) {
out->fScissorState.set(clipSpaceRTIBounds);
this->setPipelineBuilderStencil(pipelineBuilder, ars);
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil, // sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software // scissor, or entirely software
@ -476,23 +439,21 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
SkIntToScalar(-clipSpaceIBounds.fTop) SkIntToScalar(-clipSpaceIBounds.fTop)
}; };
if (UseSWOnlyPath(this->getContext(), pipelineBuilder, rt, clipToMaskOffset, elements)) { if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)) {
// The clip geometry is complex enough that it will be more efficient to create it // The clip geometry is complex enough that it will be more efficient to create it
// entirely in software // entirely in software
result.reset(CreateSoftwareClipMask(this->getContext(), result.reset(this->createSoftwareClipMask(genID,
genID, initialState,
initialState, elements,
elements, clipToMaskOffset,
clipToMaskOffset, clipSpaceIBounds));
clipSpaceIBounds));
} else { } else {
result.reset(CreateAlphaClipMask(this->getContext(), result.reset(this->createAlphaClipMask(genID,
genID, initialState,
initialState, elements,
elements, clipToMaskOffset,
clipToMaskOffset, clipSpaceIBounds));
clipSpaceIBounds)); // If createAlphaClipMask fails it means useSWOnlyPath has a bug
// If createAlphaClipMask fails it means UseSWOnlyPath has a bug
SkASSERT(result); SkASSERT(result);
} }
@ -527,67 +488,93 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
return true; return true;
} }
static bool stencil_element(GrDrawContext* dc, namespace {
const SkIRect* scissorRect, ////////////////////////////////////////////////////////////////////////////////
const GrStencilSettings& ss, // Set a coverage drawing XPF on the pipelineBuilder for the given op and invertCoverage mode
const SkMatrix& viewMatrix, void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage,
const SkClipStack::Element* element) { GrPipelineBuilder* pipelineBuilder) {
SkASSERT(op <= SkRegion::kLastOp);
// TODO: Draw rrects directly here. pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage);
switch (element->getType()) { }
case Element::kEmpty_Type:
SkDEBUGFAIL("Should never get here with an empty element.");
break;
case Element::kRect_Type:
return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss,
element->getOp(),
element->isInverseFilled(),
element->isAA(),
viewMatrix, element->getRect());
break;
default: {
SkPath path;
element->asPath(&path);
if (path.isInverseFillType()) {
path.toggleInverseFillType();
}
return dc->drawContextPriv().drawAndStencilPath(scissorRect, ss,
element->getOp(),
element->isInverseFilled(),
element->isAA(), viewMatrix, path);
break;
}
}
return false;
} }
static void draw_element(GrDrawContext* dc, ////////////////////////////////////////////////////////////////////////////////
const GrClip& clip, // TODO: can this just always be WideOpen? bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
const GrPaint &paint, const SkMatrix& viewMatrix,
const SkMatrix& viewMatrix, GrTexture* target,
const SkClipStack::Element* element) { const SkClipStack::Element* element,
GrPathRenderer* pr) {
GrRenderTarget* rt = target->asRenderTarget();
pipelineBuilder->setRenderTarget(rt);
// The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP
// which ignores color.
GrColor color = GrColor_WHITE;
// TODO: Draw rrects directly here. // TODO: Draw rrects directly here.
switch (element->getType()) { switch (element->getType()) {
case Element::kEmpty_Type: case Element::kEmpty_Type:
SkDEBUGFAIL("Should never get here with an empty element."); SkDEBUGFAIL("Should never get here with an empty element.");
break; break;
case Element::kRect_Type: case Element::kRect_Type: {
dc->drawRect(clip, paint, viewMatrix, element->getRect()); // TODO: Do rects directly to the accumulator using a aa-rect GrProcessor that covers
break; // the entire mask bounds and writes 0 outside the rect.
if (element->isAA()) {
SkRect devRect = element->getRect();
viewMatrix.mapRect(&devRect);
SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateAAFill(color, viewMatrix, element->getRect(),
devRect));
fDrawTarget->drawBatch(*pipelineBuilder, batch);
} else {
draw_non_aa_rect(fDrawTarget, *pipelineBuilder, color, viewMatrix,
element->getRect());
}
return true;
}
default: { default: {
SkPath path; SkPath path;
element->asPath(&path); element->asPath(&path);
if (path.isInverseFillType()) { if (path.isInverseFillType()) {
path.toggleInverseFillType(); path.toggleInverseFillType();
} }
GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
if (nullptr == pr) {
GrPathRendererChain::DrawType type;
type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
GrPathRendererChain::kColor_DrawType;
dc->drawPath(clip, paint, viewMatrix, path, GrStrokeInfo::FillInfo()); GrPathRenderer::CanDrawPathArgs canDrawArgs;
canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps();
canDrawArgs.fViewMatrix = &viewMatrix;
canDrawArgs.fPath = &path;
canDrawArgs.fStroke = &stroke;
canDrawArgs.fAntiAlias = element->isAA();;
canDrawArgs.fIsStencilDisabled = pipelineBuilder->getStencil().isDisabled();
canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false, type);
}
if (nullptr == pr) {
return false;
}
GrPathRenderer::DrawPathArgs args;
args.fTarget = fDrawTarget;
args.fResourceProvider = this->getContext()->resourceProvider();
args.fPipelineBuilder = pipelineBuilder;
args.fColor = color;
args.fViewMatrix = &viewMatrix;
args.fPath = &path;
args.fStroke = &stroke;
args.fAntiAlias = element->isAA();
pr->drawPath(args);
break; break;
} }
} }
return true;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -601,13 +588,32 @@ static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey
builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
} }
GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context, GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUniqueKey& key,
int32_t elementsGenID, bool renderTarget) {
GrSurfaceDesc desc;
desc.fWidth = width;
desc.fHeight = height;
desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
if (!renderTarget || this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
desc.fConfig = kAlpha_8_GrPixelConfig;
} else {
desc.fConfig = kRGBA_8888_GrPixelConfig;
}
GrTexture* texture = this->resourceProvider()->createApproxTexture(desc, 0);
if (!texture) {
return nullptr;
}
texture->resourcePriv().setUniqueKey(key);
return texture;
}
GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
GrReducedClip::InitialState initialState, GrReducedClip::InitialState initialState,
const GrReducedClip::ElementList& elements, const GrReducedClip::ElementList& elements,
const SkVector& clipToMaskOffset, const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds) { const SkIRect& clipSpaceIBounds) {
GrResourceProvider* resourceProvider = context->resourceProvider(); GrResourceProvider* resourceProvider = this->resourceProvider();
GrUniqueKey key; GrUniqueKey key;
GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) { if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
@ -615,27 +621,15 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
} }
// There's no texture in the cache. Let's try to allocate it then. // There's no texture in the cache. Let's try to allocate it then.
GrSurfaceDesc desc; SkAutoTUnref<GrTexture> texture(this->createCachedMask(
desc.fWidth = clipSpaceIBounds.width(); clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true));
desc.fHeight = clipSpaceIBounds.height();
desc.fFlags = kRenderTarget_GrSurfaceFlag;
if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
desc.fConfig = kAlpha_8_GrPixelConfig;
} else {
desc.fConfig = kRGBA_8888_GrPixelConfig;
}
SkAutoTUnref<GrTexture> texture(resourceProvider->createApproxTexture(desc, 0));
if (!texture) { if (!texture) {
return nullptr; return nullptr;
} }
texture->resourcePriv().setUniqueKey(key); // Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
SkAutoTUnref<GrDrawContext> dc(context->drawContext(texture->asRenderTarget())); const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
if (!dc) {
return nullptr;
}
// The texture may be larger than necessary, this rect represents the part of the texture // The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip. // we populate with a rasterization of the clip.
@ -643,18 +637,16 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
// The scratch texture that we are drawing into can be substantially larger than the mask. Only // The scratch texture that we are drawing into can be substantially larger than the mask. Only
// clear the part that we care about. // clear the part that we care about.
dc->clear(&maskSpaceIBounds, fDrawTarget->clear(&maskSpaceIBounds,
GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
true); true,
texture->asRenderTarget());
// Set the matrix so that rendered clip elements are transformed to mask space from clip // When we use the stencil in the below loop it is important to have this clip installed.
// space.
const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
// It is important that we use maskSpaceIBounds as the stencil rect in the below loop.
// The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
// pass must not set values outside of this bounds or stencil values outside the rect won't be // pass must not set values outside of this bounds or stencil values outside the rect won't be
// cleared. // cleared.
const GrClip clip(maskSpaceIBounds);
// walk through each clip element and perform its set op // walk through each clip element and perform its set op
for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
@ -662,54 +654,68 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
SkRegion::Op op = element->getOp(); SkRegion::Op op = element->getOp();
bool invert = element->isInverseFilled(); bool invert = element->isInverseFilled();
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
#ifdef SK_DEBUG
GrPathRenderer* pr = GetPathRenderer(context, GrPathRenderer* pr = GetPathRenderer(this->getContext(),
texture, translate, element); texture, translate, element);
if (Element::kRect_Type != element->getType() && !pr) { if (Element::kRect_Type != element->getType() && !pr) {
// UseSWOnlyPath should now filter out all cases where gpu-side mask merging would // useSWOnlyPath should now filter out all cases where gpu-side mask merging would
// be performed (i.e., pr would be NULL for a non-rect path). // be performed (i.e., pr would be NULL for a non-rect path). See https://bug.skia.org/4519
// See https://bug.skia.org/4519 for rationale and details. // for rationale and details.
SkASSERT(0); SkASSERT(0);
} continue;
#endif
// draw directly into the result with the stencil set to make the pixels affected
// by the clip shape be non-zero.
GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff)
if (!stencil_element(dc, &maskSpaceIBounds, kStencilInElement,
translate, element)) {
texture->resourcePriv().removeUniqueKey();
return nullptr;
} }
// Draw to the exterior pixels (those with a zero stencil value). {
GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, GrPipelineBuilder pipelineBuilder;
kZero_StencilOp,
kZero_StencilOp, pipelineBuilder.setClip(clip);
kEqual_StencilFunc, pipelineBuilder.setRenderTarget(texture->asRenderTarget());
0xffff, SkASSERT(pipelineBuilder.getStencil().isDisabled());
0x0000,
0xffff); // draw directly into the result with the stencil set to make the pixels affected
if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDrawOutsideElement, // by the clip shape be non-zero.
op, !invert, false, GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
translate, kReplace_StencilOp,
SkRect::Make(clipSpaceIBounds))) { kReplace_StencilOp,
texture->resourcePriv().removeUniqueKey(); kAlways_StencilFunc,
return nullptr; 0xffff,
0xffff,
0xffff);
pipelineBuilder.setStencil(kStencilInElement);
set_coverage_drawing_xpf(op, invert, &pipelineBuilder);
if (!this->drawElement(&pipelineBuilder, translate, texture, element, pr)) {
texture->resourcePriv().removeUniqueKey();
return nullptr;
}
}
{
GrPipelineBuilder backgroundPipelineBuilder;
backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder);
// Draw to the exterior pixels (those with a zero stencil value).
GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
kZero_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
backgroundPipelineBuilder.setStencil(kDrawOutsideElement);
// The color passed in here does not matter since the coverageSetOpXP won't read it.
draw_non_aa_rect(fDrawTarget, backgroundPipelineBuilder, GrColor_WHITE, translate,
SkRect::Make(clipSpaceIBounds));
} }
} else { } else {
// all the remaining ops can just be directly draw into the accumulation buffer GrPipelineBuilder pipelineBuilder;
GrPaint paint;
paint.setAntiAlias(element->isAA());
paint.setCoverageSetOpXPFactory(op, false);
draw_element(dc, GrClip::WideOpen(), paint, translate, element); // all the remaining ops can just be directly draw into the accumulation buffer
set_coverage_drawing_xpf(op, false, &pipelineBuilder);
// The color passed in here does not matter since the coverageSetOpXP won't read it.
this->drawElement(&pipelineBuilder, translate, texture, element);
} }
} }
@ -1075,15 +1081,14 @@ void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
int32_t elementsGenID,
GrReducedClip::InitialState initialState, GrReducedClip::InitialState initialState,
const GrReducedClip::ElementList& elements, const GrReducedClip::ElementList& elements,
const SkVector& clipToMaskOffset, const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds) { const SkIRect& clipSpaceIBounds) {
GrUniqueKey key; GrUniqueKey key;
GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
GrResourceProvider* resourceProvider = context->resourceProvider(); GrResourceProvider* resourceProvider = this->resourceProvider();
if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) { if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
return texture; return texture;
} }
@ -1092,7 +1097,7 @@ GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context,
// the top left corner of the resulting rect to the top left of the texture. // the top left corner of the resulting rect to the top left of the texture.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
GrSWMaskHelper helper(context); GrSWMaskHelper helper(this->getContext());
// Set the matrix so that rendered clip elements are transformed to mask space from clip // Set the matrix so that rendered clip elements are transformed to mask space from clip
// space. // space.
@ -1136,17 +1141,11 @@ GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context,
} }
// Allocate clip mask texture // Allocate clip mask texture
GrSurfaceDesc desc; GrTexture* result = this->createCachedMask(clipSpaceIBounds.width(), clipSpaceIBounds.height(),
desc.fWidth = clipSpaceIBounds.width(); key, false);
desc.fHeight = clipSpaceIBounds.height(); if (nullptr == result) {
desc.fConfig = kAlpha_8_GrPixelConfig;
GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0);
if (!result) {
return nullptr; return nullptr;
} }
result->resourcePriv().setUniqueKey(key);
helper.toTexture(result); helper.toTexture(result);
return result; return result;

View File

@ -69,12 +69,6 @@ public:
const SkRect* devBounds, const SkRect* devBounds,
GrAppliedClip*); GrAppliedClip*);
bool setupScissorClip(const GrPipelineBuilder& pipelineBuilder,
GrPipelineBuilder::AutoRestoreStencil* ars,
const SkIRect& scissor,
const SkRect* devBounds,
GrAppliedClip* out);
void adjustPathStencilParams(const GrStencilAttachment*, GrStencilSettings*); void adjustPathStencilParams(const GrStencilAttachment*, GrStencilSettings*);
private: private:
@ -129,26 +123,32 @@ private:
// Creates an alpha mask of the clip. The mask is a rasterization of elements through the // Creates an alpha mask of the clip. The mask is a rasterization of elements through the
// rect specified by clipSpaceIBounds. // rect specified by clipSpaceIBounds.
static GrTexture* CreateAlphaClipMask(GrContext*, GrTexture* createAlphaClipMask(int32_t elementsGenID,
int32_t elementsGenID, GrReducedClip::InitialState initialState,
GrReducedClip::InitialState initialState, const GrReducedClip::ElementList& elements,
const GrReducedClip::ElementList& elements, const SkVector& clipToMaskOffset,
const SkVector& clipToMaskOffset, const SkIRect& clipSpaceIBounds);
const SkIRect& clipSpaceIBounds);
// Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture. // Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture.
static GrTexture* CreateSoftwareClipMask(GrContext*, GrTexture* createSoftwareClipMask(int32_t elementsGenID,
int32_t elementsGenID, GrReducedClip::InitialState initialState,
GrReducedClip::InitialState initialState, const GrReducedClip::ElementList& elements,
const GrReducedClip::ElementList& elements, const SkVector& clipToMaskOffset,
const SkVector& clipToMaskOffset, const SkIRect& clipSpaceIBounds);
const SkIRect& clipSpaceIBounds);
static bool UseSWOnlyPath(GrContext*, bool useSWOnlyPath(const GrPipelineBuilder&,
const GrPipelineBuilder&, const GrRenderTarget* rt,
const GrRenderTarget* rt, const SkVector& clipToMaskOffset,
const SkVector& clipToMaskOffset, const GrReducedClip::ElementList& elements);
const GrReducedClip::ElementList& elements);
// Draws a clip element into the target alpha mask. The caller should have already setup the
// desired blend operation. Optionally if the caller already selected a path renderer it can
// be passed. Otherwise the function will select one if the element is a path.
bool drawElement(GrPipelineBuilder*,
const SkMatrix& viewMatrix,
GrTexture* target,
const SkClipStack::Element*,
GrPathRenderer* pr = nullptr);
/** /**
* Called prior to return control back the GrGpu in setupClipping. It updates the * Called prior to return control back the GrGpu in setupClipping. It updates the

View File

@ -9,7 +9,6 @@
#include "GrBatchTest.h" #include "GrBatchTest.h"
#include "GrColor.h" #include "GrColor.h"
#include "GrDrawContext.h" #include "GrDrawContext.h"
#include "GrDrawContextPriv.h"
#include "GrDrawingManager.h" #include "GrDrawingManager.h"
#include "GrOvalRenderer.h" #include "GrOvalRenderer.h"
#include "GrPathRenderer.h" #include "GrPathRenderer.h"
@ -34,11 +33,8 @@
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext()) #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
#define ASSERT_SINGLE_OWNER \ #define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
#define ASSERT_SINGLE_OWNER_PRIV \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; } #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->abandoned()) { return false; }
#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; } #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
class AutoCheckFlush { class AutoCheckFlush {
@ -254,28 +250,6 @@ static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
} }
GrDrawBatch* GrDrawContext::getFillRectBatch(const GrPaint& paint,
const SkMatrix& viewMatrix,
const SkRect& rect) {
GrDrawBatch* batch = nullptr;
if (should_apply_coverage_aa(paint, fRenderTarget)) {
// The fill path can handle rotation but not skew.
if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
SkRect devBoundRect;
viewMatrix.mapRect(&devBoundRect, rect);
batch = GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix,
rect, devBoundRect);
}
} else {
// filled BW rect
batch = GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect,
nullptr, nullptr);
}
return batch;
}
void GrDrawContext::drawRect(const GrClip& clip, void GrDrawContext::drawRect(const GrClip& clip,
const GrPaint& paint, const GrPaint& paint,
const SkMatrix& viewMatrix, const SkMatrix& viewMatrix,
@ -329,28 +303,35 @@ void GrDrawContext::drawRect(const GrClip& clip,
bool snapToPixelCenters = false; bool snapToPixelCenters = false;
SkAutoTUnref<GrDrawBatch> batch; SkAutoTUnref<GrDrawBatch> batch;
if (width < 0) { if (should_apply_coverage_aa(paint, fRenderTarget)) {
batch.reset(this->getFillRectBatch(paint, viewMatrix, rect)); if (width >= 0) {
} else {
GrColor color = paint.getColor();
if (should_apply_coverage_aa(paint, fRenderTarget)) {
// The stroke path needs the rect to remain axis aligned (no rotation or skew). // The stroke path needs the rect to remain axis aligned (no rotation or skew).
if (viewMatrix.rectStaysRect()) { if (viewMatrix.rectStaysRect()) {
batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, batch.reset(GrRectBatchFactory::CreateAAStroke(paint.getColor(), viewMatrix, rect,
*strokeInfo)); *strokeInfo));
} }
} else { } else {
// Non-AA hairlines are snapped to pixel centers to make which pixels are hit // The fill path can handle rotation but not skew.
// deterministic if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled()); SkRect devBoundRect;
batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, viewMatrix.mapRect(&devBoundRect, rect);
width, snapToPixelCenters)); batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix, rect,
devBoundRect));
// Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of }
// hairline rects. We jam all the vertices to pixel centers to avoid this, but not
// when MSAA is enabled because it can cause ugly artifacts.
} }
} else if (width >= 0) {
// Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
batch.reset(GrRectBatchFactory::CreateNonAAStroke(paint.getColor(), viewMatrix, rect,
width, snapToPixelCenters));
// Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
// hairline rects. We jam all the vertices to pixel centers to avoid this, but not when
// MSAA is enabled because it can cause ugly artifacts.
} else {
// filled BW rect
batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect,
nullptr, nullptr));
} }
if (batch) { if (batch) {
@ -372,39 +353,6 @@ void GrDrawContext::drawRect(const GrClip& clip,
strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo());
} }
bool GrDrawContextPriv::drawAndStencilRect(const SkIRect* scissorRect,
const GrStencilSettings& ss,
SkRegion::Op op,
bool invert,
bool doAA,
const SkMatrix& viewMatrix,
const SkRect& rect) {
ASSERT_SINGLE_OWNER_PRIV
RETURN_FALSE_IF_ABANDONED_PRIV
SkDEBUGCODE(fDrawContext->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::stencilRect");
AutoCheckFlush acf(fDrawContext->fDrawingManager);
GrPaint paint;
paint.setAntiAlias(doAA);
paint.setCoverageSetOpXPFactory(op, invert);
SkAutoTUnref<GrDrawBatch> batch(fDrawContext->getFillRectBatch(paint, viewMatrix, rect));
if (batch) {
GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, GrClip::WideOpen());
pipelineBuilder.setStencil(ss);
fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch, scissorRect);
return true;
}
SkPath path;
path.setIsVolatile(true);
path.addRect(rect);
return this->drawAndStencilPath(scissorRect, ss, op, invert, doAA, viewMatrix, path);
}
void GrDrawContext::fillRectToRect(const GrClip& clip, void GrDrawContext::fillRectToRect(const GrClip& clip,
const GrPaint& paint, const GrPaint& paint,
const SkMatrix& viewMatrix, const SkMatrix& viewMatrix,
@ -853,80 +801,6 @@ void GrDrawContext::drawPath(const GrClip& clip,
this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo);
} }
bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect,
const GrStencilSettings& ss,
SkRegion::Op op,
bool invert,
bool doAA,
const SkMatrix& viewMatrix,
const SkPath& path) {
ASSERT_SINGLE_OWNER_PRIV
RETURN_FALSE_IF_ABANDONED_PRIV
SkDEBUGCODE(fDrawContext->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
if (path.isEmpty() && path.isInverseFillType()) {
this->drawAndStencilRect(scissorRect, ss, op, invert, false, SkMatrix::I(),
SkRect::MakeIWH(fDrawContext->fRenderTarget->width(),
fDrawContext->fRenderTarget->height()));
return true;
}
AutoCheckFlush acf(fDrawContext->fDrawingManager);
// An Assumption here is that path renderer would use some form of tweaking
// the src color (either the input alpha or in the frag shader) to implement
// aa. If we have some future driver-mojo path AA that can do the right
// thing WRT to the blend then we'll need some query on the PR.
bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled();
bool isStencilDisabled = true;
bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled();
const GrPathRendererChain::DrawType type =
useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
: GrPathRendererChain::kColor_DrawType;
GrPathRenderer::CanDrawPathArgs canDrawArgs;
canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
canDrawArgs.fViewMatrix = &viewMatrix;
canDrawArgs.fPath = &path;
canDrawArgs.fStroke = &GrStrokeInfo::FillInfo();
canDrawArgs.fAntiAlias = useCoverageAA;
canDrawArgs.fIsStencilDisabled = isStencilDisabled;
canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
// Don't allow the SW renderer
GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
if (!pr) {
return false;
}
GrPaint paint;
paint.setCoverageSetOpXPFactory(op, invert);
// TODO: it is unfortunate that we have to convert this to a GrClip to
// call drawPath.
GrClip clip;
if (scissorRect) {
clip.setIRect(*scissorRect);
}
GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, clip);
pipelineBuilder.setStencil(ss);
GrPathRenderer::DrawPathArgs args;
args.fTarget = fDrawContext->getDrawTarget();
args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
args.fPipelineBuilder = &pipelineBuilder;
args.fColor = GrColor_WHITE;
args.fViewMatrix = &viewMatrix;
args.fPath = &path;
args.fStroke = &GrStrokeInfo::FillInfo();
args.fAntiAlias = useCoverageAA;
pr->drawPath(args);
return true;
}
void GrDrawContext::internalDrawPath(const GrClip& clip, void GrDrawContext::internalDrawPath(const GrClip& clip,
const GrPaint& paint, const GrPaint& paint,
const SkMatrix& viewMatrix, const SkMatrix& viewMatrix,

View File

@ -1,60 +0,0 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrDrawContextPriv_DEFINED
#define GrDrawContextPriv_DEFINED
#include "GrDrawContext.h"
class GrStencilSettings;
/** Class that adds methods to GrDrawContext that are only intended for use internal to Skia.
This class is purely a privileged window into GrDrawContext. It should never have additional
data members or virtual methods. */
class GrDrawContextPriv {
public:
bool drawAndStencilRect(const SkIRect* scissorRect,
const GrStencilSettings&,
SkRegion::Op op,
bool invert,
bool doAA,
const SkMatrix& viewMatrix,
const SkRect&);
bool drawAndStencilPath(const SkIRect* scissorRect,
const GrStencilSettings&,
SkRegion::Op op,
bool invert,
bool doAA,
const SkMatrix& viewMatrix,
const SkPath&);
void testingOnly_drawBatch(const GrPipelineBuilder& pipelineBuilder,
GrDrawBatch* batch);
private:
explicit GrDrawContextPriv(GrDrawContext* drawContext) : fDrawContext(drawContext) {}
GrDrawContextPriv(const GrRenderTargetPriv&) {} // unimpl
GrDrawContextPriv& operator=(const GrRenderTargetPriv&); // unimpl
// No taking addresses of this type.
const GrDrawContextPriv* operator&() const;
GrDrawContextPriv* operator&();
GrDrawContext* fDrawContext;
friend class GrDrawContext; // to construct/copy this type.
};
inline GrDrawContextPriv GrDrawContext::drawContextPriv() { return GrDrawContextPriv(this); }
inline const GrDrawContextPriv GrDrawContext::drawContextPriv () const {
return GrDrawContextPriv(const_cast<GrDrawContext*>(this));
}
#endif

View File

@ -221,25 +221,13 @@ void GrDrawTarget::reset() {
fBatches.reset(); fBatches.reset();
} }
void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
GrDrawBatch* batch,
const SkIRect* scissorRect) {
// Setup clip // Setup clip
GrPipelineBuilder::AutoRestoreStencil ars; GrPipelineBuilder::AutoRestoreStencil ars;
GrAppliedClip clip; GrAppliedClip clip;
if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) {
if (scissorRect) { return;
SkASSERT(GrClip::kWideOpen_ClipType == pipelineBuilder.clip().clipType());
if (!fClipMaskManager->setupScissorClip(pipelineBuilder, &ars, *scissorRect,
&batch->bounds(), &clip)) {
return;
}
} else {
if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) {
return;
}
} }
GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
if (clip.clipCoverageFragmentProcessor()) { if (clip.clipCoverageFragmentProcessor()) {
arfps.set(&pipelineBuilder); arfps.set(&pipelineBuilder);

View File

@ -101,7 +101,7 @@ public:
*/ */
const GrCaps* caps() const { return fGpu->caps(); } const GrCaps* caps() const { return fGpu->caps(); }
void drawBatch(const GrPipelineBuilder&, GrDrawBatch*, const SkIRect* scissorRect = nullptr); void drawBatch(const GrPipelineBuilder&, GrDrawBatch*);
/** /**
* Draws path into the stencil buffer. The fill must be either even/odd or * Draws path into the stencil buffer. The fill must be either even/odd or

View File

@ -154,6 +154,14 @@ public:
return xpFactory; return xpFactory;
} }
/**
* Sets a GrXPFactory that will ignore src color and perform a set operation between the draws
* output coverage and the destination. This is useful to render coverage masks as CSG.
*/
void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false) {
fXPFactory.reset(GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage));
}
/** /**
* Sets a GrXPFactory that disables color writes to the destination. This is useful when * Sets a GrXPFactory that disables color writes to the destination. This is useful when
* rendering to the stencil buffer. * rendering to the stencil buffer.

View File

@ -9,7 +9,7 @@
#include "GrBatchAtlas.h" #include "GrBatchAtlas.h"
#include "GrContextOptions.h" #include "GrContextOptions.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrDrawingManager.h" #include "GrDrawingManager.h"
#include "GrGpuResourceCacheAccess.h" #include "GrGpuResourceCacheAccess.h"
#include "GrResourceCache.h" #include "GrResourceCache.h"
@ -258,17 +258,17 @@ void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newT
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define ASSERT_SINGLE_OWNER \ #define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);) SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
#define RETURN_IF_ABANDONED if (fDrawContext->fDrawingManager->abandoned()) { return; } #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
void GrDrawContextPriv::testingOnly_drawBatch(const GrPipelineBuilder& pipelineBuilder, void GrDrawContext::internal_drawBatch(const GrPipelineBuilder& pipelineBuilder,
GrDrawBatch* batch) { GrDrawBatch* batch) {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED RETURN_IF_ABANDONED
SkDEBUGCODE(fDrawContext->validate();) SkDEBUGCODE(this->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::testingOnly_drawBatch"); GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::internal_drawBatch");
fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch); this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
} }
#undef ASSERT_SINGLE_OWNER #undef ASSERT_SINGLE_OWNER

View File

@ -15,7 +15,7 @@
#include "GrAutoLocaleSetter.h" #include "GrAutoLocaleSetter.h"
#include "GrBatchTest.h" #include "GrBatchTest.h"
#include "GrContextFactory.h" #include "GrContextFactory.h"
#include "GrDrawContextPriv.h" #include "GrDrawContext.h"
#include "GrDrawingManager.h" #include "GrDrawingManager.h"
#include "GrInvariantOutput.h" #include "GrInvariantOutput.h"
#include "GrPipeline.h" #include "GrPipeline.h"
@ -361,7 +361,7 @@ bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages) {
return false; return false;
} }
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch); drawContext->internal_drawBatch(pipelineBuilder, batch);
} }
// Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes) // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
drawingManager->flush(); drawingManager->flush();
@ -398,7 +398,7 @@ bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages) {
return false; return false;
} }
drawContext->drawContextPriv().testingOnly_drawBatch(builder, batch); drawContext->internal_drawBatch(builder, batch);
drawingManager->flush(); drawingManager->flush();
} }
} }