Define clear regions in terms of GrFixedClip

Updates clear APIs to take GrFixedClip instead of a rectangle. This
will allow us to use window rectangles with clears. Removes stencil
knobs from GrFixedClip.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2262473003

Review-Url: https://codereview.chromium.org/2262473003
This commit is contained in:
csmartdalton 2016-08-31 11:55:52 -07:00 committed by Commit bot
parent dc43898bbb
commit 29df76096f
18 changed files with 237 additions and 161 deletions

View File

@ -25,6 +25,7 @@ class GrDrawContextPriv;
class GrDrawPathBatchBase;
class GrDrawingManager;
class GrDrawTarget;
class GrFixedClip;
class GrPaint;
class GrPathProcessor;
class GrPipelineBuilder;
@ -353,6 +354,8 @@ private:
friend class GrStencilAndCoverPathRenderer; // for access to drawBatch
friend class GrTessellatingPathRenderer; // for access to drawBatch
void internalClear(const GrFixedClip&, const GrColor, bool canIgnoreClip);
bool drawFilledDRRect(const GrClip& clip,
const GrPaint& paint,
const SkMatrix& viewMatrix,

View File

@ -489,10 +489,12 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
// The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.height());
GrFixedClip clip(maskSpaceIBounds);
// The scratch texture that we are drawing into can be substantially larger than the mask. Only
// clear the part that we care about.
dc->clear(&maskSpaceIBounds, InitialState::kAllIn == reducedClip.initialState() ? -1 : 0, true);
GrColor initialCoverage = InitialState::kAllIn == reducedClip.initialState() ? -1 : 0;
dc->drawContextPriv().clear(clip, initialCoverage, true);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
@ -509,8 +511,6 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
SkRegion::Op op = element->getOp();
bool invert = element->isInverseFilled();
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
GrFixedClip clip(maskSpaceIBounds);
// draw directly into the result with the stencil set to make the pixels affected
// by the clip shape be non-zero.
static constexpr GrUserStencilSettings kStencilInElement(
@ -549,7 +549,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
paint.setAntiAlias(element->isAA());
paint.setCoverageSetOpXPFactory(op, false);
draw_element(dc.get(), GrNoClip(), paint, translate, element);
draw_element(dc.get(), clip, paint, translate, element);
}
}
@ -560,8 +560,37 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
}
////////////////////////////////////////////////////////////////////////////////
// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
// (as opposed to canvas) coordinates
// Create a 1-bit clip mask in the stencil buffer.
class StencilClip final : public GrClip {
public:
StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {}
const GrFixedClip& fixedClip() const { return fFixedClip; }
private:
bool quickContains(const SkRect&) const final {
return false;
}
void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final {
fFixedClip.getConservativeBounds(width, height, devResult, iior);
}
bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final {
return false;
}
bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip* out) const final {
if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSettings, out)) {
return false;
}
out->addStencilClip();
return true;
}
GrFixedClip fFixedClip;
typedef GrClip INHERITED;
};
bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
GrDrawContext* drawContext,
const GrReducedClip& reducedClip,
@ -590,10 +619,10 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
// We set the current clip to the bounds so that our recursive draws are scissored to them.
SkIRect stencilSpaceIBounds(reducedClip.ibounds());
stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
GrFixedClip clip(stencilSpaceIBounds);
StencilClip stencilClip(stencilSpaceIBounds);
bool insideClip = InitialState::kAllIn == reducedClip.initialState();
drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, insideClip);
bool initialState = InitialState::kAllIn == reducedClip.initialState();
drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), initialState);
// walk through each clip element and perform its set op
// with the existing clip.
@ -602,8 +631,6 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampled();
bool fillInverted = false;
// enabled at bottom of loop
clip.disableStencilClip();
// This will be used to determine whether the clip shape can be rendered into the
// stencil with arbitrary stencil settings.
@ -663,7 +690,8 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
0xffff>()
);
if (Element::kRect_Type == element->getType()) {
drawContext->drawContextPriv().stencilRect(clip, &kDrawToStencil, useHWAA,
drawContext->drawContextPriv().stencilRect(stencilClip.fixedClip(),
&kDrawToStencil, useHWAA,
viewMatrix, element->getRect());
} else {
if (!clipPath.isEmpty()) {
@ -678,7 +706,7 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
args.fPaint = &paint;
args.fUserStencilSettings = &kDrawToStencil;
args.fDrawContext = drawContext;
args.fClip = &clip;
args.fClip = &stencilClip.fixedClip();
args.fViewMatrix = &viewMatrix;
args.fShape = &shape;
args.fAntiAlias = false;
@ -688,7 +716,7 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
GrPathRenderer::StencilPathArgs args;
args.fResourceProvider = context->resourceProvider();
args.fDrawContext = drawContext;
args.fClip = &clip;
args.fClip = &stencilClip.fixedClip();
args.fViewMatrix = &viewMatrix;
args.fIsAA = element->isAA();
args.fShape = &shape;
@ -698,16 +726,13 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
}
}
// Just enable stencil clip. The passes choose whether or not they will actually use it.
clip.enableStencilClip();
// now we modify the clip bit by rendering either the clip
// element directly or a bounding rect of the entire clip.
for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++pass) {
if (drawDirectToClip) {
if (Element::kRect_Type == element->getType()) {
drawContext->drawContextPriv().stencilRect(clip, *pass, useHWAA, viewMatrix,
element->getRect());
drawContext->drawContextPriv().stencilRect(stencilClip, *pass, useHWAA,
viewMatrix, element->getRect());
} else {
GrShape shape(clipPath, GrStyle::SimpleFill());
GrPaint paint;
@ -718,7 +743,7 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
args.fPaint = &paint;
args.fUserStencilSettings = *pass;
args.fDrawContext = drawContext;
args.fClip = &clip;
args.fClip = &stencilClip;
args.fViewMatrix = &viewMatrix;
args.fShape = &shape;
args.fAntiAlias = false;
@ -728,7 +753,8 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
} else {
// The view matrix is setup to do clip space -> stencil space translation, so
// draw rect in clip space.
drawContext->drawContextPriv().stencilRect(clip, *pass, false, viewMatrix,
drawContext->drawContextPriv().stencilRect(stencilClip, *pass,
false, viewMatrix,
SkRect::Make(reducedClip.ibounds()));
}
}

View File

@ -196,45 +196,55 @@ void GrDrawContext::clear(const SkIRect* rect,
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
AutoCheckFlush acf(fDrawingManager);
this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
}
const SkIRect rtRect = SkIRect::MakeWH(this->width(), this->height());
SkIRect clippedRect;
bool isFull = false;
if (!rect ||
(canIgnoreRect && fContext->caps()->fullClearIsFree()) ||
rect->contains(rtRect)) {
rect = &rtRect;
isFull = true;
} else {
clippedRect = *rect;
if (!clippedRect.intersect(rtRect)) {
return;
}
rect = &clippedRect;
}
void GrDrawContextPriv::clear(const GrFixedClip& clip,
const GrColor color,
bool canIgnoreClip) {
ASSERT_SINGLE_OWNER_PRIV
RETURN_IF_ABANDONED_PRIV
SkDEBUGCODE(fDrawContext->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clear");
AutoCheckFlush acf(fDrawContext->fDrawingManager);
fDrawContext->internalClear(clip, color, canIgnoreClip);
}
void GrDrawContext::internalClear(const GrFixedClip& clip,
const GrColor color,
bool canIgnoreClip) {
bool isFull = !clip.scissorEnabled() ||
(canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
if (fContext->caps()->useDrawInsteadOfClear()) {
// This works around a driver bug with clear by drawing a rect instead.
// The driver will ignore a clear if it is the only thing rendered to a
// target before the target is read.
if (rect == &rtRect) {
SkRect clearRect = SkRect::MakeIWH(this->width(), this->height());
if (isFull) {
this->discard();
} else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) {
return;
}
GrPaint paint;
paint.setColor4f(GrColor4f::FromGrColor(color));
paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
this->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::Make(*rect));
this->drawRect(clip, paint, SkMatrix::I(), clearRect);
} else if (isFull) {
this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
} else {
sk_sp<GrBatch> batch(GrClearBatch::Make(*rect, color, this->accessRenderTarget()));
sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget()));
if (!batch) {
return;
}
this->getDrawTarget()->addBatch(std::move(batch));
}
}
void GrDrawContext::drawPaint(const GrClip& clip,
const GrPaint& origPaint,
const SkMatrix& viewMatrix) {
@ -543,14 +553,14 @@ void GrDrawContext::drawRect(const GrClip& clip,
this->internalDrawPath(clip, paint, viewMatrix, path, *style);
}
void GrDrawContextPriv::clearStencilClip(const SkIRect& rect, bool insideClip) {
void GrDrawContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
ASSERT_SINGLE_OWNER_PRIV
RETURN_IF_ABANDONED_PRIV
SkDEBUGCODE(fDrawContext->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
AutoCheckFlush acf(fDrawContext->fDrawingManager);
fDrawContext->getDrawTarget()->clearStencilClip(rect, insideClip,
fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask,
fDrawContext->accessRenderTarget());
}
@ -561,7 +571,7 @@ void GrDrawContextPriv::stencilPath(const GrClip& clip,
fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
}
void GrDrawContextPriv::stencilRect(const GrFixedClip& clip,
void GrDrawContextPriv::stencilRect(const GrClip& clip,
const GrUserStencilSettings* ss,
bool useHWAA,
const SkMatrix& viewMatrix,
@ -580,7 +590,7 @@ void GrDrawContextPriv::stencilRect(const GrFixedClip& clip,
fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
}
bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip,
bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip,
const GrUserStencilSettings* ss,
SkRegion::Op op,
bool invert,
@ -1232,7 +1242,7 @@ void GrDrawContext::drawPath(const GrClip& clip,
this->internalDrawPath(clip, paint, viewMatrix, path, style);
}
bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip,
bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip,
const GrUserStencilSettings* ss,
SkRegion::Op op,
bool invert,

View File

@ -25,9 +25,11 @@ public:
return fDrawContext->getDrawTarget()->instancedRendering();
}
void clearStencilClip(const SkIRect& rect, bool insideClip);
void clear(const GrFixedClip&, const GrColor, bool canIgnoreClip);
void stencilRect(const GrFixedClip& clip,
void clearStencilClip(const GrFixedClip&, bool insideStencilMask);
void stencilRect(const GrClip& clip,
const GrUserStencilSettings* ss,
bool useHWAA,
const SkMatrix& viewMatrix,
@ -38,7 +40,7 @@ public:
const SkMatrix& viewMatrix,
const GrPath*);
bool drawAndStencilRect(const GrFixedClip&,
bool drawAndStencilRect(const GrClip&,
const GrUserStencilSettings*,
SkRegion::Op op,
bool invert,
@ -46,7 +48,7 @@ public:
const SkMatrix& viewMatrix,
const SkRect&);
bool drawAndStencilPath(const GrFixedClip&,
bool drawAndStencilPath(const GrClip&,
const GrUserStencilSettings*,
SkRegion::Op op,
bool invert,

View File

@ -459,9 +459,7 @@ void GrDrawTarget::fullClear(GrRenderTarget* renderTarget, GrColor color) {
fLastFullClearBatch->setColor(color);
return;
}
sk_sp<GrClearBatch> batch(GrClearBatch::Make(SkIRect::MakeWH(renderTarget->width(),
renderTarget->height()),
color, renderTarget));
sk_sp<GrClearBatch> batch(GrClearBatch::Make(GrFixedClip::Disabled(), color, renderTarget));
if (batch.get() == this->recordBatch(batch.get(), batch->bounds())) {
fLastFullClearBatch = batch.get();
}
@ -619,8 +617,10 @@ void GrDrawTarget::forwardCombine() {
///////////////////////////////////////////////////////////////////////////////
void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
void GrDrawTarget::clearStencilClip(const GrFixedClip& clip,
bool insideStencilMask,
GrRenderTarget* rt) {
GrBatch* batch = new GrClearStencilClipBatch(clip, insideStencilMask, rt);
this->recordBatch(batch, batch->bounds());
batch->unref();
}

View File

@ -215,7 +215,7 @@ private:
void addDependency(GrDrawTarget* dependedOn);
// Used only by drawContextPriv.
void clearStencilClip(const SkIRect&, bool insideClip, GrRenderTarget*);
void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
struct RecordedBatch {
sk_sp<GrBatch> fBatch;

View File

@ -10,13 +10,6 @@
#include "GrAppliedClip.h"
#include "GrDrawContext.h"
bool GrFixedClip::quickContains(const SkRect& rect) const {
if (fHasStencilClip) {
return false;
}
return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect);
}
void GrFixedClip::getConservativeBounds(int width, int height, SkIRect* devResult,
bool* isIntersectionOfRects) const {
devResult->setXYWH(0, 0, width, height);
@ -46,9 +39,10 @@ bool GrFixedClip::apply(GrContext*, GrDrawContext* drawContext, bool isHWAntiAli
}
}
if (fHasStencilClip) {
out->addStencilClip();
}
return true;
}
const GrFixedClip& GrFixedClip::Disabled() {
static const GrFixedClip disabled = GrFixedClip();
return disabled;
}

View File

@ -12,37 +12,30 @@
#include "GrTypesPriv.h"
/**
* GrFixedClip is a clip that can be represented by fixed-function hardware. It never modifies the
* stencil buffer itself, but can be configured to use whatever clip is already there.
* GrFixedClip is a clip that gets implemented by fixed-function hardware.
*/
class GrFixedClip final : public GrClip {
public:
GrFixedClip() : fHasStencilClip(false) {}
GrFixedClip(const SkIRect& scissorRect)
: fScissorState(scissorRect)
, fHasStencilClip(false) {}
GrFixedClip() = default;
explicit GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect) {}
void reset() {
fScissorState.setDisabled();
fHasStencilClip = false;
const GrScissorState& scissorState() const { return fScissorState; }
bool scissorEnabled() const { return fScissorState.enabled(); }
const SkIRect& scissorRect() const { SkASSERT(scissorEnabled()); return fScissorState.rect(); }
void disableScissor() { fScissorState.setDisabled(); }
bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& irect) {
return fScissorState.intersect(irect);
}
void reset(const SkIRect& scissorRect) {
fScissorState.set(scissorRect);
fHasStencilClip = false;
bool quickContains(const SkRect& rect) const final {
return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect);
}
void enableStencilClip() { fHasStencilClip = true; }
void disableStencilClip() { fHasStencilClip = false; }
bool quickContains(const SkRect&) const final;
void getConservativeBounds(int width, int height, SkIRect* devResult,
bool* isIntersectionOfRects) const final;
bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const override {
if (fHasStencilClip) {
return false;
}
if (fScissorState.enabled()) {
SkRect rect = SkRect::Make(fScissorState.rect());
if (!rect.intersects(rtBounds)) {
@ -55,12 +48,13 @@ public:
return false;
};
private:
bool apply(GrContext*, GrDrawContext*, bool useHWAA, bool hasUserStencilSettings,
GrAppliedClip* out) const final;
static const GrFixedClip& Disabled();
private:
GrScissorState fScissorState;
bool fHasStencilClip;
};
#endif

View File

@ -8,6 +8,7 @@
#include "GrGpuCommandBuffer.h"
#include "GrCaps.h"
#include "GrFixedClip.h"
#include "GrGpu.h"
#include "GrPrimitiveProcessor.h"
#include "GrRenderTarget.h"
@ -18,17 +19,19 @@ void GrGpuCommandBuffer::submit(const SkIRect& bounds) {
this->onSubmit(bounds);
}
void GrGpuCommandBuffer::clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget) {
SkASSERT(renderTarget);
SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
this->onClear(renderTarget, rect, color);
void GrGpuCommandBuffer::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* rt) {
SkASSERT(rt);
SkASSERT(!clip.scissorEnabled() ||
(SkIRect::MakeWH(rt->width(), rt->height()).contains(clip.scissorRect()) &&
SkIRect::MakeWH(rt->width(), rt->height()) != clip.scissorRect()));
this->onClear(rt, clip, color);
}
void GrGpuCommandBuffer::clearStencilClip(const SkIRect& rect,
bool insideClip,
GrRenderTarget* renderTarget) {
SkASSERT(renderTarget);
this->onClearStencilClip(renderTarget, rect, insideClip);
void GrGpuCommandBuffer::clearStencilClip(const GrFixedClip& clip,
bool insideStencilMask,
GrRenderTarget* rt) {
SkASSERT(rt);
this->onClearStencilClip(rt, clip, insideStencilMask);
}

View File

@ -10,6 +10,7 @@
#include "GrColor.h"
class GrFixedClip;
class GrGpu;
class GrMesh;
class GrPipeline;
@ -65,9 +66,9 @@ public:
/**
* Clear the passed in render target. Ignores the draw state and clip.
*/
void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget);
void clear(const GrFixedClip&, GrColor, GrRenderTarget*);
void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget);
void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
/**
* Discards the contents render target. nullptr indicates that the current render target should
* be discarded.
@ -86,9 +87,11 @@ private:
int meshCount) = 0;
// overridden by backend-specific derived class to perform the clear.
virtual void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) = 0;
virtual void onClear(GrRenderTarget*, const GrFixedClip&, GrColor) = 0;
virtual void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) = 0;
virtual void onClearStencilClip(GrRenderTarget*,
const GrFixedClip&,
bool insideStencilMask) = 0;
};

View File

@ -185,7 +185,7 @@ public:
struct StencilPathArgs {
GrResourceProvider* fResourceProvider;
GrDrawContext* fDrawContext;
const GrFixedClip* fClip;
const GrClip* fClip;
const SkMatrix* fViewMatrix;
bool fIsAA;
const GrShape* fShape;

View File

@ -10,6 +10,7 @@
#include "GrBatch.h"
#include "GrBatchFlushState.h"
#include "GrFixedClip.h"
#include "GrGpu.h"
#include "GrGpuCommandBuffer.h"
#include "GrRenderTarget.h"
@ -18,8 +19,12 @@ class GrClearBatch final : public GrBatch {
public:
DEFINE_BATCH_CLASS_ID
static sk_sp<GrClearBatch> Make(const SkIRect& rect, GrColor color, GrRenderTarget* rt) {
return sk_sp<GrClearBatch>(new GrClearBatch(rect, color, rt));
static sk_sp<GrClearBatch> Make(const GrFixedClip& clip, GrColor color, GrRenderTarget* rt) {
sk_sp<GrClearBatch> batch(new GrClearBatch(clip, color, rt));
if (!batch->renderTarget()) {
return nullptr; // The clip did not contain any pixels within the render target.
}
return batch;
}
const char* name() const override { return "Clear"; }
@ -28,10 +33,12 @@ public:
GrRenderTarget* renderTarget() const override { return fRenderTarget.get(); }
SkString dumpInfo() const override {
SkString string;
string.printf("Color: 0x%08x, Rect [L: %d, T: %d, R: %d, B: %d], RT: %d",
fColor, fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom,
fRenderTarget.get()->getUniqueID());
SkString string("Scissor [");
if (fClip.scissorEnabled()) {
const SkIRect& r = fClip.scissorRect();
string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom);
}
string.appendf("], Color: 0x%08x, RT: %d", fColor, fRenderTarget.get()->getUniqueID());
string.append(INHERITED::dumpInfo());
return string;
}
@ -39,12 +46,23 @@ public:
void setColor(GrColor color) { fColor = color; }
private:
GrClearBatch(const SkIRect& rect, GrColor color, GrRenderTarget* rt)
GrClearBatch(const GrFixedClip& clip, GrColor color, GrRenderTarget* rt)
: INHERITED(ClassID())
, fRect(rect)
, fColor(color)
, fRenderTarget(rt) {
this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsZeroArea::kNo);
, fClip(clip)
, fColor(color) {
SkIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height());
if (fClip.scissorEnabled()) {
// Don't let scissors extend outside the RT. This may improve batching.
if (!fClip.intersect(rtRect)) {
return;
}
if (fClip.scissorRect() == rtRect) {
fClip.disableScissor();
}
}
this->setBounds(SkRect::Make(fClip.scissorEnabled() ? fClip.scissorRect() : rtRect),
HasAABloat::kNo, IsZeroArea::kNo);
fRenderTarget.reset(rt);
}
bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
@ -53,24 +71,31 @@ private:
// same color.
GrClearBatch* cb = t->cast<GrClearBatch>();
SkASSERT(cb->fRenderTarget == fRenderTarget);
if (cb->fRect.contains(fRect)) {
fRect = cb->fRect;
if (cb->contains(this)) {
fClip = cb->fClip;
this->replaceBounds(*t);
fColor = cb->fColor;
return true;
} else if (cb->fColor == fColor && fRect.contains(cb->fRect)) {
} else if (cb->fColor == fColor && this->contains(cb)) {
return true;
}
return false;
}
bool contains(const GrClearBatch* that) const {
// The constructor ensures that scissor gets disabled on any clip that fills the entire RT.
return !fClip.scissorEnabled() ||
(that->fClip.scissorEnabled() &&
fClip.scissorRect().contains(that->fClip.scissorRect()));
}
void onPrepare(GrBatchFlushState*) override {}
void onDraw(GrBatchFlushState* state) override {
state->commandBuffer()->clear(fRect, fColor, fRenderTarget.get());
state->commandBuffer()->clear(fClip, fColor, fRenderTarget.get());
}
SkIRect fRect;
GrFixedClip fClip;
GrColor fColor;
GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;

View File

@ -10,6 +10,7 @@
#include "GrBatch.h"
#include "GrBatchFlushState.h"
#include "GrFixedClip.h"
#include "GrGpu.h"
#include "GrGpuCommandBuffer.h"
#include "GrRenderTarget.h"
@ -18,12 +19,14 @@ class GrClearStencilClipBatch final : public GrBatch {
public:
DEFINE_BATCH_CLASS_ID
GrClearStencilClipBatch(const SkIRect& rect, bool insideClip, GrRenderTarget* rt)
GrClearStencilClipBatch(const GrFixedClip& clip, bool insideStencilMask, GrRenderTarget* rt)
: INHERITED(ClassID())
, fRect(rect)
, fInsideClip(insideClip)
, fClip(clip)
, fInsideStencilMask(insideStencilMask)
, fRenderTarget(rt) {
this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsZeroArea::kNo);
const SkRect& bounds = fClip.scissorEnabled() ? SkRect::Make(fClip.scissorRect())
: SkRect::MakeIWH(rt->width(), rt->height());
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
}
const char* name() const override { return "ClearStencilClip"; }
@ -32,10 +35,12 @@ public:
GrRenderTarget* renderTarget() const override { return fRenderTarget.get(); }
SkString dumpInfo() const override {
SkString string;
string.printf("Rect [L: %d, T: %d, R: %d, B: %d], IC: %d, RT: %d",
fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom, fInsideClip,
fRenderTarget.get()->getUniqueID());
SkString string("Scissor [");
if (fClip.scissorEnabled()) {
const SkIRect& r = fClip.scissorRect();
string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom);
}
string.appendf("], IC: %d, RT: %d", fInsideStencilMask, fRenderTarget.get()->getUniqueID());
string.append(INHERITED::dumpInfo());
return string;
}
@ -46,11 +51,11 @@ private:
void onPrepare(GrBatchFlushState*) override {}
void onDraw(GrBatchFlushState* state) override {
state->commandBuffer()->clearStencilClip(fRect, fInsideClip, fRenderTarget.get());
state->commandBuffer()->clearStencilClip(fClip, fInsideStencilMask, fRenderTarget.get());
}
SkIRect fRect;
bool fInsideClip;
const GrFixedClip fClip;
const bool fInsideStencilMask;
GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
typedef GrBatch INHERITED;

View File

@ -11,6 +11,7 @@
#include "GrGLGpuCommandBuffer.h"
#include "GrGLStencilAttachment.h"
#include "GrGLTextureRenderTarget.h"
#include "GrFixedClip.h"
#include "GrGpuResourcePriv.h"
#include "GrMesh.h"
#include "GrPipeline.h"
@ -2197,17 +2198,15 @@ void GrGLGpu::disableScissor() {
}
}
void GrGLGpu::clear(const SkIRect& rect, GrColor color, GrRenderTarget* target) {
void GrGLGpu::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* target) {
this->handleDirtyContext();
// parent class should never let us get here with no RT
SkASSERT(target);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->flushRenderTarget(glRT, &rect);
GrScissorState scissorState;
scissorState.set(rect);
this->flushScissor(scissorState, glRT->getViewport(), glRT->origin());
this->flushRenderTarget(glRT, clip.scissorEnabled() ? &clip.scissorRect() : nullptr);
this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin());
this->disableWindowRectangles();
GrGLfloat r, g, b, a;
@ -2240,7 +2239,9 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) {
fHWStencilSettings.invalidate();
}
void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* target) {
void GrGLGpu::clearStencilClip(const GrFixedClip& clip,
bool insideStencilMask,
GrRenderTarget* target) {
SkASSERT(target);
this->handleDirtyContext();
@ -2261,7 +2262,7 @@ void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTar
static const GrGLint clipStencilMask = ~0;
#endif
GrGLint value;
if (insideClip) {
if (insideStencilMask) {
value = (1 << (stencilBitCount - 1));
} else {
value = 0;
@ -2269,9 +2270,7 @@ void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTar
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
GrScissorState scissorState;
scissorState.set(rect);
this->flushScissor(scissorState, glRT->getViewport(), glRT->origin());
this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin());
this->disableWindowRectangles();
GL_CALL(StencilMask((uint32_t) clipStencilMask));

View File

@ -105,12 +105,12 @@ public:
// The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
// Thus this is the implementation of the clear call for the corresponding passthrough function
// on GrGLGpuCommandBuffer.
void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget);
void clear(const GrFixedClip&, GrColor, GrRenderTarget*);
// The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
// Thus this is the implementation of the clearStencil call for the corresponding passthrough
// function on GrGLGpuCommandBuffer.
void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget);
void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
const GrGLContext* glContextForTesting() const override {
return &this->glContext();

View File

@ -39,12 +39,14 @@ private:
fGpu->draw(pipeline, primProc, mesh, meshCount);
}
void onClear(GrRenderTarget* rt, const SkIRect& rect, GrColor color) override {
fGpu->clear(rect, color, rt);
void onClear(GrRenderTarget* rt, const GrFixedClip& clip, GrColor color) override {
fGpu->clear(clip, color, rt);
}
void onClearStencilClip(GrRenderTarget* rt, const SkIRect& rect, bool insideClip) override {
fGpu->clearStencilClip(rect, insideClip, rt);
void onClearStencilClip(GrRenderTarget* rt,
const GrFixedClip& clip,
bool insideStencilMask) override {
fGpu->clearStencilClip(clip, insideStencilMask, rt);
}
GrGLGpu* fGpu;

View File

@ -7,6 +7,7 @@
#include "GrVkGpuCommandBuffer.h"
#include "GrFixedClip.h"
#include "GrMesh.h"
#include "GrPipeline.h"
#include "GrRenderTargetPriv.h"
@ -166,8 +167,8 @@ void GrVkGpuCommandBuffer::discard(GrRenderTarget* target) {
}
void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target,
const SkIRect& rect,
bool insideClip) {
const GrFixedClip& clip,
bool insideStencilMask) {
SkASSERT(target);
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
@ -182,7 +183,7 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target,
VkClearDepthStencilValue vkStencilColor;
memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
if (insideClip) {
if (insideStencilMask) {
vkStencilColor.stencil = (1 << (stencilBitCount - 1));
} else {
vkStencilColor.stencil = 0;
@ -190,11 +191,15 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target,
VkClearRect clearRect;
// Flip rect if necessary
SkIRect vkRect = rect;
if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
vkRect.fTop = vkRT->height() - rect.fBottom;
vkRect.fBottom = vkRT->height() - rect.fTop;
SkIRect vkRect;
if (!clip.scissorEnabled()) {
vkRect.setXYWH(0, 0, vkRT->width(), vkRT->height());
} else if (kBottomLeft_GrSurfaceOrigin != vkRT->origin()) {
vkRect = clip.scissorRect();
} else {
const SkIRect& scissor = clip.scissorRect();
vkRect.setLTRB(scissor.fLeft, vkRT->height() - scissor.fBottom,
scissor.fRight, vkRT->height() - scissor.fTop);
}
clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
@ -215,7 +220,7 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target,
fIsEmpty = false;
}
void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const GrFixedClip& clip, GrColor color) {
// parent class should never let us get here with no RT
SkASSERT(target);
@ -224,7 +229,7 @@ void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect,
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
if (fIsEmpty && rect.width() == target->width() && rect.height() == target->height()) {
if (fIsEmpty && !clip.scissorEnabled()) {
// We will change the render pass to do a clear load instead
GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE);
@ -259,10 +264,15 @@ void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect,
// We always do a sub rect clear with clearAttachments since we are inside a render pass
VkClearRect clearRect;
// Flip rect if necessary
SkIRect vkRect = rect;
if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
vkRect.fTop = vkRT->height() - rect.fBottom;
vkRect.fBottom = vkRT->height() - rect.fTop;
SkIRect vkRect;
if (!clip.scissorEnabled()) {
vkRect.setXYWH(0, 0, vkRT->width(), vkRT->height());
} else if (kBottomLeft_GrSurfaceOrigin != vkRT->origin()) {
vkRect = clip.scissorRect();
} else {
const SkIRect& scissor = clip.scissorRect();
vkRect.setLTRB(scissor.fLeft, vkRT->height() - scissor.fBottom,
scissor.fRight, vkRT->height() - scissor.fTop);
}
clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };

View File

@ -52,9 +52,9 @@ private:
const GrMesh* mesh,
int meshCount) override;
void onClear(GrRenderTarget* rt, const SkIRect& rect, GrColor color) override;
void onClear(GrRenderTarget* rt, const GrFixedClip&, GrColor color) override;
void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
void onClearStencilClip(GrRenderTarget*, const GrFixedClip&, bool insideStencilMask) override;
const GrVkRenderPass* fRenderPass;
GrVkSecondaryCommandBuffer* fCommandBuffer;