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:
parent
2d61e71700
commit
bf25d433f4
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user