Add GrSurfaceFillContext
This is a new base class for GrSurfaceDrawContext. It allows any
alpha-type but is restricted to non-blending fills of irects using FPs,
clears,and discards.
Bug: skia:11019
Change-Id: I229ce5f452e66796e2fa5c0e7a6ddccbf23bef5c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341680
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrSurfaceDrawContext.cpp b/src/gpu/GrSurfaceDrawContext.cpp
index 31c5d34..2a07d0d 100644
--- a/src/gpu/GrSurfaceDrawContext.cpp
+++ b/src/gpu/GrSurfaceDrawContext.cpp
@@ -73,7 +73,6 @@
#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner())
#define RETURN_IF_ABANDONED if (fContext->abandoned()) { return; }
#define RETURN_FALSE_IF_ABANDONED if (fContext->abandoned()) { return false; }
-#define RETURN_NULL_IF_ABANDONED if (fContext->abandoned()) { return nullptr; }
//////////////////////////////////////////////////////////////////////////////
@@ -202,43 +201,6 @@
surfaceProps);
}
-static inline GrColorType color_type_fallback(GrColorType ct) {
- switch (ct) {
- // kRGBA_8888 is our default fallback for many color types that may not have renderable
- // backend formats.
- case GrColorType::kAlpha_8:
- case GrColorType::kBGR_565:
- case GrColorType::kABGR_4444:
- case GrColorType::kBGRA_8888:
- case GrColorType::kRGBA_1010102:
- case GrColorType::kBGRA_1010102:
- case GrColorType::kRGBA_F16:
- case GrColorType::kRGBA_F16_Clamped:
- return GrColorType::kRGBA_8888;
- case GrColorType::kAlpha_F16:
- return GrColorType::kRGBA_F16;
- case GrColorType::kGray_8:
- return GrColorType::kRGB_888x;
- default:
- return GrColorType::kUnknown;
- }
-}
-
-std::tuple<GrColorType, GrBackendFormat> GrSurfaceDrawContext::GetFallbackColorTypeAndFormat(
- GrImageContext* context, GrColorType colorType, int sampleCnt) {
- auto caps = context->priv().caps();
- do {
- auto format = caps->getDefaultBackendFormat(colorType, GrRenderable::kYes);
- // We continue to the fallback color type if there no default renderable format or we
- // requested msaa and the format doesn't support msaa.
- if (format.isValid() && caps->isFormatRenderable(format, sampleCnt)) {
- return {colorType, format};
- }
- colorType = color_type_fallback(colorType);
- } while (colorType != GrColorType::kUnknown);
- return {GrColorType::kUnknown, {}};
-}
-
std::unique_ptr<GrSurfaceDrawContext> GrSurfaceDrawContext::MakeWithFallback(
GrRecordingContext* context,
GrColorType colorType,
@@ -326,28 +288,16 @@
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps,
bool flushTimeOpsTask)
- : GrSurfaceContext(context,
- std::move(readView),
- {colorType, kPremul_SkAlphaType, std::move(colorSpace)})
- , fWriteView(std::move(writeView))
+ : GrSurfaceFillContext(context,
+ std::move(readView),
+ std::move(writeView),
+ {colorType, kPremul_SkAlphaType, std::move(colorSpace)},
+ flushTimeOpsTask)
, fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
- , fFlushTimeOpsTask(flushTimeOpsTask)
, fGlyphPainter(*this) {
- fOpsTask = sk_ref_sp(context->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
- SkASSERT(this->asSurfaceProxy() == fWriteView.proxy());
- SkASSERT(this->origin() == fWriteView.origin());
-
SkDEBUGCODE(this->validate();)
}
-#ifdef SK_DEBUG
-void GrSurfaceDrawContext::onValidate() const {
- if (fOpsTask && !fOpsTask->isClosed()) {
- SkASSERT(this->drawingManager()->getLastRenderTask(fWriteView.proxy()) == fOpsTask.get());
- }
-}
-#endif
-
GrSurfaceDrawContext::~GrSurfaceDrawContext() {
ASSERT_SINGLE_OWNER
}
@@ -371,27 +321,6 @@
return GrMipmapped::kNo;
}
-GrOpsTask* GrSurfaceDrawContext::getOpsTask() {
- ASSERT_SINGLE_OWNER
- SkDEBUGCODE(this->validate();)
-
- if (!fOpsTask || fOpsTask->isClosed()) {
- sk_sp<GrOpsTask> newOpsTask = this->drawingManager()->newOpsTask(this->writeSurfaceView(),
- fFlushTimeOpsTask);
- if (fOpsTask && fNumStencilSamples > 0) {
- // Store the stencil values in memory upon completion of fOpsTask.
- fOpsTask->setMustPreserveStencil();
- // Reload the stencil buffer content at the beginning of newOpsTask.
- // FIXME: Could the topo sort insert a task between these two that modifies the stencil
- // values?
- newOpsTask->setInitialStencilContent(GrOpsTask::StencilContent::kPreserved);
- }
- fOpsTask = std::move(newOpsTask);
- }
- SkASSERT(!fOpsTask->isClosed());
- return fOpsTask.get();
-}
-
static SkColor compute_canonical_color(const SkPaint& paint, bool lcd) {
SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint);
if (lcd) {
@@ -516,99 +445,6 @@
}
}
-void GrSurfaceDrawContext::discard() {
- ASSERT_SINGLE_OWNER
- RETURN_IF_ABANDONED
- SkDEBUGCODE(this->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceDrawContext", "discard", fContext);
-
- AutoCheckFlush acf(this->drawingManager());
-
- this->getOpsTask()->discard();
-}
-
-static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
- paint->setColor4f(color);
- if (color.isOpaque()) {
- // Can just rely on the src-over blend mode to do the right thing
- paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
- } else {
- // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
- // were src blended
- paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
- }
-}
-
-// NOTE: We currently pass the premul color unmodified to the gpu, since we assume the GrRTC has a
-// premul alpha type. If we ever support different alpha type render targets, this function should
-// transform the color as appropriate.
-void GrSurfaceDrawContext::internalClear(const SkIRect* scissor,
- const SkPMColor4f& color,
- bool upgradePartialToFull) {
- ASSERT_SINGLE_OWNER
- RETURN_IF_ABANDONED
- SkDEBUGCODE(this->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceDrawContext", "clear", fContext);
-
- // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
- // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
- // supports then. Drawing an axis-aligned rect is the fallback path.
- GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
- if (scissor && !scissorState.set(*scissor)) {
- // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
- // except clear ops are not draw ops).
- return;
- }
-
- // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
- // the test. We only do this when the clear would be handled by a load op or natively.
- if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
- if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
- this->caps()->shouldInitializeTextures())) {
- // TODO: wrt the shouldInitializeTextures path, it would be more performant to
- // only clear the entire target if we knew it had not been cleared before. As
- // is this could end up doing a lot of redundant clears.
- scissorState.setDisabled();
- } else {
- // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
- // render target to overflow into any approx-fit padding of the backing store dimensions
- scissorState.relaxTest(this->dimensions());
- }
- }
-
- if (!scissorState.enabled()) {
- // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
- // discard all prior ops in the current task since the color buffer will be overwritten.
- GrOpsTask* opsTask = this->getOpsTask();
- if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
- !this->caps()->performColorClearsAsDraws()) {
- SkPMColor4f clearColor = this->writeSurfaceView().swizzle().applyTo(color);
- // The op list was emptied and native clears are allowed, so just use the load op
- opsTask->setColorLoadOp(GrLoadOp::kClear, clearColor.array());
- return;
- } else {
- // Will use an op for the clear, reset the load op to discard since the op will
- // blow away the color buffer contents
- opsTask->setColorLoadOp(GrLoadOp::kDiscard);
- }
- }
-
- // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
- // as a load op.
- bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
- (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
- if (clearAsDraw) {
- GrPaint paint;
- clear_to_grpaint(color, &paint);
- this->addDrawOp(nullptr,
- GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
- SkRect::Make(scissorState.rect())));
- } else {
- SkPMColor4f clearColor = this->writeSurfaceView().swizzle().applyTo(color);
- this->addOp(GrClearOp::MakeColor(fContext, scissorState, clearColor.array()));
- }
-}
-
void GrSurfaceDrawContext::drawPaint(const GrClip* clip,
GrPaint&& paint,
const SkMatrix& viewMatrix) {
@@ -759,7 +595,7 @@
// Since the cropped quad became a rectangle which covered the bounds of the rrect,
// we can draw the rrect directly and ignore the edge flags
GrPaint paint;
- clear_to_grpaint(*constColor, &paint);
+ ClearToGrPaint(constColor->array(), &paint);
this->drawRRect(nullptr, std::move(paint), result.fAA, SkMatrix::I(), result.fRRect,
GrStyle::SimpleFill());
return QuadOptimization::kSubmitted;
@@ -926,8 +762,8 @@
int numRequiredSamples = this->numSamples();
if (useMixedSamplesIfNotMSAA && 1 == numRequiredSamples) {
SkASSERT(this->asRenderTargetProxy()->canUseMixedSamples(*this->caps()));
- numRequiredSamples = this->caps()->internalMultisampleCount(
- this->asSurfaceProxy()->backendFormat());
+ numRequiredSamples =
+ this->caps()->internalMultisampleCount(this->asSurfaceProxy()->backendFormat());
}
SkASSERT(numRequiredSamples > 0);
@@ -1984,12 +1820,6 @@
}
}
-void GrSurfaceDrawContext::addOp(GrOp::Owner op) {
- GrDrawingManager* drawingMgr = this->drawingManager();
- this->getOpsTask()->addOp(drawingMgr,
- std::move(op), GrTextureResolveManager(drawingMgr), *this->caps());
-}
-
void GrSurfaceDrawContext::addDrawOp(const GrClip* clip,
GrOp::Owner op,
const std::function<WillAddOpFn>& willAddFn) {
@@ -2017,9 +1847,12 @@
bool skipDraw = false;
if (clip) {
// Have a complex clip, so defer to its early clip culling
- GrAAType aaType = usesHWAA ? GrAAType::kMSAA :
- (op->hasAABloat() ? GrAAType::kCoverage :
- GrAAType::kNone);
+ GrAAType aaType;
+ if (usesHWAA) {
+ aaType = GrAAType::kMSAA;
+ } else {
+ aaType = op->hasAABloat() ? GrAAType::kCoverage : GrAAType::kNone;
+ }
skipDraw = clip->apply(fContext, this, aaType, usesUserStencilBits,
&appliedClip, &bounds) == GrClip::Effect::kClippedOut;
} else {
@@ -2125,31 +1958,3 @@
dstProxyView->setDstSampleType(fDstSampleType);
return true;
}
-
-bool GrSurfaceDrawContext::blitTexture(GrSurfaceProxyView view,
- const SkIRect& srcRect,
- const SkIPoint& dstPoint) {
- SkASSERT(view.asTextureProxy());
- SkIRect clippedSrcRect;
- SkIPoint clippedDstPoint;
- if (!GrClipSrcRectAndDstPoint(this->asSurfaceProxy()->dimensions(), view.proxy()->dimensions(),
- srcRect, dstPoint, &clippedSrcRect, &clippedDstPoint)) {
- return false;
- }
-
- GrPaint paint;
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-
- auto fp = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
- if (!fp) {
- return false;
- }
- paint.setColorFragmentProcessor(std::move(fp));
-
- this->fillRectToRect(
- nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
- SkRect::MakeXYWH(clippedDstPoint.fX, clippedDstPoint.fY, clippedSrcRect.width(),
- clippedSrcRect.height()),
- SkRect::Make(clippedSrcRect));
- return true;
-}