Make GrCopySurfaceOp friendlier to GrSurfaceProxy (take 2)

Reland of: https://skia-review.googlesource.com/c/11325/ (Make GrCopySurfaceOp friendlier to GrSurfaceProxy)

Change-Id: Ibe7312cebe7793af5803353a1499fbe7874c558f
Reviewed-on: https://skia-review.googlesource.com/11780
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2017-04-07 10:08:53 -04:00 committed by Skia Commit-Bot
parent 2d61e71700
commit bf25d433f4
17 changed files with 206 additions and 169 deletions

View File

@ -17,7 +17,7 @@
#include "SkString.h"
struct GrContextOptions;
class GrRenderTarget;
class GrRenderTargetProxy;
/**
* Represents the capabilities of a GrContext.
@ -187,13 +187,13 @@ public:
/**
* 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
* used for doing dst copies needed in blends, thus the src is always a GrRenderTargetProxy. It
* will populate the origin, config, and flags fields of the desc such that copySurface can
* efficiently succeed. rectsMustMatch will be set to true if the copy operation must ensure
* that the src and dest rects are identical. disallowSubrect will be set to true if copy rect
* must equal src's bounds.
*/
virtual bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc,
virtual bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const = 0;
protected:

View File

@ -23,19 +23,18 @@ public:
GrDrawingManager* drawingManager() { return fContext->fDrawingManager.get(); }
// Create a renderTargetContext that wraps an existing renderTarget
sk_sp<GrRenderTargetContext> makeWrappedRenderTargetContext(sk_sp<GrRenderTarget> rt,
sk_sp<SkColorSpace> colorSpace,
sk_sp<GrRenderTargetContext> makeWrappedRenderTargetContext(sk_sp<GrRenderTarget>,
sk_sp<SkColorSpace>,
const SkSurfaceProps* = nullptr);
// Create a surfaceContext that wraps an existing texture or renderTarget
sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurface> tex);
sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurface>);
sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
sk_sp<SkColorSpace>);
sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy>, sk_sp<SkColorSpace>);
sk_sp<GrSurfaceContext> makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
SkBackingFit dstFit,
SkBudgeted isDstBudgeted);
sk_sp<GrSurfaceContext> makeDeferredSurfaceContext(const GrSurfaceDesc&,
SkBackingFit,
SkBudgeted);
// TODO: Maybe add a 'surfaceProps' param (that is ignored for non-RTs) and remove
// makeBackendTextureRenderTargetContext & makeBackendTextureAsRenderTargetRenderTargetContext

View File

@ -135,22 +135,10 @@ bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::onCopy");
// TODO: defer instantiation until flush time
sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
if (!src) {
return false;
}
// TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
sk_sp<GrRenderTarget> rt(
sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
if (!rt) {
return false;
}
return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
return this->getOpList()->copySurface(fContext->resourceProvider(),
fRenderTargetProxy.get(), srcProxy, srcRect, dstPoint);
}
// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
@ -1664,8 +1652,7 @@ uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<Gr
GrXferProcessor::DstTexture dstTexture;
if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
this->setupDstTexture(rt, clip, op->bounds(), &dstTexture);
if (!dstTexture.texture()) {
if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, op->bounds(), &dstTexture)) {
return SK_InvalidUniqueID;
}
}
@ -1720,8 +1707,7 @@ uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipeline
args.fXPInputCoverage = analysis.outputCoverage();
if (analysis.requiresDstTexture()) {
this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
if (!args.fDstTexture.texture()) {
if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, bounds, &args.fDstTexture)) {
return SK_InvalidUniqueID;
}
}
@ -1731,33 +1717,39 @@ uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipeline
return this->getOpList()->addOp(std::move(op), this);
}
void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
bool GrRenderTargetContext::setupDstTexture(GrRenderTargetProxy* rtProxy, const GrClip& clip,
const SkRect& opBounds,
GrXferProcessor::DstTexture* dstTexture) {
if (this->caps()->textureBarrierSupport()) {
if (GrTexture* rtTex = rt->asTexture()) {
if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
// MDB TODO: remove this instantiation. Blocked on making DstTexture be proxy-based
sk_sp<GrTexture> tex(sk_ref_sp(texProxy->instantiate(fContext->resourceProvider())));
if (!tex) {
SkDebugf("setupDstTexture: instantiation of src texture failed.\n");
return false; // We have bigger problems now
}
// 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->setTexture(std::move(tex));
dstTexture->setOffset(0, 0);
return;
return true;
}
}
SkIRect copyRect = SkIRect::MakeWH(rt->width(), rt->height());
SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
SkIRect clippedRect;
clip.getConservativeBounds(rt->width(), rt->height(), &clippedRect);
clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
SkIRect drawIBounds;
opBounds.roundOut(&drawIBounds);
// Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
drawIBounds.outset(1, 1);
if (!clippedRect.intersect(drawIBounds)) {
#ifdef SK_DEBUG
GrCapsDebugf(this->caps(), "Missed an early reject. "
"Bailing on draw from setupDstTexture.\n");
GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
#endif
return;
return false;
}
// MSAA consideration: When there is support for reading MSAA samples in the shader we could
@ -1765,41 +1757,56 @@ void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& cl
GrSurfaceDesc desc;
bool rectsMustMatch = false;
bool disallowSubrect = false;
if (!this->caps()->initDescForDstCopy(rt, &desc, &rectsMustMatch, &disallowSubrect)) {
desc.fOrigin = kDefault_GrSurfaceOrigin;
if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &rectsMustMatch, &disallowSubrect)) {
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fConfig = rt->config();
desc.fConfig = rtProxy->config();
}
if (!disallowSubrect) {
copyRect = clippedRect;
}
SkIPoint dstPoint;
SkIPoint dstOffset;
static const uint32_t kFlags = 0;
sk_sp<GrTexture> copy;
SkIPoint dstPoint, dstOffset;
SkBackingFit fit;
if (rectsMustMatch) {
SkASSERT(desc.fOrigin == rt->origin());
desc.fWidth = rt->width();
desc.fHeight = rt->height();
SkASSERT(desc.fOrigin == rtProxy->origin());
desc.fWidth = rtProxy->width();
desc.fHeight = rtProxy->height();
dstPoint = {copyRect.fLeft, copyRect.fTop};
dstOffset = {0, 0};
copy = fContext->resourceProvider()->createTexture(desc, SkBudgeted::kYes, kFlags);
fit = SkBackingFit::kExact;
} else {
desc.fWidth = copyRect.width();
desc.fHeight = copyRect.height();
dstPoint = {0, 0};
dstOffset = {copyRect.fLeft, copyRect.fTop};
copy.reset(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
fit = SkBackingFit::kApprox;
}
sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
desc,
fit,
SkBudgeted::kYes);
if (!sContext) {
SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
return false;
}
if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
SkDebugf("setupDstTexture: copy failed.\n");
return false;
}
GrTextureProxy* copyProxy = sContext->asTextureProxy();
// MDB TODO: remove this instantiation once DstTexture is proxy-backed
sk_sp<GrTexture> copy(sk_ref_sp(copyProxy->instantiate(fContext->resourceProvider())));
if (!copy) {
SkDebugf("Failed to create temporary copy of destination texture.\n");
return;
SkDebugf("setupDstTexture: instantiation of copied texture failed.\n");
return false;
}
this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
dstTexture->setTexture(std::move(copy));
dstTexture->setOffset(dstOffset);
return true;
}

View File

@ -469,12 +469,13 @@ private:
uint32_t addLegacyMeshDrawOp(GrPipelineBuilder&&, const GrClip&,
std::unique_ptr<GrLegacyMeshDrawOp>);
// 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*);
// Makes a copy of the proxy if it is necessary for the draw and places the texture that should
// be used by GrXferProcessor to access the destination color in 'result'. If the return
// value is false then a texture copy could not be made.
bool SK_WARN_UNUSED_RESULT setupDstTexture(GrRenderTargetProxy*,
const GrClip&,
const SkRect& opBounds,
GrXferProcessor::DstTexture* result);
GrRenderTargetOpList* getOpList();

View File

@ -236,11 +236,12 @@ void GrRenderTargetOpList::discard(GrRenderTargetContext* renderTargetContext) {
////////////////////////////////////////////////////////////////////////////////
bool GrRenderTargetOpList::copySurface(GrSurface* dst,
GrSurface* src,
bool GrRenderTargetOpList::copySurface(GrResourceProvider* resourceProvider,
GrSurfaceProxy* dst,
GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(dst, src, srcRect, dstPoint);
std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(resourceProvider, dst, src, srcRect, dstPoint);
if (!op) {
return false;
}

View File

@ -98,8 +98,9 @@ public:
* depending on the type of surface, configs, etc, and the backend-specific
* limitations.
*/
bool copySurface(GrSurface* dst,
GrSurface* src,
bool copySurface(GrResourceProvider* resourceProvider,
GrSurfaceProxy* dst,
GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint);

View File

@ -84,20 +84,9 @@ bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy,
fContext->contextPriv().flushSurfaceWrites(srcProxy);
#endif
// TODO: defer instantiation until flush time
sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
if (!src) {
return false;
}
// TODO: this needs to be fixed up since it ends the deferrable of the GrTexture
sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
if (!tex) {
return false;
}
GrTextureOpList* opList = this->getOpList();
bool result = opList->copySurface(tex.get(), src.get(), srcRect, dstPoint);
bool result = opList->copySurface(fContext->resourceProvider(),
fTextureProxy.get(), srcProxy, srcRect, dstPoint);
#ifndef ENABLE_MDB
GrOpFlushState flushState(fContext->getGpu(), nullptr);

View File

@ -76,11 +76,12 @@ void GrTextureOpList::reset() {
////////////////////////////////////////////////////////////////////////////////
bool GrTextureOpList::copySurface(GrSurface* dst,
GrSurface* src,
bool GrTextureOpList::copySurface(GrResourceProvider* resourceProvider,
GrSurfaceProxy* dst,
GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(dst, src, srcRect, dstPoint);
std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(resourceProvider, dst, src, srcRect, dstPoint);
if (!op) {
return false;
}

View File

@ -52,8 +52,9 @@ public:
* depending on the type of surface, configs, etc, and the backend-specific
* limitations.
*/
bool copySurface(GrSurface* dst,
GrSurface* src,
bool copySurface(GrResourceProvider* resourceProvider,
GrSurfaceProxy* dst,
GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint);

View File

@ -11,6 +11,7 @@
#include "GrGLRenderTarget.h"
#include "GrGLTexture.h"
#include "GrShaderCaps.h"
#include "GrSurfaceProxyPriv.h"
#include "SkTSearch.h"
#include "SkTSort.h"
#include "instanced/GLInstancedRendering.h"
@ -2071,7 +2072,7 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
#endif
}
bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc,
bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const {
// By default, we don't require rects to match.
*rectsMustMatch = false;
@ -2081,17 +2082,22 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc
// 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;
if (src->asTextureProxy() && this->isConfigRenderable(src->config(), false)) {
desc->fOrigin = kBottomLeft_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;
{
// The only way we could see a non-GR_GL_TEXTURE_2D texture would be if it were
// wrapped. In that case the proxy would already be instantiated.
const GrTexture* srcTexture = src->priv().peekTexture();
const GrGLTexture* glSrcTexture = static_cast<const GrGLTexture*>(srcTexture);
if (glSrcTexture && glSrcTexture->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
@ -2130,18 +2136,20 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc
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();
*rectsMustMatch = rectsMustMatchForBlitFramebuffer;
*disallowSubrect = disallowSubrectForBlitFramebuffer;
return true;
{
bool srcIsMSAARenderbuffer = src->desc().fSampleCnt > 0 && this->usesMSAARenderBuffers();
if (srcIsMSAARenderbuffer) {
// 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();
*rectsMustMatch = rectsMustMatchForBlitFramebuffer;
*disallowSubrect = disallowSubrectForBlitFramebuffer;
return true;
}
return false;
}
return false;
}
// We'll do a CopyTexSubImage. Make the dst a plain old texture.

View File

@ -359,8 +359,8 @@ public:
return fRGBAToBGRAReadbackConversionsAreSlow;
}
bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch,
bool* disallowSubrect) const override;
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override;
private:
enum ExternalFormatUsage {

View File

@ -8,12 +8,12 @@
#include "GrCopySurfaceOp.h"
// returns true if the read/written rect intersects the src/dst and false if not.
bool GrCopySurfaceOp::ClipSrcRectAndDstPoint(const GrSurface* dst,
const GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint,
SkIRect* clippedSrcRect,
SkIPoint* clippedDstPoint) {
static bool clip_src_rect_and_dst_point(const GrSurfaceProxy* dst,
const GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint,
SkIRect* clippedSrcRect,
SkIPoint* clippedDstPoint) {
*clippedSrcRect = srcRect;
*clippedDstPoint = dstPoint;
@ -58,21 +58,37 @@ bool GrCopySurfaceOp::ClipSrcRectAndDstPoint(const GrSurface* dst,
return !clippedSrcRect->isEmpty();
}
std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrResourceProvider* resourceProvider,
GrSurfaceProxy* dstProxy, GrSurfaceProxy* srcProxy,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
SkASSERT(dst);
SkASSERT(src);
if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
SkASSERT(dstProxy);
SkASSERT(srcProxy);
if (GrPixelConfigIsSint(dstProxy->config()) != GrPixelConfigIsSint(srcProxy->config())) {
return nullptr;
}
if (GrPixelConfigIsCompressed(dst->config())) {
if (GrPixelConfigIsCompressed(dstProxy->config())) {
return nullptr;
}
SkIRect clippedSrcRect;
SkIPoint clippedDstPoint;
// If the rect is outside the src or dst then we've already succeeded.
if (!ClipSrcRectAndDstPoint(dst, src, srcRect, dstPoint, &clippedSrcRect, &clippedDstPoint)) {
// If the rect is outside the srcProxy or dstProxy then we've already succeeded.
if (!clip_src_rect_and_dst_point(dstProxy, srcProxy, srcRect, dstPoint,
&clippedSrcRect, &clippedDstPoint)) {
return nullptr;
}
return std::unique_ptr<GrOp>(new GrCopySurfaceOp(dst, src, clippedSrcRect, clippedDstPoint));
// MDB TODO: remove this instantiation
GrSurface* dstTex = dstProxy->instantiate(resourceProvider);
if (!dstTex) {
return nullptr;
}
GrSurface* srcTex = srcProxy->instantiate(resourceProvider);
if (!srcTex) {
return nullptr;
}
return std::unique_ptr<GrOp>(new GrCopySurfaceOp(dstTex, srcTex,
dstProxy->uniqueID(), srcProxy->uniqueID(),
clippedSrcRect, clippedDstPoint));
}

View File

@ -8,45 +8,44 @@
#ifndef GrCopySurfaceOp_DEFINED
#define GrCopySurfaceOp_DEFINED
#include "GrGpu.h"
#include "GrOp.h"
#include "GrOpFlushState.h"
#include "GrRenderTarget.h"
class GrCopySurfaceOp final : public GrOp {
public:
DEFINE_OP_CLASS_ID
/** This should not really be exposed as Create() will apply this clipping, but there is
* currently a workaround in GrContext::copySurface() for non-render target dsts that relies
* on it. */
static bool ClipSrcRectAndDstPoint(const GrSurface* dst,
const GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint,
SkIRect* clippedSrcRect,
SkIPoint* clippedDstPoint);
static std::unique_ptr<GrOp> Make(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
// MDB TODO: remove the resourceProvider parameter
static std::unique_ptr<GrOp> Make(GrResourceProvider*,
GrSurfaceProxy* dst, GrSurfaceProxy* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint);
const char* name() const override { return "CopySurface"; }
SkString dumpInfo() const override {
SkString string;
string.printf(
"SRC: 0x%p, DST: 0x%p, SRECT: [L: %d, T: %d, R: %d, B: %d], "
"DPT:[X: %d, Y: %d]",
fDst.get(), fSrc.get(), fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight,
fSrcRect.fBottom, fDstPoint.fX, fDstPoint.fY);
string.printf("src: (proxyID: %d, rtID: %d), dst: (proxyID: %d, rtID: %d), "
"srcRect: [L: %d, T: %d, R: %d, B: %d], dstPt: [X: %d, Y: %d]",
fSrcProxyID.asUInt(), fSrc.get()->uniqueID().asUInt(),
fDstProxyID.asUInt(), fDst.get()->uniqueID().asUInt(),
fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom,
fDstPoint.fX, fDstPoint.fY);
string.append(INHERITED::dumpInfo());
return string;
}
private:
GrCopySurfaceOp(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIPoint& dstPoint)
: INHERITED(ClassID()), fDst(dst), fSrc(src), fSrcRect(srcRect), fDstPoint(dstPoint) {
GrCopySurfaceOp(GrSurface* dst, GrSurface* src,
GrSurfaceProxy::UniqueID dstID, GrSurfaceProxy::UniqueID srcID,
const SkIRect& srcRect, const SkIPoint& dstPoint)
: INHERITED(ClassID())
, fDstProxyID(dstID)
, fSrcProxyID(srcID)
, fDst(dst)
, fSrc(src)
, fSrcRect(srcRect)
, fDstPoint(dstPoint) {
SkRect bounds =
SkRect::MakeXYWH(SkIntToScalar(dstPoint.fX), SkIntToScalar(dstPoint.fY),
SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
@ -67,10 +66,14 @@ private:
}
}
// MDB TODO: remove the proxy IDs once the GrSurfaceProxy carries the ref since they will
// be redundant
GrSurfaceProxy::UniqueID fDstProxyID;
GrSurfaceProxy::UniqueID fSrcProxyID;
GrPendingIOResource<GrSurface, kWrite_GrIOType> fDst;
GrPendingIOResource<GrSurface, kRead_GrIOType> fSrc;
SkIRect fSrcRect;
SkIPoint fDstPoint;
GrPendingIOResource<GrSurface, kRead_GrIOType> fSrc;
SkIRect fSrcRect;
SkIPoint fDstPoint;
typedef GrOp INHERITED;
};

View File

@ -6,7 +6,7 @@
*/
#include "GrVkCaps.h"
#include "GrRenderTarget.h"
#include "GrRenderTargetProxy.h"
#include "GrShaderCaps.h"
#include "GrVkUtil.h"
#include "vk/GrVkBackendContext.h"
@ -53,7 +53,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface*
this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags);
}
bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc,
bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const {
// Vk doesn't use rectsMustMatch or disallowSubrect. Always return false.
*rectsMustMatch = false;
@ -64,7 +64,7 @@ bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc
// render target as well.
desc->fOrigin = src->origin();
desc->fConfig = src->config();
if (src->numColorSamples() > 1 || (src->asTexture() && this->supportsCopiesAsDraws())) {
if (src->numColorSamples() > 1 || (src->asTextureProxy() && this->supportsCopiesAsDraws())) {
desc->fFlags = kRenderTarget_GrSurfaceFlag;
} else {
// Just going to use CopyImage here

View File

@ -104,8 +104,8 @@ public:
return fPreferedStencilFormat;
}
bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch,
bool* disallowSubrect) const override;
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override;
private:
enum VkVendor {

View File

@ -84,23 +84,29 @@ DEF_TEST(Blend_byte_multiply, r) {
namespace {
static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target(
GrContext* context, int sampleCnt, int width, int height, GrPixelConfig config,
GrSurfaceOrigin origin,
sk_sp<GrTexture>* backingSurface) {
GrSurfaceDesc backingDesc;
backingDesc.fHeight = height;
backingDesc.fWidth = width;
backingDesc.fConfig = config;
backingDesc.fOrigin = kDefault_GrSurfaceOrigin;
backingDesc.fFlags = kRenderTarget_GrSurfaceFlag;
backingDesc.fOrigin = origin;
backingDesc.fWidth = width;
backingDesc.fHeight = height;
backingDesc.fConfig = config;
backingDesc.fSampleCnt = sampleCnt;
*backingSurface = context->resourceProvider()->createTexture(backingDesc, SkBudgeted::kNo);
if (!(*backingSurface)) {
return nullptr;
}
GrBackendTextureDesc desc;
desc.fConfig = config;
desc.fFlags = kRenderTarget_GrBackendTextureFlag;
desc.fOrigin = origin;
desc.fWidth = width;
desc.fHeight = height;
desc.fFlags = kRenderTarget_GrBackendTextureFlag;
desc.fTextureHandle = (*backingSurface)->getTextureHandle();
desc.fConfig = config;
desc.fSampleCnt = sampleCnt;
desc.fTextureHandle = (*backingSurface)->getTextureHandle();
sk_sp<SkSurface> surface =
SkSurface::MakeFromBackendTextureAsRenderTarget(context, desc, nullptr);
return surface;
@ -127,31 +133,35 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ES2BlendWithNoTexture, reporter, ctxInfo)
};
struct TestCase {
RectAndSamplePoint rectAndPoints;
SkRect clip;
int sampleCnt;
RectAndSamplePoint fRectAndPoints;
SkRect fClip;
int fSampleCnt;
GrSurfaceOrigin fOrigin;
};
std::vector<TestCase> testCases;
for (int sampleCnt : {0, 4}) {
for (auto rectAndPoints : allRectsAndPoints) {
for (auto clip : {SkRect::MakeXYWH(0, 0, 10, 10), SkRect::MakeXYWH(1, 1, 8, 8)}) {
testCases.push_back({rectAndPoints, clip, sampleCnt});
for (auto origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
for (int sampleCnt : {0, 4}) {
for (auto rectAndPoints : allRectsAndPoints) {
for (auto clip : {SkRect::MakeXYWH(0, 0, 10, 10), SkRect::MakeXYWH(1, 1, 8, 8)}) {
testCases.push_back({rectAndPoints, clip, sampleCnt, origin});
}
}
}
}
// Run each test case:
for (auto testCase : testCases) {
int sampleCnt = testCase.sampleCnt;
SkRect paintRect = testCase.rectAndPoints.rect;
SkIPoint outPoint = testCase.rectAndPoints.outPoint;
SkIPoint inPoint = testCase.rectAndPoints.inPoint;
int sampleCnt = testCase.fSampleCnt;
SkRect paintRect = testCase.fRectAndPoints.rect;
SkIPoint outPoint = testCase.fRectAndPoints.outPoint;
SkIPoint inPoint = testCase.fRectAndPoints.inPoint;
GrSurfaceOrigin origin = testCase.fOrigin;
sk_sp<GrTexture> backingSurface;
// BGRA forces a framebuffer blit on ES2.
sk_sp<SkSurface> surface = create_gpu_surface_backend_texture_as_render_target(
context, sampleCnt, kWidth, kHeight, kConfig, &backingSurface);
context, sampleCnt, kWidth, kHeight, kConfig, origin, &backingSurface);
if (!surface && sampleCnt > 0) {
// Some platforms don't support MSAA.
@ -161,7 +171,7 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ES2BlendWithNoTexture, reporter, ctxInfo)
// Fill our canvas with 0xFFFF80
SkCanvas* canvas = surface->getCanvas();
canvas->clipRect(testCase.clip, false);
canvas->clipRect(testCase.fClip, false);
SkPaint black_paint;
black_paint.setColor(SkColorSetRGB(0xFF, 0xFF, 0x80));
canvas->drawRect(SkRect::MakeXYWH(0, 0, kWidth, kHeight), black_paint);

View File

@ -273,8 +273,8 @@ public:
bool isConfigTexturable(GrPixelConfig config) const override { return false; }
bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override { return false; }
bool canConfigBeImageStorage(GrPixelConfig) const override { return false; }
bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch,
bool* disallowSubrect) const override {
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override {
return false;
}