aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-03-06 16:17:12 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-03-07 15:11:24 +0000
commit467921e5e6479fe9cebba125657d8e33d89004ae (patch)
treebffd056e5d9ad99a50c1876d658f4b31d6721d15 /src
parent894d5611e54cbf62a03ff9ffb48a2302dda9ab86 (diff)
Move GrDrawOp pipeline/clip processing to GrRenderTargetContext
This is currently done in GrOpList. However, it can trigger resource creation, which in turn can trigger a flush. In the future flushing may destroy the op list. Change-Id: I21cb1e10060bf31c95431c0511fcfff637cd6498 Reviewed-on: https://skia-review.googlesource.com/9304 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrGpu.h8
-rw-r--r--src/gpu/GrRenderTargetContext.cpp234
-rw-r--r--src/gpu/GrRenderTargetContext.h501
-rw-r--r--src/gpu/GrRenderTargetOpList.cpp211
-rw-r--r--src/gpu/GrRenderTargetOpList.h38
-rw-r--r--src/gpu/gl/GrGLCaps.cpp61
-rw-r--r--src/gpu/gl/GrGLCaps.h2
-rw-r--r--src/gpu/gl/GrGLGpu.cpp59
-rw-r--r--src/gpu/gl/GrGLGpu.h2
-rw-r--r--src/gpu/vk/GrVkCaps.cpp20
-rw-r--r--src/gpu/vk/GrVkCaps.h2
-rw-r--r--src/gpu/vk/GrVkGpu.cpp17
-rw-r--r--src/gpu/vk/GrVkGpu.h2
13 files changed, 783 insertions, 374 deletions
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 5b69ead462..ed77fcd0d3 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -307,14 +307,6 @@ public:
GrPixelConfig config, GrBuffer* transferBuffer,
size_t offset, size_t rowBytes, GrFence* fence);
- /**
- * This is can be called before allocating a texture to be a dst for copySurface. This is only
- * used for doing dst copies needed in blends, thus the src is always a GrRenderTarget. It will
- * populate the origin, config, and flags fields of the desc such that copySurface can
- * efficiently succeed.
- */
- virtual bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const = 0;
-
// After the client interacts directly with the 3D context state the GrGpu
// must resync its internal state and assumptions about 3D context state.
// Each time this occurs the GrGpu bumps a timestamp.
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 1ddf8df511..bae2ea6307 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -6,8 +6,8 @@
*/
#include "GrRenderTargetContext.h"
+#include "GrAppliedClip.h"
#include "GrColor.h"
-#include "GrDrawOpTest.h"
#include "GrDrawingManager.h"
#include "GrFixedClip.h"
#include "GrGpuResourcePriv.h"
@@ -17,9 +17,14 @@
#include "GrRenderTargetContextPriv.h"
#include "GrRenderTargetPriv.h"
#include "GrResourceProvider.h"
+#include "GrStencilAttachment.h"
+#include "SkLatticeIter.h"
+#include "SkMatrixPriv.h"
#include "SkSurfacePriv.h"
-
+#include "effects/GrRRectEffect.h"
+#include "instanced/InstancedRendering.h"
#include "ops/GrClearOp.h"
+#include "ops/GrDrawOp.h"
#include "ops/GrDrawAtlasOp.h"
#include "ops/GrDrawVerticesOp.h"
#include "ops/GrLatticeOp.h"
@@ -28,20 +33,11 @@
#include "ops/GrRectOpFactory.h"
#include "ops/GrRegionOp.h"
#include "ops/GrShadowRRectOp.h"
-
-#include "effects/GrRRectEffect.h"
-
-#include "instanced/InstancedRendering.h"
-
+#include "ops/GrStencilPathOp.h"
#include "text/GrAtlasTextContext.h"
#include "text/GrStencilAndCoverTextContext.h"
-
#include "../private/GrAuditTrail.h"
-#include "SkGr.h"
-#include "SkLatticeIter.h"
-#include "SkMatrixPriv.h"
-
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
#define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
@@ -523,7 +519,7 @@ bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
if (ss) {
pipelineBuilder.setUserStencil(ss);
}
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return true;
}
}
@@ -540,7 +536,7 @@ bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
if (ss) {
pipelineBuilder.setUserStencil(ss);
}
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return true;
}
}
@@ -663,7 +659,7 @@ void GrRenderTargetContext::drawRect(const GrClip& clip,
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -699,9 +695,55 @@ void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
GrAAType aaType,
const SkMatrix& viewMatrix,
const GrPath* path) {
+ ASSERT_SINGLE_OWNER_PRIV
+ RETURN_IF_ABANDONED_PRIV
+ SkDEBUGCODE(fRenderTargetContext->validate();)
+ GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
+ "GrRenderTargetContext::stencilPath");
+
SkASSERT(aaType != GrAAType::kCoverage);
- fRenderTargetContext->getOpList()->stencilPath(fRenderTargetContext, clip, aaType, viewMatrix,
- path);
+
+ bool useHWAA = GrAATypeIsHW(aaType);
+ // TODO: extract portions of checkDraw that are relevant to path stenciling.
+ SkASSERT(path);
+ SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
+
+ // FIXME: Use path bounds instead of this WAR once
+ // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
+ SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
+
+ // Setup clip
+ GrAppliedClip appliedClip(bounds);
+ if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
+ &appliedClip)) {
+ return;
+ }
+
+ // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
+ // attempt this in a situation that would require coverage AA.
+ SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
+
+ GrRenderTarget* rt = fRenderTargetContext->accessRenderTarget();
+ if (!rt) {
+ return;
+ }
+ GrStencilAttachment* stencilAttachment =
+ fRenderTargetContext->fContext->resourceProvider()->attachStencilAttachment(rt);
+ if (!stencilAttachment) {
+ SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
+ return;
+ }
+
+ std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
+ useHWAA,
+ path->getFillType(),
+ appliedClip.hasStencilClip(),
+ stencilAttachment->bits(),
+ appliedClip.scissorState(),
+ fRenderTargetContext->accessRenderTarget(),
+ path);
+ op->setClippedBounds(appliedClip.clippedDrawBounds());
+ fRenderTargetContext->getOpList()->recordOp(std::move(op), fRenderTargetContext);
}
void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
@@ -779,7 +821,7 @@ void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
&aaType));
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -838,7 +880,7 @@ void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
&aaType));
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -854,7 +896,7 @@ void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
std::unique_ptr<GrDrawOp> op =
GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
@@ -904,7 +946,7 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip,
return;
}
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
void GrRenderTargetContext::drawVertices(const GrClip& clip,
@@ -926,7 +968,7 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip,
return;
}
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
///////////////////////////////////////////////////////////////////////////////
@@ -948,7 +990,7 @@ void GrRenderTargetContext::drawAtlas(const GrClip& clip,
std::unique_ptr<GrDrawOp> op =
GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
///////////////////////////////////////////////////////////////////////////////
@@ -993,7 +1035,7 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
fInstancedPipelineInfo, &aaType));
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, *clip, std::move(op));
return;
}
}
@@ -1009,7 +1051,7 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
shaderCaps);
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, *clip, std::move(op));
return;
}
}
@@ -1047,7 +1089,7 @@ void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
blurRadius, stroke, shaderCaps);
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -1071,7 +1113,7 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
&aaType));
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return true;
}
}
@@ -1191,7 +1233,7 @@ void GrRenderTargetContext::drawRegion(const GrClip& clip,
std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
void GrRenderTargetContext::drawOval(const GrClip& clip,
@@ -1222,7 +1264,7 @@ void GrRenderTargetContext::drawOval(const GrClip& clip,
fInstancedPipelineInfo, &aaType));
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -1234,7 +1276,7 @@ void GrRenderTargetContext::drawOval(const GrClip& clip,
GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -1274,7 +1316,7 @@ void GrRenderTargetContext::drawArc(const GrClip& clip,
shaderCaps);
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -1302,7 +1344,7 @@ void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
imageHeight, std::move(iter), dst);
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
void GrRenderTargetContext::prepareForExternalIO() {
@@ -1339,7 +1381,7 @@ void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
if (ss) {
pipelineBuilder.setUserStencil(ss);
}
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
// Can 'path' be drawn as a pair of filled nested rectangles?
@@ -1419,7 +1461,7 @@ void GrRenderTargetContext::drawPath(const GrClip& clip,
GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
}
return;
}
@@ -1433,7 +1475,7 @@ void GrRenderTargetContext::drawPath(const GrClip& clip,
paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
if (op) {
GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ this->addDrawOp(pipelineBuilder, clip, std::move(op));
return;
}
}
@@ -1605,6 +1647,32 @@ void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
pr->drawPath(args);
}
+static void op_bounds(SkRect* bounds, const GrOp* op) {
+ *bounds = op->bounds();
+ if (op->hasZeroArea()) {
+ if (op->hasAABloat()) {
+ bounds->outset(0.5f, 0.5f);
+ } else {
+ // We don't know which way the particular GPU will snap lines or points at integer
+ // coords. So we ensure that the bounds is large enough for either snap.
+ SkRect before = *bounds;
+ bounds->roundOut(bounds);
+ if (bounds->fLeft == before.fLeft) {
+ bounds->fLeft -= 1;
+ }
+ if (bounds->fTop == before.fTop) {
+ bounds->fTop -= 1;
+ }
+ if (bounds->fRight == before.fRight) {
+ bounds->fRight += 1;
+ }
+ if (bounds->fBottom == before.fBottom) {
+ bounds->fBottom += 1;
+ }
+ }
+ }
+}
+
void GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
std::unique_ptr<GrDrawOp> op) {
ASSERT_SINGLE_OWNER
@@ -1612,5 +1680,99 @@ void GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
SkDEBUGCODE(this->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
- this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+ // Setup clip
+ SkRect bounds;
+ op_bounds(&bounds, op.get());
+ GrAppliedClip appliedClip(bounds);
+ if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
+ pipelineBuilder.hasUserStencilSettings(), &appliedClip)) {
+ return;
+ }
+
+ // This forces instantiation of the render target. Pipeline creation is moving to flush time
+ // by which point instantiation must have occurred anyway.
+ GrRenderTarget* rt = this->accessRenderTarget();
+ if (!rt) {
+ return;
+ }
+
+ GrResourceProvider* resourceProvider = fContext->resourceProvider();
+ if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
+ if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
+ SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
+ return;
+ }
+ }
+
+ GrProcessorSet::FragmentProcessorAnalysis analysis;
+ op->analyzeProcessors(&analysis, pipelineBuilder.processors(), appliedClip, *this->caps());
+
+ GrPipeline::InitArgs args;
+ pipelineBuilder.getPipelineInitArgs(&args);
+ args.fAppliedClip = &appliedClip;
+ args.fRenderTarget = rt;
+ args.fCaps = this->caps();
+ args.fAnalysis = &analysis;
+
+ if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), analysis)) {
+ this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
+ if (!args.fDstTexture.texture()) {
+ return;
+ }
+ }
+ op->initPipeline(args);
+ // TODO: We need to add pipeline dependencies on textures, etc before recording this op.
+ op->setClippedBounds(appliedClip.clippedDrawBounds());
+ this->getOpList()->addOp(std::move(op), this);
+}
+
+void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
+ const SkRect& opBounds,
+ GrXferProcessor::DstTexture* dstTexture) {
+ if (this->caps()->textureBarrierSupport()) {
+ if (GrTexture* rtTex = rt->asTexture()) {
+ // The render target is a texture, so we can read from it directly in the shader. The XP
+ // will be responsible to detect this situation and request a texture barrier.
+ dstTexture->setTexture(sk_ref_sp(rtTex));
+ dstTexture->setOffset(0, 0);
+ return;
+ }
+ }
+
+ SkIRect copyRect;
+ clip.getConservativeBounds(rt->width(), rt->height(), &copyRect);
+
+ SkIRect drawIBounds;
+ opBounds.roundOut(&drawIBounds);
+ if (!copyRect.intersect(drawIBounds)) {
+#ifdef SK_DEBUG
+ GrCapsDebugf(this->caps(), "Missed an early reject. "
+ "Bailing on draw from setupDstTexture.\n");
+#endif
+ return;
+ }
+
+ // MSAA consideration: When there is support for reading MSAA samples in the shader we could
+ // have per-sample dst values by making the copy multisampled.
+ GrSurfaceDesc desc;
+ if (!this->caps()->initDescForDstCopy(rt, &desc)) {
+ desc.fOrigin = kDefault_GrSurfaceOrigin;
+ desc.fFlags = kRenderTarget_GrSurfaceFlag;
+ desc.fConfig = rt->config();
+ }
+
+ desc.fWidth = copyRect.width();
+ desc.fHeight = copyRect.height();
+
+ static const uint32_t kFlags = 0;
+ sk_sp<GrTexture> copy(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
+
+ if (!copy) {
+ SkDebugf("Failed to create temporary copy of destination texture.\n");
+ return;
+ }
+ SkIPoint dstPoint = {0, 0};
+ this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
+ dstTexture->setTexture(std::move(copy));
+ dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
}
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
new file mode 100644
index 0000000000..d711c81456
--- /dev/null
+++ b/src/gpu/GrRenderTargetContext.h
@@ -0,0 +1,501 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRenderTargetContext_DEFINED
+#define GrRenderTargetContext_DEFINED
+
+#include "GrColor.h"
+#include "GrContext.h"
+#include "GrPaint.h"
+#include "GrSurfaceContext.h"
+#include "GrXferProcessor.h"
+#include "SkRefCnt.h"
+#include "SkSurfaceProps.h"
+#include "../private/GrInstancedPipelineInfo.h"
+#include "../private/GrRenderTargetProxy.h"
+
+class GrClip;
+class GrDrawingManager;
+class GrDrawOp;
+class GrFixedClip;
+class GrPipelineBuilder;
+class GrRenderTarget;
+class GrRenderTargetContextPriv;
+class GrRenderTargetOpList;
+class GrStyle;
+class GrSurface;
+class GrTextureProxy;
+struct GrUserStencilSettings;
+class SkDrawFilter;
+struct SkIPoint;
+struct SkIRect;
+class SkLatticeIter;
+class SkMatrix;
+class SkPaint;
+class SkPath;
+struct SkPoint;
+struct SkRect;
+class SkRegion;
+class SkRRect;
+struct SkRSXform;
+class SkTextBlob;
+class SkVertices;
+
+/**
+ * A helper object to orchestrate commands (draws, etc...) for GrSurfaces that are GrRenderTargets.
+ */
+class SK_API GrRenderTargetContext : public GrSurfaceContext {
+public:
+ ~GrRenderTargetContext() override;
+
+ // We use SkPaint rather than GrPaint here for two reasons:
+ // * The SkPaint carries extra text settings. If these were extracted to a lighter object
+ // we could use GrPaint except that
+ // * SkPaint->GrPaint conversion depends upon whether the glyphs are color or grayscale and
+ // this can vary within a text run.
+ virtual void drawText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
+ const char text[], size_t byteLength, SkScalar x, SkScalar y,
+ const SkIRect& clipBounds);
+ virtual void drawPosText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
+ const char text[], size_t byteLength, const SkScalar pos[],
+ int scalarsPerPosition, const SkPoint& offset,
+ const SkIRect& clipBounds);
+ virtual void drawTextBlob(const GrClip&, const SkPaint&,
+ const SkMatrix& viewMatrix, const SkTextBlob*,
+ SkScalar x, SkScalar y,
+ SkDrawFilter*, const SkIRect& clipBounds);
+
+ /**
+ * Provides a perfomance hint that the render target's contents are allowed
+ * to become undefined.
+ */
+ void discard();
+
+ /**
+ * Clear the entire or rect of the render target, ignoring any clips.
+ * @param rect the rect to clear or the whole thing if rect is NULL.
+ * @param color the color to clear to.
+ * @param canIgnoreRect allows partial clears to be converted to whole
+ * clears on platforms for which that is cheap
+ */
+ void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect);
+
+ /**
+ * Draw everywhere (respecting the clip) with the paint.
+ */
+ void drawPaint(const GrClip&, GrPaint&&, const SkMatrix& viewMatrix);
+
+ /**
+ * Draw the rect using a paint.
+ * @param paint describes how to color pixels.
+ * @param GrAA Controls whether rect is antialiased
+ * @param viewMatrix transformation matrix
+ * @param style The style to apply. Null means fill. Currently path effects are not
+ * allowed.
+ * The rects coords are used to access the paint (through texture matrix)
+ */
+ void drawRect(const GrClip&,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRect&,
+ const GrStyle* style = nullptr);
+
+ /**
+ * Maps a rectangle of shader coordinates to a rectangle and fills that rectangle.
+ *
+ * @param paint describes how to color pixels.
+ * @param GrAA Controls whether rect is antialiased
+ * @param viewMatrix transformation matrix which applies to rectToDraw
+ * @param rectToDraw the rectangle to draw
+ * @param localRect the rectangle of shader coordinates applied to rectToDraw
+ */
+ void fillRectToRect(const GrClip&,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRect& rectToDraw,
+ const SkRect& localRect);
+
+ /**
+ * Fills a rect with a paint and a localMatrix.
+ */
+ void fillRectWithLocalMatrix(const GrClip& clip,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const SkMatrix& localMatrix);
+
+ /**
+ * Draw a roundrect using a paint.
+ *
+ * @param paint describes how to color pixels.
+ * @param GrAA Controls whether rrect is antialiased.
+ * @param viewMatrix transformation matrix
+ * @param rrect the roundrect to draw
+ * @param style style to apply to the rrect. Currently path effects are not allowed.
+ */
+ void drawRRect(const GrClip&,
+ GrPaint&&,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRRect& rrect,
+ const GrStyle& style);
+
+ /**
+ * Draw a roundrect using a paint and a shadow shader. This is separate from drawRRect
+ * because it uses different underlying geometry and GeometryProcessor
+ *
+ * @param paint describes how to color pixels.
+ * @param viewMatrix transformation matrix
+ * @param rrect the roundrect to draw
+ * @param blurRadius amount of shadow blur to apply (in device space)
+ * @param style style to apply to the rrect. Currently path effects are not allowed.
+ */
+ void drawShadowRRect(const GrClip&,
+ GrPaint&&,
+ const SkMatrix& viewMatrix,
+ const SkRRect& rrect,
+ SkScalar blurRadius,
+ const GrStyle& style);
+
+ /**
+ * Shortcut for filling a SkPath consisting of nested rrects using a paint. The result is
+ * undefined if outer does not contain inner.
+ *
+ * @param paint describes how to color pixels.
+ * @param GrAA Controls whether rrects edges are antialiased
+ * @param viewMatrix transformation matrix
+ * @param outer the outer roundrect
+ * @param inner the inner roundrect
+ */
+ void drawDRRect(const GrClip&,
+ GrPaint&&,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRRect& outer,
+ const SkRRect& inner);
+
+ /**
+ * Draws a path.
+ *
+ * @param paint describes how to color pixels.
+ * @param GrAA Controls whether the path is antialiased.
+ * @param viewMatrix transformation matrix
+ * @param path the path to draw
+ * @param style style to apply to the path.
+ */
+ void drawPath(const GrClip&,
+ GrPaint&&,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkPath&,
+ const GrStyle& style);
+
+ enum class ColorArrayType {
+ kPremulGrColor,
+ kSkColor,
+ };
+ /**
+ * Draws vertices with a paint.
+ *
+ * @param paint describes how to color pixels.
+ * @param viewMatrix transformation matrix
+ * @param primitiveType primitives type to draw.
+ * @param vertexCount number of vertices.
+ * @param positions array of vertex positions, required.
+ * @param texCoords optional array of texture coordinates used
+ * to access the paint.
+ * @param colors optional array of per-vertex colors, supercedes
+ * the paint's color field.
+ * @param indices optional array of indices. If NULL vertices
+ * are drawn non-indexed.
+ * @param indexCount if indices is non-null then this is the
+ * number of indices.
+ * @param ColorArrayType Determines how the color array should be interpreted.
+ */
+ void drawVertices(const GrClip&,
+ GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ GrPrimitiveType primitiveType,
+ int vertexCount,
+ const SkPoint positions[],
+ const SkPoint texs[],
+ const uint32_t colors[],
+ const uint16_t indices[],
+ int indexCount,
+ ColorArrayType = ColorArrayType::kPremulGrColor);
+
+ /**
+ * Draws vertices with a paint.
+ *
+ * @param paint describes how to color pixels.
+ * @param viewMatrix transformation matrix
+ * @param veritces specifies the mesh to draw.
+ * @param flags A bitfield of options specified by SkCanvas::VerticesFlags.
+ */
+ void drawVertices(const GrClip&,
+ GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ sk_sp<SkVertices> vertices,
+ uint32_t flags);
+
+ /**
+ * Draws textured sprites from an atlas with a paint. This currently does not support AA for the
+ * sprite rectangle edges.
+ *
+ * @param paint describes how to color pixels.
+ * @param viewMatrix transformation matrix
+ * @param spriteCount number of sprites.
+ * @param xform array of compressed transformation data, required.
+ * @param texRect array of texture rectangles used to access the paint.
+ * @param colors optional array of per-sprite colors, supercedes
+ * the paint's color field.
+ */
+ void drawAtlas(const GrClip&,
+ GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ int spriteCount,
+ const SkRSXform xform[],
+ const SkRect texRect[],
+ const SkColor colors[]);
+
+ /**
+ * Draws a region.
+ *
+ * @param paint describes how to color pixels
+ * @param viewMatrix transformation matrix
+ * @param aa should the rects of the region be antialiased.
+ * @param region the region to be drawn
+ * @param style style to apply to the region
+ */
+ void drawRegion(const GrClip&,
+ GrPaint&& paint,
+ GrAA aa,
+ const SkMatrix& viewMatrix,
+ const SkRegion& region,
+ const GrStyle& style);
+
+ /**
+ * Draws an oval.
+ *
+ * @param paint describes how to color pixels.
+ * @param GrAA Controls whether the oval is antialiased.
+ * @param viewMatrix transformation matrix
+ * @param oval the bounding rect of the oval.
+ * @param style style to apply to the oval. Currently path effects are not allowed.
+ */
+ void drawOval(const GrClip&,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRect& oval,
+ const GrStyle& style);
+ /**
+ * Draws a partial arc of an oval.
+ *
+ * @param paint describes how to color pixels.
+ * @param GrGrAA Controls whether the arc is antialiased.
+ * @param viewMatrix transformation matrix.
+ * @param oval the bounding rect of the oval.
+ * @param startAngle starting angle in degrees.
+ * @param sweepAngle angle to sweep in degrees. Must be in (-360, 360)
+ * @param useCenter true means that the implied path begins at the oval center, connects as
+ * a line to the point indicated by the start contains the arc indicated by
+ * the sweep angle. If false the line beginning at the center point is
+ * omitted.
+ * @param style style to apply to the oval.
+ */
+ void drawArc(const GrClip&,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRect& oval,
+ SkScalar startAngle,
+ SkScalar sweepAngle,
+ bool useCenter,
+ const GrStyle& style);
+
+ /**
+ * Draw the image as a set of rects, specified by |iter|.
+ */
+ void drawImageLattice(const GrClip&,
+ GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ int imageWidth,
+ int imageHeight,
+ std::unique_ptr<SkLatticeIter> iter,
+ const SkRect& dst);
+
+ /**
+ * After this returns any pending surface IO will be issued to the backend 3D API and
+ * if the surface has MSAA it will be resolved.
+ */
+ void prepareForExternalIO();
+
+ bool isStencilBufferMultisampled() const {
+ return fRenderTargetProxy->isStencilBufferMultisampled();
+ }
+ bool isUnifiedMultisampled() const { return fRenderTargetProxy->isUnifiedMultisampled(); }
+ bool hasMixedSamples() const { return fRenderTargetProxy->isMixedSampled(); }
+
+ const GrCaps* caps() const { return fContext->caps(); }
+ const GrSurfaceDesc& desc() const { return fRenderTargetProxy->desc(); }
+ int width() const { return fRenderTargetProxy->width(); }
+ int height() const { return fRenderTargetProxy->height(); }
+ GrPixelConfig config() const { return fRenderTargetProxy->config(); }
+ int numColorSamples() const { return fRenderTargetProxy->numColorSamples(); }
+ const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
+ GrColorSpaceXform* getColorXformFromSRGB() const { return fColorXformFromSRGB.get(); }
+ GrSurfaceOrigin origin() const { return fRenderTargetProxy->origin(); }
+
+ bool wasAbandoned() const;
+
+ GrRenderTarget* instantiate();
+
+ GrRenderTarget* accessRenderTarget() {
+ // TODO: usage of this entry point needs to be reduced and potentially eliminated
+ // since it ends the deferral of the GrRenderTarget's allocation
+ return fRenderTargetProxy->instantiate(fContext->resourceProvider());
+ }
+
+ GrSurfaceProxy* asSurfaceProxy() override { return fRenderTargetProxy.get(); }
+ const GrSurfaceProxy* asSurfaceProxy() const override { return fRenderTargetProxy.get(); }
+ sk_sp<GrSurfaceProxy> asSurfaceProxyRef() override { return fRenderTargetProxy; }
+
+ GrTextureProxy* asTextureProxy() override;
+ sk_sp<GrTextureProxy> asTextureProxyRef() override;
+
+ GrRenderTargetProxy* asRenderTargetProxy() override { return fRenderTargetProxy.get(); }
+ sk_sp<GrRenderTargetProxy> asRenderTargetProxyRef() override { return fRenderTargetProxy; }
+
+ GrRenderTargetContext* asRenderTargetContext() override { return this; }
+
+ sk_sp<GrTexture> asTexture() {
+ if (!this->accessRenderTarget()) {
+ return nullptr;
+ }
+
+ // TODO: usage of this entry point needs to be reduced and potentially eliminated
+ // since it ends the deferral of the GrRenderTarget's allocation
+ // It's usage should migrate to asTextureProxyRef
+ return sk_ref_sp(this->accessRenderTarget()->asTexture());
+ }
+
+ // Provides access to functions that aren't part of the public API.
+ GrRenderTargetContextPriv priv();
+ const GrRenderTargetContextPriv priv() const;
+
+ bool isWrapped_ForTesting() const;
+
+protected:
+ GrRenderTargetContext(GrContext*, GrDrawingManager*, sk_sp<GrRenderTargetProxy>,
+ sk_sp<SkColorSpace>, const SkSurfaceProps*, GrAuditTrail*,
+ GrSingleOwner*);
+
+ SkDEBUGCODE(void validate() const;)
+
+private:
+ inline GrAAType decideAAType(GrAA aa, bool allowMixedSamples = false) {
+ if (GrAA::kNo == aa) {
+ return GrAAType::kNone;
+ }
+ if (this->isUnifiedMultisampled()) {
+ return GrAAType::kMSAA;
+ }
+ if (allowMixedSamples && this->isStencilBufferMultisampled()) {
+ return GrAAType::kMixedSamples;
+ }
+ return GrAAType::kCoverage;
+ }
+
+ friend class GrAtlasTextBlob; // for access to addDrawOp
+ friend class GrStencilAndCoverTextContext; // for access to addDrawOp
+
+ friend class GrDrawingManager; // for ctor
+ friend class GrRenderTargetContextPriv;
+ friend class GrSWMaskHelper; // for access to addDrawOp
+
+ // All the path renderers currently make their own ops
+ friend class GrSoftwarePathRenderer; // for access to addDrawOp
+ friend class GrAAConvexPathRenderer; // for access to addDrawOp
+ friend class GrDashLinePathRenderer; // for access to addDrawOp
+ friend class GrAAHairLinePathRenderer; // for access to addDrawOp
+ friend class GrAALinearizingConvexPathRenderer; // for access to addDrawOp
+ friend class GrAADistanceFieldPathRenderer; // for access to addDrawOp
+ friend class GrDefaultPathRenderer; // for access to addDrawOp
+ friend class GrMSAAPathRenderer; // for access to addDrawOp
+ friend class GrStencilAndCoverPathRenderer; // for access to addDrawOp
+ friend class GrTessellatingPathRenderer; // for access to addDrawOp
+ // for a unit test
+ friend void test_draw_op(GrContext*, GrRenderTargetContext*,
+ sk_sp<GrFragmentProcessor>, sk_sp<GrTextureProxy>);
+
+ void internalClear(const GrFixedClip&, const GrColor, bool canIgnoreClip);
+
+ // Only consumes the GrPaint if successful.
+ bool drawFilledDRRect(const GrClip& clip,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRRect& origOuter,
+ const SkRRect& origInner);
+
+ // Only consumes the GrPaint if successful.
+ bool drawFilledRect(const GrClip& clip,
+ GrPaint&& paint,
+ GrAA,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const GrUserStencilSettings* ss);
+
+ void drawNonAAFilledRect(const GrClip&,
+ GrPaint&&,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const SkRect* localRect,
+ const SkMatrix* localMatrix,
+ const GrUserStencilSettings* ss,
+ GrAAType hwOrNoneAAType);
+
+ void internalDrawPath(
+ const GrClip&, GrPaint&&, GrAA, const SkMatrix&, const SkPath&, const GrStyle&);
+
+ bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+ bool onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
+ size_t dstRowBytes, int x, int y) override;
+ bool onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
+ size_t srcRowBytes, int x, int y, uint32_t flags) override;
+
+ // This performs processing specific to GrDrawOp-derived ops before recording them into the
+ // op list.
+ void addDrawOp(const GrPipelineBuilder&, const GrClip&, std::unique_ptr<GrDrawOp>);
+
+ // Makes a copy of the dst if it is necessary for the draw and returns the texture that should
+ // be used by GrXferProcessor to access the destination color. If the texture is nullptr then
+ // a texture copy could not be made.
+ void setupDstTexture(GrRenderTarget*, const GrClip&, const SkRect& opBounds,
+ GrXferProcessor::DstTexture*);
+
+
+ GrRenderTargetOpList* getOpList();
+
+ sk_sp<GrRenderTargetProxy> fRenderTargetProxy;
+
+ // In MDB-mode the GrOpList can be closed by some other renderTargetContext that has picked
+ // it up. For this reason, the GrOpList should only ever be accessed via 'getOpList'.
+ GrRenderTargetOpList* fOpList;
+ GrInstancedPipelineInfo fInstancedPipelineInfo;
+
+ sk_sp<GrColorSpaceXform> fColorXformFromSRGB;
+ SkSurfaceProps fSurfaceProps;
+
+ typedef GrSurfaceContext INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 2b05a16b50..2c28406fd0 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -6,35 +6,17 @@
*/
#include "GrRenderTargetOpList.h"
-
-#include "GrAppliedClip.h"
#include "GrAuditTrail.h"
#include "GrCaps.h"
-#include "GrRenderTargetContext.h"
#include "GrGpu.h"
#include "GrGpuCommandBuffer.h"
-#include "GrPath.h"
-#include "GrPipeline.h"
-#include "GrMemoryPool.h"
-#include "GrPipelineBuilder.h"
#include "GrRenderTarget.h"
+#include "GrRenderTargetContext.h"
#include "GrResourceProvider.h"
-#include "GrRenderTargetPriv.h"
-#include "GrStencilAttachment.h"
-#include "GrSurfacePriv.h"
-#include "GrTexture.h"
-
-#include "SkStrokeRec.h"
-
#include "ops/GrClearOp.h"
#include "ops/GrClearStencilClipOp.h"
#include "ops/GrCopySurfaceOp.h"
#include "ops/GrDiscardOp.h"
-#include "ops/GrDrawOp.h"
-#include "ops/GrDrawPathOp.h"
-#include "ops/GrRectOpFactory.h"
-#include "ops/GrStencilPathOp.h"
-
#include "instanced/InstancedRendering.h"
using gr_instanced::InstancedRendering;
@@ -52,8 +34,6 @@ GrRenderTargetOpList::GrRenderTargetOpList(GrRenderTargetProxy* rtp, GrGpu* gpu,
, fGpu(SkRef(gpu))
, fResourceProvider(resourceProvider)
, fLastClipStackGenID(SK_InvalidUniqueID) {
- // TODO: Stop extracting the context (currently needed by GrClip)
- fContext = fGpu->getContext();
fMaxOpLookback = (options.fMaxOpCombineLookback < 0) ? kDefaultMaxOpLookback
: options.fMaxOpCombineLookback;
@@ -92,58 +72,6 @@ void GrRenderTargetOpList::dump() const {
}
#endif
-void GrRenderTargetOpList::setupDstTexture(GrRenderTarget* rt,
- const GrClip& clip,
- const SkRect& opBounds,
- GrXferProcessor::DstTexture* dstTexture) {
- if (this->caps()->textureBarrierSupport()) {
- if (GrTexture* rtTex = rt->asTexture()) {
- // The render target is a texture, so we can read from it directly in the shader. The XP
- // will be responsible to detect this situation and request a texture barrier.
- dstTexture->setTexture(sk_ref_sp(rtTex));
- dstTexture->setOffset(0, 0);
- return;
- }
- }
-
- SkIRect copyRect;
- clip.getConservativeBounds(rt->width(), rt->height(), &copyRect);
-
- SkIRect drawIBounds;
- opBounds.roundOut(&drawIBounds);
- if (!copyRect.intersect(drawIBounds)) {
-#ifdef SK_DEBUG
- GrCapsDebugf(this->caps(), "Missed an early reject. "
- "Bailing on draw from setupDstTexture.\n");
-#endif
- return;
- }
-
- // MSAA consideration: When there is support for reading MSAA samples in the shader we could
- // have per-sample dst values by making the copy multisampled.
- GrSurfaceDesc desc;
- if (!fGpu->initDescForDstCopy(rt, &desc)) {
- desc.fOrigin = kDefault_GrSurfaceOrigin;
- desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fConfig = rt->config();
- }
-
- desc.fWidth = copyRect.width();
- desc.fHeight = copyRect.height();
-
- static const uint32_t kFlags = 0;
- sk_sp<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
-
- if (!copy) {
- SkDebugf("Failed to create temporary copy of destination texture.\n");
- return;
- }
- SkIPoint dstPoint = {0, 0};
- this->copySurface(copy.get(), rt, copyRect, dstPoint);
- dstTexture->setTexture(std::move(copy));
- dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
-}
-
void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) {
// Semi-usually the GrOpLists are already closed at this point, but sometimes Ganesh
// needs to flush mid-draw. In that case, the SkGpuDevice's GrOpLists won't be closed
@@ -216,152 +144,19 @@ void GrRenderTargetOpList::reset() {
}
void GrRenderTargetOpList::abandonGpuResources() {
- if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
+ if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
InstancedRendering* ir = this->instancedRendering();
ir->resetGpuResources(InstancedRendering::ResetType::kAbandon);
}
}
void GrRenderTargetOpList::freeGpuResources() {
- if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
+ if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
InstancedRendering* ir = this->instancedRendering();
ir->resetGpuResources(InstancedRendering::ResetType::kDestroy);
}
}
-static void op_bounds(SkRect* bounds, const GrOp* op) {
- *bounds = op->bounds();
- if (op->hasZeroArea()) {
- if (op->hasAABloat()) {
- bounds->outset(0.5f, 0.5f);
- } else {
- // We don't know which way the particular GPU will snap lines or points at integer
- // coords. So we ensure that the bounds is large enough for either snap.
- SkRect before = *bounds;
- bounds->roundOut(bounds);
- if (bounds->fLeft == before.fLeft) {
- bounds->fLeft -= 1;
- }
- if (bounds->fTop == before.fTop) {
- bounds->fTop -= 1;
- }
- if (bounds->fRight == before.fRight) {
- bounds->fRight += 1;
- }
- if (bounds->fBottom == before.fBottom) {
- bounds->fBottom += 1;
- }
- }
- }
-}
-
-void GrRenderTargetOpList::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
- GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
- std::unique_ptr<GrDrawOp> op) {
- // Setup clip
- SkRect bounds;
- op_bounds(&bounds, op.get());
- GrAppliedClip appliedClip(bounds);
- if (!clip.apply(fContext, renderTargetContext, pipelineBuilder.isHWAntialias(),
- pipelineBuilder.hasUserStencilSettings(), &appliedClip)) {
- return;
- }
-
- if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
- if (!renderTargetContext->accessRenderTarget()) {
- return;
- }
-
- if (!fResourceProvider->attachStencilAttachment(
- renderTargetContext->accessRenderTarget())) {
- SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
- return;
- }
- }
-
- GrProcessorSet::FragmentProcessorAnalysis analysis;
- op->analyzeProcessors(&analysis, pipelineBuilder.processors(), appliedClip, *this->caps());
-
- GrPipeline::InitArgs args;
- pipelineBuilder.getPipelineInitArgs(&args);
- args.fAppliedClip = &appliedClip;
- // This forces instantiation of the render target. Pipeline creation is moving to flush time
- // by which point instantiation must have occurred anyway.
- args.fRenderTarget = renderTargetContext->accessRenderTarget();
- if (!args.fRenderTarget) {
- return;
- }
- args.fCaps = this->caps();
- args.fAnalysis = &analysis;
-
- if (!renderTargetContext->accessRenderTarget()) {
- return;
- }
-
- if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), analysis)) {
- this->setupDstTexture(renderTargetContext->accessRenderTarget(), clip, bounds,
- &args.fDstTexture);
- if (!args.fDstTexture.texture()) {
- return;
- }
- }
- op->initPipeline(args);
-
-#ifdef ENABLE_MDB
- SkASSERT(fSurface);
- op->pipeline()->addDependenciesTo(fSurface);
-#endif
- op->setClippedBounds(appliedClip.clippedDrawBounds());
- this->recordOp(std::move(op), renderTargetContext);
-}
-
-void GrRenderTargetOpList::stencilPath(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
- GrAAType aaType,
- const SkMatrix& viewMatrix,
- const GrPath* path) {
- bool useHWAA = GrAATypeIsHW(aaType);
- // TODO: extract portions of checkDraw that are relevant to path stenciling.
- SkASSERT(path);
- SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
-
- // FIXME: Use path bounds instead of this WAR once
- // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
- SkRect bounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height());
-
- // Setup clip
- GrAppliedClip appliedClip(bounds);
- if (!clip.apply(fContext, renderTargetContext, useHWAA, true, &appliedClip)) {
- return;
- }
-
- // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
- // attempt this in a situation that would require coverage AA.
- SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
-
- if (!renderTargetContext->accessRenderTarget()) {
- return;
- }
- GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment(
- renderTargetContext->accessRenderTarget());
- if (!stencilAttachment) {
- SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
- return;
- }
-
- std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
- useHWAA,
- path->getFillType(),
- appliedClip.hasStencilClip(),
- stencilAttachment->bits(),
- appliedClip.scissorState(),
- renderTargetContext->accessRenderTarget(),
- path);
- op->setClippedBounds(appliedClip.clippedDrawBounds());
- this->recordOp(std::move(op), renderTargetContext);
-}
-
void GrRenderTargetOpList::fullClear(GrRenderTargetContext* renderTargetContext, GrColor color) {
GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
// Currently this just inserts or updates the last clear op. However, once in MDB this can
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index 36bdc6bf55..e232547f70 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -8,19 +8,11 @@
#ifndef GrRenderTargetOpList_DEFINED
#define GrRenderTargetOpList_DEFINED
-#include "GrClip.h"
-#include "GrContext.h"
#include "GrOpList.h"
-#include "GrPathProcessor.h"
#include "GrPrimitiveProcessor.h"
#include "GrPathRendering.h"
-#include "GrXferProcessor.h"
-
-#include "ops/GrDrawOp.h"
-
#include "SkClipStack.h"
#include "SkMatrix.h"
-#include "SkPath.h"
#include "SkStringUtils.h"
#include "SkStrokeRec.h"
#include "SkTArray.h"
@@ -29,10 +21,8 @@
class GrAuditTrail;
class GrClearOp;
-class GrClip;
class GrCaps;
-class GrPath;
-class GrDrawPathOpBase;
+class GrClip;
class GrOp;
class GrPipelineBuilder;
class GrRenderTargetProxy;
@@ -77,26 +67,10 @@ public:
*/
const GrCaps* caps() const { return fGpu->caps(); }
- void addDrawOp(const GrPipelineBuilder&, GrRenderTargetContext*, const GrClip&,
- std::unique_ptr<GrDrawOp>);
-
void addOp(std::unique_ptr<GrOp> op, GrRenderTargetContext* renderTargetContext) {
this->recordOp(std::move(op), renderTargetContext);
}
- /**
- * Draws the path into user stencil bits. Upon return, all user stencil values
- * inside the path will be nonzero. The path's fill must be either even/odd or
- * winding (notnverse or hairline).It will respect the HW antialias boolean (if
- * possible in the 3D API). Note, we will never have an inverse fill with
- * stencil path.
- */
- void stencilPath(GrRenderTargetContext*,
- const GrClip&,
- GrAAType aa,
- const SkMatrix& viewMatrix,
- const GrPath*);
-
/** Clears the entire render target */
void fullClear(GrRenderTargetContext*, GrColor color);
@@ -136,14 +110,6 @@ private:
void forwardCombine();
- // Makes a copy of the dst if it is necessary for the draw and returns the texture that should
- // be used by GrXferProcessor to access the destination color. If the texture is nullptr then
- // a texture copy could not be made.
- void setupDstTexture(GrRenderTarget*,
- const GrClip&,
- const SkRect& opBounds,
- GrXferProcessor::DstTexture*);
-
// Used only via GrRenderTargetContextPriv.
void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTargetContext*);
@@ -159,8 +125,6 @@ private:
GrClearOp* fLastFullClearOp = nullptr;
GrGpuResource::UniqueID fLastFullClearRenderTargetID = GrGpuResource::UniqueID::InvalidID();
- // The context is only in service of the GrClip, remove once it doesn't need this.
- GrContext* fContext;
GrGpu* fGpu;
GrResourceProvider* fResourceProvider;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d2e18995a3..cb0d7899e7 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -5,16 +5,15 @@
* found in the LICENSE file.
*/
-
#include "GrGLCaps.h"
-
#include "GrContextOptions.h"
#include "GrGLContext.h"
#include "GrGLRenderTarget.h"
+#include "GrGLTexture.h"
#include "GrShaderCaps.h"
-#include "instanced/GLInstancedRendering.h"
#include "SkTSearch.h"
#include "SkTSort.h"
+#include "instanced/GLInstancedRendering.h"
GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
const GrGLContextInfo& ctxInfo,
@@ -2068,6 +2067,62 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
#endif
}
+bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
+ // If the src is a texture, we can implement the blit as a draw assuming the config is
+ // renderable.
+ if (src->asTexture() && this->isConfigRenderable(src->config(), false)) {
+ desc->fOrigin = kDefault_GrSurfaceOrigin;
+ desc->fFlags = kRenderTarget_GrSurfaceFlag;
+ desc->fConfig = src->config();
+ return true;
+ }
+
+ const GrGLTexture* srcTexture = static_cast<const GrGLTexture*>(src->asTexture());
+ if (srcTexture && srcTexture->target() != GR_GL_TEXTURE_2D) {
+ // Not supported for FBO blit or CopyTexSubImage
+ return false;
+ }
+
+ // We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
+ // possible and we return false to fallback to creating a render target dst for render-to-
+ // texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo
+ // creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
+ GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin;
+ if (this->blitFramebufferSupportFlags() & kNoScalingOrMirroring_BlitFramebufferFlag) {
+ originForBlitFramebuffer = src->origin();
+ }
+
+ // Check for format issues with glCopyTexSubImage2D
+ if (this->bgraIsInternalFormat() && kBGRA_8888_GrPixelConfig == src->config()) {
+ // glCopyTexSubImage2D doesn't work with this config. If the bgra can be used with fbo blit
+ // then we set up for that, otherwise fail.
+ if (this->canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) {
+ desc->fOrigin = originForBlitFramebuffer;
+ desc->fConfig = kBGRA_8888_GrPixelConfig;
+ return true;
+ }
+ return false;
+ }
+
+ const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src);
+ if (srcRT->renderFBOID() != srcRT->textureFBOID()) {
+ // It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO blit or
+ // fail.
+ if (this->canConfigBeFBOColorAttachment(src->config())) {
+ desc->fOrigin = originForBlitFramebuffer;
+ desc->fConfig = src->config();
+ return true;
+ }
+ return false;
+ }
+
+ // We'll do a CopyTexSubImage. Make the dst a plain old texture.
+ desc->fConfig = src->config();
+ desc->fOrigin = src->origin();
+ desc->fFlags = kNone_GrSurfaceFlags;
+ return true;
+}
+
void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
if (options.fEnableInstancedRendering) {
fInstancedSupport = gr_instanced::GLInstancedRendering::CheckSupport(*this);
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 8a83e02222..a659435784 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -359,6 +359,8 @@ public:
return fRGBAToBGRAReadbackConversionsAreSlow;
}
+ bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
+
private:
enum ExternalFormatUsage {
kTexImage_ExternalFormatUsage,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index bda1c16b59..7a811d1c8f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3464,65 +3464,6 @@ void GrGLGpu::unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface
}
}
-bool GrGLGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
- // If the src is a texture, we can implement the blit as a draw assuming the config is
- // renderable.
- if (src->asTexture() && this->caps()->isConfigRenderable(src->config(), false)) {
- desc->fOrigin = kDefault_GrSurfaceOrigin;
- desc->fFlags = kRenderTarget_GrSurfaceFlag;
- desc->fConfig = src->config();
- return true;
- }
-
- const GrGLTexture* srcTexture = static_cast<const GrGLTexture*>(src->asTexture());
- if (srcTexture && srcTexture->target() != GR_GL_TEXTURE_2D) {
- // Not supported for FBO blit or CopyTexSubImage
- return false;
- }
-
- // We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
- // possible and we return false to fallback to creating a render target dst for render-to-
- // texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo
- // creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
-
- GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin;
- if (this->glCaps().blitFramebufferSupportFlags() &
- GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag) {
- originForBlitFramebuffer = src->origin();
- }
-
- // Check for format issues with glCopyTexSubImage2D
- if (kGLES_GrGLStandard == this->glStandard() && this->glCaps().bgraIsInternalFormat() &&
- kBGRA_8888_GrPixelConfig == src->config()) {
- // glCopyTexSubImage2D doesn't work with this config. If the bgra can be used with fbo blit
- // then we set up for that, otherwise fail.
- if (this->glCaps().canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) {
- desc->fOrigin = originForBlitFramebuffer;
- desc->fConfig = kBGRA_8888_GrPixelConfig;
- return true;
- }
- return false;
- }
-
- const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src);
- if (srcRT->renderFBOID() != srcRT->textureFBOID()) {
- // It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO blit or
- // fail.
- if (this->glCaps().canConfigBeFBOColorAttachment(src->config())) {
- desc->fOrigin = originForBlitFramebuffer;
- desc->fConfig = src->config();
- return true;
- }
- return false;
- }
-
- // We'll do a CopyTexSubImage. Make the dst a plain old texture.
- desc->fConfig = src->config();
- desc->fOrigin = src->origin();
- desc->fFlags = kNone_GrSurfaceFlags;
- return true;
-}
-
bool GrGLGpu::onCopySurface(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 564ed7629a..6a175d51e9 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -75,8 +75,6 @@ public:
GrPixelConfig srcConfig, DrawPreference*,
WritePixelTempDrawInfo*) override;
- bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
-
// These functions should be used to bind GL objects. They track the GL state and skip redundant
// bindings. Making the equivalent glBind calls directly will confuse the state tracking.
void bindVertexArray(GrGLuint id) {
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index fd454ad544..16a91c1a1f 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -6,11 +6,11 @@
*/
#include "GrVkCaps.h"
-
+#include "GrRenderTarget.h"
#include "GrShaderCaps.h"
#include "GrVkUtil.h"
-#include "vk/GrVkInterface.h"
#include "vk/GrVkBackendContext.h"
+#include "vk/GrVkInterface.h"
GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags)
@@ -52,6 +52,22 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface*
this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags);
}
+bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
+ // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
+ // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
+ // render target as well.
+ desc->fOrigin = src->origin();
+ desc->fConfig = src->config();
+ if (src->numColorSamples() > 1 || (src->asTexture() && this->supportsCopiesAsDraws())) {
+ desc->fFlags = kRenderTarget_GrSurfaceFlag;
+ } else {
+ // Just going to use CopyImage here
+ desc->fFlags = kNone_GrSurfaceFlags;
+ }
+
+ return true;
+}
+
void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags) {
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 6d030f69a1..6ef0796257 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -87,6 +87,8 @@ public:
return fPreferedStencilFormat;
}
+ bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
+
private:
enum VkVendor {
kQualcomm_VkVendor = 20803,
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index b85aa2da4e..4008c7c162 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1590,23 +1590,6 @@ bool GrVkGpu::onCopySurface(GrSurface* dst,
return false;
}
-bool GrVkGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
- // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
- // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
- // render target as well.
- desc->fOrigin = src->origin();
- desc->fConfig = src->config();
- if (src->numColorSamples() > 1 ||
- (src->asTexture() && this->vkCaps().supportsCopiesAsDraws())) {
- desc->fFlags = kRenderTarget_GrSurfaceFlag;
- } else {
- // Just going to use CopyImage here
- desc->fFlags = kNone_GrSurfaceFlags;
- }
-
- return true;
-}
-
void GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) {
// TODO: stub.
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 7203bf1f8b..9556d85f58 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -79,8 +79,6 @@ public:
void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override;
- bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
-
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,