diff options
author | Brian Salomon <bsalomon@google.com> | 2017-03-06 16:17:12 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-07 15:11:24 +0000 |
commit | 467921e5e6479fe9cebba125657d8e33d89004ae (patch) | |
tree | bffd056e5d9ad99a50c1876d658f4b31d6721d15 /src | |
parent | 894d5611e54cbf62a03ff9ffb48a2302dda9ab86 (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.h | 8 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 234 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.h | 501 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetOpList.cpp | 211 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetOpList.h | 38 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 61 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 59 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 2 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 20 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.h | 2 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 17 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 2 |
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(), ©Rect); + + 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(), ©Rect); - - 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, |