Reland "Reland "Remove support for copyAsDraw in gpu copySurface.""

This reverts commit 4c6f9b7670.

Reason for revert: Landing with neuxs 7 and androind one fixes

Original change's description:
> Revert "Reland "Remove support for copyAsDraw in gpu copySurface.""
>
> This reverts commit 84ea04949c.
>
> Reason for revert: nexus 7 and android one broken
>
> Original change's description:
> > Reland "Remove support for copyAsDraw in gpu copySurface."
> >
> > This reverts commit c5167c053b.
> >
> > Reason for revert: fixed
> >
> > Original change's description:
> > > Revert "Remove support for copyAsDraw in gpu copySurface."
> > >
> > > This reverts commit 6565506463.
> > >
> > > Reason for revert: seems to break things?
> > >
> > > Original change's description:
> > > > Remove support for copyAsDraw in gpu copySurface.
> > > >
> > > > The major changes on a higher lever are:
> > > > 1) The majority of all copies now go through GrSurfaceProxy::Copy which
> > > > takes in a proxy and returns a new one with the data copied to it. This
> > > > is the most common use case within Ganesh.
> > > >
> > > > 2) The backend copy calls no longer do draws, require origins to be the
> > > > same, and won't do any swizzling or adjustment of subrects. They are
> > > > all implemented to be dumb copy this data to this other spot.
> > > >
> > > > 3) The GrSurfaceContext copy call has now been moved to priv and renamed
> > > > copyNoDraw, and a new priv copyAsDraw was added to GrRenderTargetContext.
> > > >
> > > > 4) WritePixels and ReplaceRenderTarget both need to specifiy the destination
> > > > of copies. They are the only users (besides the GrSurfaceProxy::Copy) which
> > > > call the priv methods on GrSurfaceContext.
> > > >
> > > > Change-Id: Iaf1eb3a73ccaf39a75af77e281dae594f809186f
> > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/217459
> > > > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > > > Commit-Queue: Greg Daniel <egdaniel@google.com>
> > >
> > > TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com
> > >
> > > Change-Id: Id43aa8aa1451e794342e930441d9975b90e6b59f
> > > No-Presubmit: true
> > > No-Tree-Checks: true
> > > No-Try: true
> > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/218549
> > > Reviewed-by: Greg Daniel <egdaniel@google.com>
> > > Commit-Queue: Greg Daniel <egdaniel@google.com>
> >
> > TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com
> >
> > Change-Id: I1a96f85ae2ff7622a6b57406755d478e7fbcf56e
> > No-Presubmit: true
> > No-Tree-Checks: true
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/218797
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > Commit-Queue: Greg Daniel <egdaniel@google.com>
>
> TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com
>
> Change-Id: I310930a9df30535f45a065263a40239141e15562
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/219384
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Greg Daniel <egdaniel@google.com>

TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com

Change-Id: I88df4f19aa26ed77b5af4e25d138387cbabd1934
No-Presubmit: true
No-Tree-Checks: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/219386
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2019-06-07 11:43:30 -04:00 committed by Skia Commit-Bot
parent 33a6f7c0a8
commit 46cfbc67f6
60 changed files with 609 additions and 2418 deletions

View File

@ -196,29 +196,11 @@ protected:
return fProxy; return fProxy;
} }
// need to copy the subset into a new texture
GrSurfaceDesc desc;
desc.fWidth = info.width();
desc.fHeight = info.height();
desc.fConfig = fProxy->config();
GrMipMapped mipMapped = willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo; GrMipMapped mipMapped = willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo;
sk_sp<GrSurfaceContext> dstContext(fCtx->priv().makeDeferredSurfaceContext( return GrSurfaceProxy::Copy(fCtx.get(), fProxy.get(), mipMapped,
fProxy->backendFormat(), desc, fProxy->origin(), mipMapped, SkBackingFit::kExact, SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
SkBudgeted::kYes)); SkBackingFit::kExact, SkBudgeted::kYes);
if (!dstContext) {
return nullptr;
}
if (!dstContext->copy(
fProxy.get(),
SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
SkIPoint::Make(0, 0))) {
return nullptr;
}
return dstContext->asTextureProxyRef();
} }
private: private:

View File

@ -632,10 +632,6 @@ skia_vk_sources = [
"$_src/gpu/vk/GrVkCommandBuffer.h", "$_src/gpu/vk/GrVkCommandBuffer.h",
"$_src/gpu/vk/GrVkCommandPool.cpp", "$_src/gpu/vk/GrVkCommandPool.cpp",
"$_src/gpu/vk/GrVkCommandPool.h", "$_src/gpu/vk/GrVkCommandPool.h",
"$_src/gpu/vk/GrVkCopyManager.cpp",
"$_src/gpu/vk/GrVkCopyManager.h",
"$_src/gpu/vk/GrVkCopyPipeline.cpp",
"$_src/gpu/vk/GrVkCopyPipeline.h",
"$_src/gpu/vk/GrVkDescriptorPool.cpp", "$_src/gpu/vk/GrVkDescriptorPool.cpp",
"$_src/gpu/vk/GrVkDescriptorPool.h", "$_src/gpu/vk/GrVkDescriptorPool.h",
"$_src/gpu/vk/GrVkDescriptorSet.cpp", "$_src/gpu/vk/GrVkDescriptorSet.cpp",
@ -715,11 +711,7 @@ skia_metal_sources = [
"$_src/gpu/mtl/GrMtlCaps.mm", "$_src/gpu/mtl/GrMtlCaps.mm",
"$_src/gpu/mtl/GrMtlCommandBuffer.h", "$_src/gpu/mtl/GrMtlCommandBuffer.h",
"$_src/gpu/mtl/GrMtlCommandBuffer.mm", "$_src/gpu/mtl/GrMtlCommandBuffer.mm",
"$_src/gpu/mtl/GrMtlCopyManager.h",
"$_src/gpu/mtl/GrMtlCopyManager.mm",
"$_src/gpu/mtl/GrMtlCppUtil.h", "$_src/gpu/mtl/GrMtlCppUtil.h",
"$_src/gpu/mtl/GrMtlCopyPipelineState.h",
"$_src/gpu/mtl/GrMtlCopyPipelineState.mm",
"$_src/gpu/mtl/GrMtlDepthStencil.h", "$_src/gpu/mtl/GrMtlDepthStencil.h",
"$_src/gpu/mtl/GrMtlDepthStencil.mm", "$_src/gpu/mtl/GrMtlDepthStencil.mm",
"$_src/gpu/mtl/GrMtlGpu.h", "$_src/gpu/mtl/GrMtlGpu.h",

View File

@ -297,7 +297,6 @@ tests_sources = [
"$_tests/VkBackendSurfaceTest.cpp", "$_tests/VkBackendSurfaceTest.cpp",
"$_tests/VkDrawableTest.cpp", "$_tests/VkDrawableTest.cpp",
"$_tests/VkHardwareBufferTest.cpp", "$_tests/VkHardwareBufferTest.cpp",
"$_tests/VkMakeCopyPipelineTest.cpp",
"$_tests/VkPriorityExtensionTest.cpp", "$_tests/VkPriorityExtensionTest.cpp",
"$_tests/VkWrapTests.cpp", "$_tests/VkWrapTests.cpp",
"$_tests/VptrTest.cpp", "$_tests/VptrTest.cpp",

View File

@ -437,20 +437,21 @@ public:
return fGpuMemorySize; return fGpuMemorySize;
} }
enum class RectsMustMatch : bool {
kNo = false,
kYes = true
};
// Helper function that creates a temporary SurfaceContext to perform the copy // Helper function that creates a temporary SurfaceContext to perform the copy
// The copy is is not a render target and not multisampled. // The copy is is not a render target and not multisampled.
static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped, static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
SkIRect srcRect, SkBackingFit, SkBudgeted); SkIRect srcRect, SkBackingFit, SkBudgeted,
RectsMustMatch = RectsMustMatch::kNo);
// Copy the entire 'src' // Copy the entire 'src'
static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped, static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
SkBackingFit, SkBudgeted); SkBackingFit, SkBudgeted);
// Test-only entry point - should decrease in use as proxies propagate
static sk_sp<GrSurfaceContext> TestCopy(GrRecordingContext* context,
const GrSurfaceDesc& dstDesc,
GrSurfaceOrigin, GrSurfaceProxy* srcProxy);
bool isWrapped_ForTesting() const; bool isWrapped_ForTesting() const;
SkDEBUGCODE(void validate(GrContext_Base*) const;) SkDEBUGCODE(void validate(GrContext_Base*) const;)

View File

@ -208,28 +208,10 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
// because Vulkan will want to do the copy as a draw. All other copies would require a // because Vulkan will want to do the copy as a draw. All other copies would require a
// layout change in Vulkan and we do not change the layout of borrowed images. // layout change in Vulkan and we do not change the layout of borrowed images.
GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo; GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
GrBackendFormat format = proxy->backendFormat().makeTexture2D();
if (!format.isValid()) {
return nullptr;
}
sk_sp<GrRenderTargetContext> rtContext(
context->priv().makeDeferredRenderTargetContext(
format, SkBackingFit::kExact, info.width(), info.height(),
proxy->config(), nullptr, 1, mipMapped, proxy->origin(), nullptr,
SkBudgeted::kYes));
if (!rtContext) {
return nullptr;
}
SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height()); SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
if (!rtContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
return nullptr;
}
return rtContext->asTextureProxyRef(); return GrSurfaceProxy::Copy(context, proxy.get(), mipMapped, subset, SkBackingFit::kExact,
SkBudgeted::kYes);
} }
} }

View File

@ -310,8 +310,7 @@ public:
* copy rect must equal src's bounds. * copy rect must equal src's bounds.
*/ */
virtual bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, virtual bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
GrSurfaceOrigin* origin, bool* rectsMustMatch, bool* rectsMustMatch, bool* disallowSubrect) const = 0;
bool* disallowSubrect) const = 0;
bool validateSurfaceDesc(const GrSurfaceDesc&, GrMipMapped) const; bool validateSurfaceDesc(const GrSurfaceDesc&, GrMipMapped) const;

View File

@ -15,6 +15,7 @@
#include "src/gpu/GrGpu.h" #include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h" #include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrSurfaceContextPriv.h"
#include "src/gpu/GrSurfacePriv.h" #include "src/gpu/GrSurfacePriv.h"
#include "src/gpu/GrTextureContext.h" #include "src/gpu/GrTextureContext.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"

View File

@ -222,10 +222,8 @@ sk_sp<GrGpuBuffer> GrGpu::createBuffer(size_t size, GrGpuBufferType intendedType
return buffer; return buffer;
} }
bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrGpu::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) {
GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext); GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext);
SkASSERT(dst && src); SkASSERT(dst && src);
@ -235,8 +233,7 @@ bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
this->handleDirtyContext(); this->handleDirtyContext();
return this->onCopySurface(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint, return this->onCopySurface(dst, src, srcRect, dstPoint, canDiscardOutsideDstRect);
canDiscardOutsideDstRect);
} }
bool GrGpu::readPixels(GrSurface* surface, int left, int top, int width, int height, bool GrGpu::readPixels(GrSurface* surface, int left, int top, int width, int height,

View File

@ -253,13 +253,11 @@ public:
// Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst // Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst
// take place at the GrOpList level and this function implement faster copy paths. The rect // take place at the GrOpList level and this function implement faster copy paths. The rect
// and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the // and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the
// src/dst bounds and non-empty. If canDiscardOutsideDstRect is set to true then we don't need // src/dst bounds and non-empty. They must also be in their exact device space coords, including
// to preserve any data on the dst surface outside of the copy. // already being transformed for origin if need be. If canDiscardOutsideDstRect is set to true
bool copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, // then we don't need to preserve any data on the dst surface outside of the copy.
GrSurface* src, GrSurfaceOrigin srcOrigin, bool copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIRect& srcRect, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect = false);
const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect = false);
// Queries the per-pixel HW sample locations for the given render target, and then finds or // Queries the per-pixel HW sample locations for the given render target, and then finds or
// assigns a key that uniquely identifies the sample pattern. The actual sample locations can be // assigns a key that uniquely identifies the sample pattern. The actual sample locations can be
@ -537,10 +535,8 @@ private:
virtual bool onRegenerateMipMapLevels(GrTexture*) = 0; virtual bool onRegenerateMipMapLevels(GrTexture*) = 0;
// overridden by backend specific derived class to perform the copy surface // overridden by backend specific derived class to perform the copy surface
virtual bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, virtual bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) = 0;
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) = 0;
virtual void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access, virtual void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
const GrFlushInfo&, const GrPrepareForExternalIORequests&) = 0; const GrFlushInfo&, const GrPrepareForExternalIORequests&) = 0;

View File

@ -30,9 +30,9 @@ public:
virtual ~GrGpuCommandBuffer() {} virtual ~GrGpuCommandBuffer() {}
// Copy src into current surface owned by either a GrGpuTextureCommandBuffer or // Copy src into current surface owned by either a GrGpuTextureCommandBuffer or
// GrGpuRenderTargetCommandBuffer. // GrGpuRenderTargetCommandBuffer. The srcRect and dstPoint must be in dst coords and have
virtual void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, // already been adjusted for any origin flips.
const SkIRect& srcRect, const SkIPoint& dstPoint) = 0; virtual void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
// Initiates a transfer from the surface owned by the command buffer to the GrGpuBuffer. // Initiates a transfer from the surface owned by the command buffer to the GrGpuBuffer.
virtual void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, virtual void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) = 0; GrGpuBuffer* transferBuffer, size_t offset) = 0;
@ -47,19 +47,14 @@ public:
void set(GrTexture* texture, GrSurfaceOrigin origin) { void set(GrTexture* texture, GrSurfaceOrigin origin) {
SkASSERT(!fTexture); SkASSERT(!fTexture);
fOrigin = origin;
fTexture = texture; fTexture = texture;
} }
protected: protected:
GrGpuTextureCommandBuffer() : fOrigin(kTopLeft_GrSurfaceOrigin), fTexture(nullptr) {} GrGpuTextureCommandBuffer() : fTexture(nullptr) {}
GrGpuTextureCommandBuffer(GrTexture* texture, GrSurfaceOrigin origin) GrGpuTextureCommandBuffer(GrTexture* texture, GrSurfaceOrigin origin) : fTexture(texture) {}
: fOrigin(origin)
, fTexture(texture) {
}
GrSurfaceOrigin fOrigin;
GrTexture* fTexture; GrTexture* fTexture;
private: private:

View File

@ -1785,27 +1785,17 @@ sk_sp<GrRenderTargetContext> GrRenderTargetContext::rescale(const SkImageInfo& i
int srcH = srcRect.height(); int srcH = srcRect.height();
int srcX = srcRect.fLeft; int srcX = srcRect.fLeft;
int srcY = srcRect.fTop; int srcY = srcRect.fTop;
sk_sp<GrSurfaceContext> srcContext = sk_ref_sp(this); sk_sp<GrTextureProxy> texProxy = sk_ref_sp(fRenderTargetProxy->asTextureProxy());
SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint; SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
if (!this->asTextureProxy()) { if (!texProxy) {
GrSurfaceDesc desc; texProxy = GrSurfaceProxy::Copy(fContext, fRenderTargetProxy.get(), GrMipMapped::kNo,
desc.fWidth = srcW; srcRect, SkBackingFit::kApprox, SkBudgeted::kNo);
desc.fHeight = srcH; if (!texProxy) {
desc.fConfig = fRenderTargetProxy->config();
auto sContext = direct->priv().makeDeferredSurfaceContext(
fRenderTargetProxy->backendFormat().makeTexture2D(), desc, this->origin(),
GrMipMapped::kNo, SkBackingFit::kApprox, SkBudgeted::kNo,
this->colorSpaceInfo().refColorSpace());
if (!sContext) {
return nullptr;
}
if (!sContext->copy(fRenderTargetProxy.get(), srcRect, {0, 0})) {
return nullptr; return nullptr;
} }
srcX = 0; srcX = 0;
srcY = 0; srcY = 0;
constraint = SkCanvas::kFast_SrcRectConstraint; constraint = SkCanvas::kFast_SrcRectConstraint;
srcContext = std::move(sContext);
} }
float sx = (float)info.width() / srcW; float sx = (float)info.width() / srcW;
@ -1824,33 +1814,35 @@ sk_sp<GrRenderTargetContext> GrRenderTargetContext::rescale(const SkImageInfo& i
stepsY = sy != 1.f; stepsY = sy != 1.f;
} }
SkASSERT(stepsX || stepsY); SkASSERT(stepsX || stepsY);
auto currentColorSpace = this->colorSpaceInfo().refColorSpace();
// Assume we should ignore the rescale linear request if the surface has no color space since // Assume we should ignore the rescale linear request if the surface has no color space since
// it's unclear how we'd linearize from an unknown color space. // it's unclear how we'd linearize from an unknown color space.
if (rescaleGamma == SkSurface::RescaleGamma::kLinear && if (rescaleGamma == SkSurface::RescaleGamma::kLinear &&
srcContext->colorSpaceInfo().colorSpace() && currentColorSpace.get() && !currentColorSpace->gammaIsLinear()) {
!srcContext->colorSpaceInfo().colorSpace()->gammaIsLinear()) { auto cs = currentColorSpace->makeLinearGamma();
auto cs = srcContext->colorSpaceInfo().colorSpace()->makeLinearGamma();
auto backendFormat = this->caps()->getBackendFormatFromGrColorType(GrColorType::kRGBA_F16, auto backendFormat = this->caps()->getBackendFormatFromGrColorType(GrColorType::kRGBA_F16,
GrSRGBEncoded::kNo); GrSRGBEncoded::kNo);
auto xform = GrColorSpaceXform::Make(srcContext->colorSpaceInfo().colorSpace(), auto xform = GrColorSpaceXform::Make(currentColorSpace.get(), kPremul_SkAlphaType, cs.get(),
kPremul_SkAlphaType, cs.get(), kPremul_SkAlphaType); kPremul_SkAlphaType);
// We'll fall back to kRGBA_8888 if half float not supported. // We'll fall back to kRGBA_8888 if half float not supported.
auto linearRTC = fContext->priv().makeDeferredRenderTargetContextWithFallback( auto linearRTC = fContext->priv().makeDeferredRenderTargetContextWithFallback(
backendFormat, SkBackingFit::kExact, srcW, srcH, kRGBA_half_GrPixelConfig, backendFormat, SkBackingFit::kExact, srcW, srcH, kRGBA_half_GrPixelConfig, cs, 1,
std::move(cs), 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
if (!linearRTC) { if (!linearRTC) {
return nullptr; return nullptr;
} }
linearRTC->drawTexture(GrNoClip(), srcContext->asTextureProxyRef(), linearRTC->drawTexture(GrNoClip(), texProxy,
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
SK_PMColor4fWHITE, SkRect::Make(srcRect), SkRect::MakeWH(srcW, srcH), SK_PMColor4fWHITE, SkRect::Make(srcRect), SkRect::MakeWH(srcW, srcH),
GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(), GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(),
std::move(xform)); std::move(xform));
srcContext = std::move(linearRTC); texProxy = linearRTC->asTextureProxyRef();
currentColorSpace = std::move(cs);
srcX = 0; srcX = 0;
srcY = 0; srcY = 0;
constraint = SkCanvas::kFast_SrcRectConstraint; constraint = SkCanvas::kFast_SrcRectConstraint;
} }
sk_sp<GrRenderTargetContext> currRTC;
while (stepsX || stepsY) { while (stepsX || stepsY) {
int nextW = info.width(); int nextW = info.width();
int nextH = info.height(); int nextH = info.height();
@ -1872,23 +1864,22 @@ sk_sp<GrRenderTargetContext> GrRenderTargetContext::rescale(const SkImageInfo& i
} }
--stepsY; --stepsY;
} }
GrBackendFormat backendFormat = GrBackendFormat backendFormat = texProxy->backendFormat().makeTexture2D();
srcContext->asSurfaceProxy()->backendFormat().makeTexture2D(); GrPixelConfig config = texProxy->config();
GrPixelConfig config = srcContext->asSurfaceProxy()->config(); auto cs = currentColorSpace;
auto cs = srcContext->colorSpaceInfo().refColorSpace();
sk_sp<GrColorSpaceXform> xform; sk_sp<GrColorSpaceXform> xform;
if (!stepsX && !stepsY) { if (!stepsX && !stepsY) {
// Might as well fold conversion to final info in the last step. // Might as well fold conversion to final info in the last step.
backendFormat = this->caps()->getBackendFormatFromColorType(info.colorType()); backendFormat = this->caps()->getBackendFormatFromColorType(info.colorType());
config = this->caps()->getConfigFromBackendFormat(backendFormat, info.colorType()); config = this->caps()->getConfigFromBackendFormat(backendFormat, info.colorType());
cs = info.refColorSpace(); cs = info.refColorSpace();
xform = GrColorSpaceXform::Make(srcContext->colorSpaceInfo().colorSpace(), xform = GrColorSpaceXform::Make(this->colorSpaceInfo().colorSpace(),
kPremul_SkAlphaType, cs.get(), info.alphaType()); kPremul_SkAlphaType, cs.get(), info.alphaType());
} }
auto nextRTC = fContext->priv().makeDeferredRenderTargetContextWithFallback( currRTC = fContext->priv().makeDeferredRenderTargetContextWithFallback(
backendFormat, SkBackingFit::kExact, nextW, nextH, config, std::move(cs), 1, backendFormat, SkBackingFit::kExact, nextW, nextH, config, std::move(cs), 1,
GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
if (!nextRTC) { if (!currRTC) {
return nullptr; return nullptr;
} }
auto dstRect = SkRect::MakeWH(nextW, nextH); auto dstRect = SkRect::MakeWH(nextW, nextH);
@ -1902,14 +1893,12 @@ sk_sp<GrRenderTargetContext> GrRenderTargetContext::rescale(const SkImageInfo& i
} else if (nextH == srcH) { } else if (nextH == srcH) {
dir = GrBicubicEffect::Direction::kX; dir = GrBicubicEffect::Direction::kX;
} }
if (srcW != srcContext->width() || srcH != srcContext->height()) { if (srcW != texProxy->width() || srcH != texProxy->height()) {
auto domain = GrTextureDomain::MakeTexelDomain( auto domain = GrTextureDomain::MakeTexelDomain(
SkIRect::MakeXYWH(srcX, srcY, srcW, srcH), GrTextureDomain::kClamp_Mode); SkIRect::MakeXYWH(srcX, srcY, srcW, srcH), GrTextureDomain::kClamp_Mode);
fp = GrBicubicEffect::Make(srcContext->asTextureProxyRef(), matrix, domain, dir, fp = GrBicubicEffect::Make(texProxy, matrix, domain, dir, kPremul_SkAlphaType);
kPremul_SkAlphaType);
} else { } else {
fp = GrBicubicEffect::Make(srcContext->asTextureProxyRef(), matrix, dir, fp = GrBicubicEffect::Make(texProxy, matrix, dir, kPremul_SkAlphaType);
kPremul_SkAlphaType);
} }
if (xform) { if (xform) {
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform)); fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
@ -1917,26 +1906,24 @@ sk_sp<GrRenderTargetContext> GrRenderTargetContext::rescale(const SkImageInfo& i
GrPaint paint; GrPaint paint;
paint.addColorFragmentProcessor(std::move(fp)); paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc); paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
nextRTC->drawFilledRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), currRTC->drawFilledRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
dstRect); dstRect);
} else { } else {
auto filter = rescaleQuality == kNone_SkFilterQuality ? GrSamplerState::Filter::kNearest auto filter = rescaleQuality == kNone_SkFilterQuality ? GrSamplerState::Filter::kNearest
: GrSamplerState::Filter::kBilerp; : GrSamplerState::Filter::kBilerp;
auto srcSubset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH); auto srcSubset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH);
nextRTC->drawTexture(GrNoClip(), srcContext->asTextureProxyRef(), filter, currRTC->drawTexture(GrNoClip(), texProxy, filter, SkBlendMode::kSrc, SK_PMColor4fWHITE,
SkBlendMode::kSrc, SK_PMColor4fWHITE, srcSubset, dstRect, srcSubset, dstRect, GrAA::kNo, GrQuadAAFlags::kNone, constraint,
GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(), SkMatrix::I(), std::move(xform));
std::move(xform));
} }
srcContext = std::move(nextRTC); texProxy = currRTC->asTextureProxyRef();
srcX = srcY = 0; srcX = srcY = 0;
srcW = nextW; srcW = nextW;
srcH = nextH; srcH = nextH;
constraint = SkCanvas::kFast_SrcRectConstraint; constraint = SkCanvas::kFast_SrcRectConstraint;
} }
auto result = sk_ref_sp(srcContext->asRenderTargetContext()); SkASSERT(currRTC);
SkASSERT(result); return currRTC;
return result;
} }
void GrRenderTargetContext::asyncRescaleAndReadPixels( void GrRenderTargetContext::asyncRescaleAndReadPixels(
@ -2001,24 +1988,13 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels(
SkRect srcRectToDraw = SkRect::Make(srcRect); SkRect srcRectToDraw = SkRect::Make(srcRect);
// If the src is not texturable first try to make a copy to a texture. // If the src is not texturable first try to make a copy to a texture.
if (!texProxy) { if (!texProxy) {
GrSurfaceDesc desc; texProxy = GrSurfaceProxy::Copy(fContext, fRenderTargetProxy.get(),
desc.fWidth = srcRect.width(); GrMipMapped::kNo, srcRect, SkBackingFit::kApprox,
desc.fHeight = srcRect.height(); SkBudgeted::kNo);
desc.fConfig = fRenderTargetProxy->config(); if (!texProxy) {
auto sContext = direct->priv().makeDeferredSurfaceContext(
backendFormat, desc, this->origin(), GrMipMapped::kNo,
SkBackingFit::kApprox, SkBudgeted::kNo,
this->colorSpaceInfo().refColorSpace());
if (!sContext) {
callback(context, nullptr, 0); callback(context, nullptr, 0);
return; return;
} }
if (!sContext->copy(fRenderTargetProxy.get(), srcRect, {0, 0})) {
callback(context, nullptr, 0);
return;
}
texProxy = sk_ref_sp(sContext->asTextureProxy());
SkASSERT(texProxy);
srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height()); srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height());
} }
rtc = direct->priv().makeDeferredRenderTargetContext( rtc = direct->priv().makeDeferredRenderTargetContext(
@ -2568,12 +2544,10 @@ bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const Gr
GrSurfaceDesc desc; GrSurfaceDesc desc;
bool rectsMustMatch = false; bool rectsMustMatch = false;
bool disallowSubrect = false; bool disallowSubrect = false;
GrSurfaceOrigin origin; if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &rectsMustMatch,
if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &origin, &rectsMustMatch,
&disallowSubrect)) { &disallowSubrect)) {
desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fConfig = rtProxy->config(); desc.fConfig = rtProxy->config();
origin = rtProxy->origin();
} }
if (!disallowSubrect) { if (!disallowSubrect) {
@ -2582,36 +2556,56 @@ bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const Gr
SkIPoint dstPoint, dstOffset; SkIPoint dstPoint, dstOffset;
SkBackingFit fit; SkBackingFit fit;
GrSurfaceProxy::RectsMustMatch matchRects;
if (rectsMustMatch) { if (rectsMustMatch) {
desc.fWidth = rtProxy->width(); desc.fWidth = rtProxy->width();
desc.fHeight = rtProxy->height(); desc.fHeight = rtProxy->height();
dstPoint = {copyRect.fLeft, copyRect.fTop}; dstPoint = {copyRect.fLeft, copyRect.fTop};
dstOffset = {0, 0}; dstOffset = {0, 0};
fit = SkBackingFit::kExact; fit = SkBackingFit::kExact;
matchRects = GrSurfaceProxy::RectsMustMatch::kYes;
} else { } else {
desc.fWidth = copyRect.width(); desc.fWidth = copyRect.width();
desc.fHeight = copyRect.height(); desc.fHeight = copyRect.height();
dstPoint = {0, 0}; dstPoint = {0, 0};
dstOffset = {copyRect.fLeft, copyRect.fTop}; dstOffset = {copyRect.fLeft, copyRect.fTop};
fit = SkBackingFit::kApprox; fit = SkBackingFit::kApprox;
matchRects = GrSurfaceProxy::RectsMustMatch::kNo;
} }
SkASSERT(rtProxy->backendFormat().textureType() == GrTextureType::k2D); sk_sp<GrTextureProxy> newProxy = GrSurfaceProxy::Copy(fContext, rtProxy, GrMipMapped::kNo,
const GrBackendFormat& format = rtProxy->backendFormat(); copyRect, fit, SkBudgeted::kYes,
sk_sp<GrSurfaceContext> sContext = fContext->priv().makeDeferredSurfaceContext( matchRects);
format, desc, origin, GrMipMapped::kNo, fit, SkBudgeted::kYes, SkASSERT(newProxy);
sk_ref_sp(this->colorSpaceInfo().colorSpace()));
if (!sContext) {
SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
return false;
}
if (!sContext->copy(rtProxy, copyRect, dstPoint)) { dstProxy->setProxy(std::move(newProxy));
SkDebugf("setupDstTexture: copy failed.\n");
return false;
}
dstProxy->setProxy(sContext->asTextureProxyRef());
dstProxy->setOffset(dstOffset); dstProxy->setOffset(dstOffset);
return true; return true;
} }
bool GrRenderTargetContext::blitTexture(GrTextureProxy* src, const SkIRect& srcRect,
const SkIPoint& dstPoint) {
SkIRect clippedSrcRect;
SkIPoint clippedDstPoint;
if (!GrClipSrcRectAndDstPoint(this->asSurfaceProxy()->isize(), src->isize(), srcRect, dstPoint,
&clippedSrcRect, &clippedDstPoint)) {
return false;
}
GrPaint paint;
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
auto fp = GrSimpleTextureEffect::Make(sk_ref_sp(src->asTextureProxy()),
SkMatrix::I());
if (!fp) {
return false;
}
paint.addColorFragmentProcessor(std::move(fp));
this->fillRectToRect(
GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::MakeXYWH(clippedDstPoint.fX, clippedDstPoint.fY, clippedSrcRect.width(),
clippedSrcRect.height()),
SkRect::Make(clippedSrcRect));
return true;
}

View File

@ -396,6 +396,13 @@ public:
std::unique_ptr<SkLatticeIter>, std::unique_ptr<SkLatticeIter>,
const SkRect& dst); const SkRect& dst);
/**
* Draws the src texture with no matrix. The dstRect is the dstPoint with the width and height
* of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces
* respectively.
*/
bool blitTexture(GrTextureProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint);
/** /**
* Adds the necessary signal and wait semaphores and adds the passed in SkDrawable to the * Adds the necessary signal and wait semaphores and adds the passed in SkDrawable to the
* command stream. * command stream.

View File

@ -5,6 +5,8 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "src/gpu/GrSurfaceContext.h"
#include "include/private/GrAuditTrail.h" #include "include/private/GrAuditTrail.h"
#include "include/private/GrOpList.h" #include "include/private/GrOpList.h"
#include "include/private/GrRecordingContext.h" #include "include/private/GrRecordingContext.h"
@ -15,7 +17,7 @@
#include "src/gpu/GrGpu.h" #include "src/gpu/GrGpu.h"
#include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrSurfaceContext.h" #include "src/gpu/GrSurfaceContextPriv.h"
#include "src/gpu/GrSurfacePriv.h" #include "src/gpu/GrSurfacePriv.h"
#include "src/gpu/GrTextureContext.h" #include "src/gpu/GrTextureContext.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"
@ -377,7 +379,7 @@ bool GrSurfaceContext::writePixelsImpl(GrContext* direct, int left, int top, int
} }
auto tempProxy = direct->priv().proxyProvider()->createProxy( auto tempProxy = direct->priv().proxyProvider()->createProxy(
format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes); format, desc, dstProxy->origin(), SkBackingFit::kApprox, SkBudgeted::kYes);
if (!tempProxy) { if (!tempProxy) {
return false; return false;
} }
@ -399,7 +401,7 @@ bool GrSurfaceContext::writePixelsImpl(GrContext* direct, int left, int top, int
} }
if (this->asRenderTargetContext()) { if (this->asRenderTargetContext()) {
std::unique_ptr<GrFragmentProcessor> fp; std::unique_ptr<GrFragmentProcessor> fp;
if (canvas2DFastPath) { if (canvas2DFastPath) {
fp = direct->priv().createUPMToPMEffect( fp = direct->priv().createUPMToPMEffect(
GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I())); GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
@ -421,10 +423,9 @@ bool GrSurfaceContext::writePixelsImpl(GrContext* direct, int left, int top, int
} else { } else {
SkIRect srcRect = SkIRect::MakeWH(width, height); SkIRect srcRect = SkIRect::MakeWH(width, height);
SkIPoint dstPoint = SkIPoint::Make(left, top); SkIPoint dstPoint = SkIPoint::Make(left, top);
if (!caps->canCopySurface(this->asSurfaceProxy(), tempProxy.get(), srcRect, dstPoint)) { if (!this->copy(tempProxy.get(), srcRect, dstPoint)) {
return false; return false;
} }
SkAssertResult(this->copy(tempProxy.get(), srcRect, dstPoint));
} }
return true; return true;
} }
@ -531,13 +532,17 @@ bool GrSurfaceContext::copy(GrSurfaceProxy* src, const SkIRect& srcRect, const S
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(this->auditTrail(), "GrSurfaceContext::copy"); GR_AUDIT_TRAIL_AUTO_FRAME(this->auditTrail(), "GrSurfaceContextPriv::copy");
if (!fContext->priv().caps()->canCopySurface(this->asSurfaceProxy(), src, srcRect, SkASSERT(src->backendFormat().textureType() != GrTextureType::kExternal);
dstPoint)) { SkASSERT(src->origin() == this->asSurfaceProxy()->origin());
GrSurfaceProxy* dst = this->asSurfaceProxy();
if (!fContext->priv().caps()->canCopySurface(dst, src, srcRect, dstPoint)) {
return false; return false;
} }
return this->getOpList()->copySurface(fContext, this->asSurfaceProxy(), return this->getOpList()->copySurface(fContext, dst, src, srcRect, dstPoint);
src, srcRect, dstPoint);
} }

View File

@ -39,26 +39,6 @@ public:
int width() const { return this->asSurfaceProxy()->width(); } int width() const { return this->asSurfaceProxy()->width(); }
int height() const { return this->asSurfaceProxy()->height(); } int height() const { return this->asSurfaceProxy()->height(); }
/*
* Copy 'src' into the proxy backing this context
* @param src src of pixels
* @param srcRect the subset of 'src' to copy
* @param dstPoint the origin of the 'srcRect' in the destination coordinate space
* @return true if the copy succeeded; false otherwise
*
* Note: Notionally, 'srcRect' is clipped to 'src's extent with 'dstPoint' being adjusted.
* Then the 'srcRect' offset by 'dstPoint' is clipped against the dst's extent.
* The end result is only valid src pixels and dst pixels will be touched but the copied
* regions will not be shifted.
*/
bool copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint);
bool copy(GrSurfaceProxy* src) {
return this->copy(src,
SkIRect::MakeWH(src->width(), src->height()),
SkIPoint::Make(0, 0));
}
/** /**
* These flags can be used with the read/write pixels functions below. * These flags can be used with the read/write pixels functions below.
*/ */
@ -134,6 +114,17 @@ public:
GrSurfaceContextPriv surfPriv(); GrSurfaceContextPriv surfPriv();
const GrSurfaceContextPriv surfPriv() const; const GrSurfaceContextPriv surfPriv() const;
#if GR_TEST_UTILS
bool testCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
return this->copy(src, srcRect, dstPoint);
}
bool testCopy(GrSurfaceProxy* src) {
return this->copy(src);
}
#endif
protected: protected:
friend class GrSurfaceContextPriv; friend class GrSurfaceContextPriv;
@ -150,6 +141,29 @@ protected:
GrRecordingContext* fContext; GrRecordingContext* fContext;
private: private:
friend class GrSurfaceProxy; // for copy
/**
* Copy 'src' into the proxy backing this context. This call will not do any draw fallback.
* Currently only writePixels and replaceRenderTarget call this directly. All other copies
* should go through GrSurfaceProxy::Copy.
* @param src src of pixels
* @param srcRect the subset of 'src' to copy
* @param dstPoint the origin of the 'srcRect' in the destination coordinate space
* @return true if the copy succeeded; false otherwise
*
* Note: Notionally, 'srcRect' is clipped to 'src's extent with 'dstPoint' being adjusted.
* Then the 'srcRect' offset by 'dstPoint' is clipped against the dst's extent.
* The end result is only valid src pixels and dst pixels will be touched but the copied
* regions will not be shifted. The 'src' must have the same origin as the backing proxy
* of fSurfaceContext.
*/
bool copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint);
bool copy(GrSurfaceProxy* src) {
return this->copy(src, SkIRect::MakeWH(src->width(), src->height()), SkIPoint::Make(0, 0));
}
bool writePixelsImpl(GrContext* direct, int left, int top, int width, int height, bool writePixelsImpl(GrContext* direct, int left, int top, int width, int height,
GrColorType srcColorType, SkColorSpace* srcColorSpace, GrColorType srcColorType, SkColorSpace* srcColorSpace,
const void* srcBuffer, size_t srcRowBytes, uint32_t pixelOpsFlags); const void* srcBuffer, size_t srcRowBytes, uint32_t pixelOpsFlags);

View File

@ -12,11 +12,13 @@
#include "include/private/GrOpList.h" #include "include/private/GrOpList.h"
#include "include/private/GrRecordingContext.h" #include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h" #include "src/gpu/GrCaps.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h" #include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpuResourcePriv.h" #include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceContext.h" #include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrSurfaceContextPriv.h"
#include "src/gpu/GrSurfacePriv.h" #include "src/gpu/GrSurfacePriv.h"
#include "src/gpu/GrTexturePriv.h" #include "src/gpu/GrTexturePriv.h"
#include "src/gpu/GrTextureRenderTargetProxy.h" #include "src/gpu/GrTextureRenderTargetProxy.h"
@ -335,33 +337,54 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
GrMipMapped mipMapped, GrMipMapped mipMapped,
SkIRect srcRect, SkIRect srcRect,
SkBackingFit fit, SkBackingFit fit,
SkBudgeted budgeted) { SkBudgeted budgeted,
RectsMustMatch rectsMustMatch) {
SkASSERT(LazyState::kFully != src->lazyInstantiationState()); SkASSERT(LazyState::kFully != src->lazyInstantiationState());
GrSurfaceDesc dstDesc;
dstDesc.fConfig = src->config();
SkIPoint dstPoint;
if (rectsMustMatch == RectsMustMatch::kYes) {
dstDesc.fWidth = src->width();
dstDesc.fHeight = src->height();
dstPoint = {srcRect.fLeft, srcRect.fTop};
} else {
dstDesc.fWidth = srcRect.width();
dstDesc.fHeight = srcRect.height();
dstPoint = {0, 0};
}
if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) { if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
return nullptr; return nullptr;
} }
GrSurfaceDesc dstDesc; if (src->backendFormat().textureType() != GrTextureType::kExternal) {
dstDesc.fWidth = srcRect.width(); sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext(
dstDesc.fHeight = srcRect.height(); src->backendFormat().makeTexture2D(), dstDesc, src->origin(), mipMapped, fit,
dstDesc.fConfig = src->config(); budgeted));
if (!dstContext) {
GrBackendFormat format = src->backendFormat().makeTexture2D(); return nullptr;
if (!format.isValid()) { }
return nullptr; if (dstContext->copy(src, srcRect, dstPoint)) {
return dstContext->asTextureProxyRef();
}
} }
if (src->asTextureProxy()) {
GrBackendFormat format = src->backendFormat().makeTexture2D();
if (!format.isValid()) {
return nullptr;
}
sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext( sk_sp<GrRenderTargetContext> dstContext = context->priv().makeDeferredRenderTargetContext(
format, dstDesc, src->origin(), mipMapped, fit, budgeted)); format, fit, dstDesc.fWidth, dstDesc.fHeight, dstDesc.fConfig, nullptr, 1,
if (!dstContext) { mipMapped, src->origin(), nullptr, budgeted);
return nullptr;
if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
return dstContext->asTextureProxyRef();
}
} }
// Can't use backend copies or draws.
if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) { return nullptr;
return nullptr;
}
return dstContext->asTextureProxyRef();
} }
sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src, sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
@ -372,29 +395,6 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfac
budgeted); budgeted);
} }
sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrRecordingContext* context,
const GrSurfaceDesc& dstDesc,
GrSurfaceOrigin origin, GrSurfaceProxy* srcProxy) {
SkASSERT(LazyState::kFully != srcProxy->lazyInstantiationState());
GrBackendFormat format = srcProxy->backendFormat().makeTexture2D();
if (!format.isValid()) {
return nullptr;
}
sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext(
format, dstDesc, origin, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kYes));
if (!dstContext) {
return nullptr;
}
if (!dstContext->copy(srcProxy)) {
return nullptr;
}
return dstContext;
}
void GrSurfaceProxyPriv::exactify() { void GrSurfaceProxyPriv::exactify() {
SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState()); SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
if (this->isExact()) { if (this->isExact()) {

View File

@ -254,7 +254,11 @@ void SkGpuDevice::replaceRenderTargetContext(sk_sp<GrRenderTargetContext> rtc,
if (this->context()->abandoned()) { if (this->context()->abandoned()) {
return; return;
} }
rtc->copy(fRenderTargetContext->asSurfaceProxy());
SkASSERT(fRenderTargetContext->asTextureProxy());
SkAssertResult(rtc->blitTexture(fRenderTargetContext->asTextureProxy(),
SkIRect::MakeWH(this->width(), this->height()),
SkIPoint::Make(0,0)));
} }
fRenderTargetContext = std::move(rtc); fRenderTargetContext = std::move(rtc);

View File

@ -133,31 +133,8 @@ sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
return nullptr; return nullptr;
} }
GrProxyProvider* proxyProvider = ctx->priv().proxyProvider(); return GrSurfaceProxy::Copy(ctx, baseProxy, GrMipMapped::kYes, SkBackingFit::kExact,
GrSurfaceDesc desc; SkBudgeted::kYes);
desc.fFlags = kNone_GrSurfaceFlags;
desc.fWidth = baseProxy->width();
desc.fHeight = baseProxy->height();
desc.fConfig = baseProxy->config();
desc.fSampleCnt = 1;
GrBackendFormat format = baseProxy->backendFormat().makeTexture2D();
if (!format.isValid()) {
return nullptr;
}
sk_sp<GrTextureProxy> proxy =
proxyProvider->createMipMapProxy(format, desc, baseProxy->origin(), SkBudgeted::kYes);
if (!proxy) {
return nullptr;
}
// Copy the base layer to our proxy
sk_sp<GrSurfaceContext> sContext = ctx->priv().makeWrappedSurfaceContext(proxy);
SkASSERT(sContext);
SkAssertResult(sContext->copy(baseProxy));
return proxy;
} }
sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrRecordingContext* ctx, sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrRecordingContext* ctx,

View File

@ -82,4 +82,60 @@ static inline void GrMapRectPoints(const SkRect& inRect, const SkRect& outRect,
SkMatrix rectTransform = SkMatrix::MakeRectToRect(inRect, outRect, SkMatrix::kFill_ScaleToFit); SkMatrix rectTransform = SkMatrix::MakeRectToRect(inRect, outRect, SkMatrix::kFill_ScaleToFit);
rectTransform.mapPoints(outPts, inPts, ptCount); rectTransform.mapPoints(outPts, inPts, ptCount);
} }
/**
* Clips the srcRect and the dstPoint to the bounds of the srcSize and dstSize respectively. Returns
* true if the srcRect and dstRect intersect the srcRect and dst rect (dstPoint with srcRect
* width/height). Returns false otherwise. The clipped values are returned in clippedSrcRect and
* clippedDstPoint.
*/
static inline bool GrClipSrcRectAndDstPoint(const SkISize& dstSize,
const SkISize& srcSize,
const SkIRect& srcRect,
const SkIPoint& dstPoint,
SkIRect* clippedSrcRect,
SkIPoint* clippedDstPoint) {
*clippedSrcRect = srcRect;
*clippedDstPoint = dstPoint;
// clip the left edge to src and dst bounds, adjusting dstPoint if necessary
if (clippedSrcRect->fLeft < 0) {
clippedDstPoint->fX -= clippedSrcRect->fLeft;
clippedSrcRect->fLeft = 0;
}
if (clippedDstPoint->fX < 0) {
clippedSrcRect->fLeft -= clippedDstPoint->fX;
clippedDstPoint->fX = 0;
}
// clip the top edge to src and dst bounds, adjusting dstPoint if necessary
if (clippedSrcRect->fTop < 0) {
clippedDstPoint->fY -= clippedSrcRect->fTop;
clippedSrcRect->fTop = 0;
}
if (clippedDstPoint->fY < 0) {
clippedSrcRect->fTop -= clippedDstPoint->fY;
clippedDstPoint->fY = 0;
}
// clip the right edge to the src and dst bounds.
if (clippedSrcRect->fRight > srcSize.width()) {
clippedSrcRect->fRight = srcSize.width();
}
if (clippedDstPoint->fX + clippedSrcRect->width() > dstSize.width()) {
clippedSrcRect->fRight = clippedSrcRect->fLeft + dstSize.width() - clippedDstPoint->fX;
}
// clip the bottom edge to the src and dst bounds.
if (clippedSrcRect->fBottom > srcSize.height()) {
clippedSrcRect->fBottom = srcSize.height();
}
if (clippedDstPoint->fY + clippedSrcRect->height() > dstSize.height()) {
clippedSrcRect->fBottom = clippedSrcRect->fTop + dstSize.height() - clippedDstPoint->fY;
}
// The above clipping steps may have inverted the rect if it didn't intersect either the src or
// dst bounds.
return !clippedSrcRect->isEmpty();
}
#endif #endif

View File

@ -2358,11 +2358,9 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
} }
bool GrGLCaps::canCopyTexSubImage(GrPixelConfig dstConfig, bool dstHasMSAARenderBuffer, bool GrGLCaps::canCopyTexSubImage(GrPixelConfig dstConfig, bool dstHasMSAARenderBuffer,
bool dstIsTextureable, bool dstIsGLTexture2D, const GrTextureType* dstTypeIfTexture,
GrSurfaceOrigin dstOrigin,
GrPixelConfig srcConfig, bool srcHasMSAARenderBuffer, GrPixelConfig srcConfig, bool srcHasMSAARenderBuffer,
bool srcIsTextureable, bool srcIsGLTexture2D, const GrTextureType* srcTypeIfTexture) const {
GrSurfaceOrigin srcOrigin) const {
// Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage
// and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps // and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
// many drivers would allow it to work, but ANGLE does not. // many drivers would allow it to work, but ANGLE does not.
@ -2378,16 +2376,15 @@ bool GrGLCaps::canCopyTexSubImage(GrPixelConfig dstConfig, bool dstHasMSAARender
// CopyTex(Sub)Image writes to a texture and we have no way of dynamically wrapping a RT in a // CopyTex(Sub)Image writes to a texture and we have no way of dynamically wrapping a RT in a
// texture. // texture.
if (!dstIsTextureable) { if (!dstTypeIfTexture) {
return false; return false;
} }
// Check that we could wrap the source in an FBO, that the dst is TEXTURE_2D, that no mirroring // Check that we could wrap the source in an FBO, that the dst is not TEXTURE_EXTERNAL, that no
// is required // mirroring is required
if (this->canConfigBeFBOColorAttachment(srcConfig) && if (this->canConfigBeFBOColorAttachment(srcConfig) &&
(!srcIsTextureable || srcIsGLTexture2D) && (!srcTypeIfTexture || *srcTypeIfTexture != GrTextureType::kExternal) &&
dstIsGLTexture2D && *dstTypeIfTexture != GrTextureType::kExternal) {
dstOrigin == srcOrigin) {
return true; return true;
} else { } else {
return false; return false;
@ -2395,11 +2392,10 @@ bool GrGLCaps::canCopyTexSubImage(GrPixelConfig dstConfig, bool dstHasMSAARender
} }
bool GrGLCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool GrGLCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt,
bool dstIsTextureable, bool dstIsGLTexture2D, const GrTextureType* dstTypeIfTexture,
GrSurfaceOrigin dstOrigin,
GrPixelConfig srcConfig, int srcSampleCnt, GrPixelConfig srcConfig, int srcSampleCnt,
bool srcIsTextureable, bool srcIsGLTexture2D, const GrTextureType* srcTypeIfTexture,
GrSurfaceOrigin srcOrigin, const SkRect& srcBounds, const SkRect& srcBounds, bool srcBoundsExact,
const SkIRect& srcRect, const SkIPoint& dstPoint) const { const SkIRect& srcRect, const SkIPoint& dstPoint) const {
auto blitFramebufferFlags = this->blitFramebufferSupportFlags(); auto blitFramebufferFlags = this->blitFramebufferSupportFlags();
if (!this->canConfigBeFBOColorAttachment(dstConfig) || if (!this->canConfigBeFBOColorAttachment(dstConfig) ||
@ -2407,30 +2403,23 @@ bool GrGLCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt,
return false; return false;
} }
if (dstIsTextureable && !dstIsGLTexture2D) { if (dstTypeIfTexture && *dstTypeIfTexture == GrTextureType::kExternal) {
return false; return false;
} }
if (srcIsTextureable && !srcIsGLTexture2D) { if (srcTypeIfTexture && *srcTypeIfTexture == GrTextureType::kExternal) {
return false; return false;
} }
if (GrGLCaps::kNoSupport_BlitFramebufferFlag & blitFramebufferFlags) { if (GrGLCaps::kNoSupport_BlitFramebufferFlag & blitFramebufferFlags) {
return false; return false;
} }
if (GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag & blitFramebufferFlags) {
// We would mirror to compensate for origin changes. Note that copySurface is
// specified such that the src and dst rects are the same.
if (dstOrigin != srcOrigin) {
return false;
}
}
if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) { if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) {
if (srcSampleCnt > 1) { if (srcSampleCnt > 1) {
if (1 == dstSampleCnt) { if (1 == dstSampleCnt) {
return false; return false;
} }
if (SkRect::Make(srcRect) != srcBounds) { if (SkRect::Make(srcRect) != srcBounds || !srcBoundsExact) {
return false; return false;
} }
} }
@ -2457,9 +2446,6 @@ bool GrGLCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt,
if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) { if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) {
return false; return false;
} }
if (dstOrigin != srcOrigin) {
return false;
}
} }
} }
return true; return true;
@ -2485,9 +2471,6 @@ static bool has_msaa_render_buffer(const GrSurfaceProxy* surf, const GrGLCaps& g
bool GrGLCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src, bool GrGLCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
const SkIRect& srcRect, const SkIPoint& dstPoint) const { const SkIRect& srcRect, const SkIPoint& dstPoint) const {
GrSurfaceOrigin dstOrigin = dst->origin();
GrSurfaceOrigin srcOrigin = src->origin();
GrPixelConfig dstConfig = dst->config(); GrPixelConfig dstConfig = dst->config();
GrPixelConfig srcConfig = src->config(); GrPixelConfig srcConfig = src->config();
@ -2502,8 +2485,7 @@ bool GrGLCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy*
SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy())); SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy())); SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
// None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the // None of our copy methods can handle a swizzle.
// swizzle.
if (this->shaderCaps()->configOutputSwizzle(src->config()) != if (this->shaderCaps()->configOutputSwizzle(src->config()) !=
this->shaderCaps()->configOutputSwizzle(dst->config())) { this->shaderCaps()->configOutputSwizzle(dst->config())) {
return false; return false;
@ -2512,37 +2494,29 @@ bool GrGLCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy*
const GrTextureProxy* dstTex = dst->asTextureProxy(); const GrTextureProxy* dstTex = dst->asTextureProxy();
const GrTextureProxy* srcTex = src->asTextureProxy(); const GrTextureProxy* srcTex = src->asTextureProxy();
bool dstIsTex2D = dstTex ? (dstTex->textureType() == GrTextureType::k2D) : false; GrTextureType dstTexType;
bool srcIsTex2D = srcTex ? (srcTex->textureType() == GrTextureType::k2D) : false; GrTextureType* dstTexTypePtr = nullptr;
GrTextureType srcTexType;
// One of the possible requirements for copy as blit is that the srcRect must match the bounds GrTextureType* srcTexTypePtr = nullptr;
// of the src surface. If we have a approx fit surface we can't know for sure what the src if (dstTex) {
// bounds will be at this time. Thus we assert that if we say we can copy as blit and the src is dstTexType = dstTex->textureType();
// approx that we also can copy as draw. Therefore when it comes time to do the copy we will dstTexTypePtr = &dstTexType;
// know we will at least be able to do it as a draw. }
#ifdef SK_DEBUG if (srcTex) {
if (this->canCopyAsBlit(dstConfig, dstSampleCnt, SkToBool(dstTex), srcTexType = srcTex->textureType();
dstIsTex2D, dstOrigin, srcConfig, srcSampleCnt, SkToBool(srcTex), srcTexTypePtr = &srcTexType;
srcIsTex2D, srcOrigin, src->getBoundsRect(), srcRect, dstPoint) &&
!src->priv().isExact()) {
SkASSERT(this->canCopyAsDraw(dstConfig, SkToBool(srcTex)));
} }
#endif
return this->canCopyTexSubImage(dstConfig, has_msaa_render_buffer(dst, *this), return this->canCopyTexSubImage(dstConfig, has_msaa_render_buffer(dst, *this), dstTexTypePtr,
SkToBool(dstTex), dstIsTex2D, dstOrigin, srcConfig, has_msaa_render_buffer(src, *this), srcTexTypePtr) ||
srcConfig, has_msaa_render_buffer(src, *this), this->canCopyAsBlit(dstConfig, dstSampleCnt, dstTexTypePtr, srcConfig, srcSampleCnt,
SkToBool(srcTex), srcIsTex2D, srcOrigin) || srcTexTypePtr, src->getBoundsRect(), src->priv().isExact(),
this->canCopyAsBlit(dstConfig, dstSampleCnt, SkToBool(dstTex), srcRect, dstPoint) ||
dstIsTex2D, dstOrigin, srcConfig, srcSampleCnt, SkToBool(srcTex),
srcIsTex2D, srcOrigin, src->getBoundsRect(), srcRect,
dstPoint) ||
this->canCopyAsDraw(dstConfig, SkToBool(srcTex)); this->canCopyAsDraw(dstConfig, SkToBool(srcTex));
} }
bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
GrSurfaceOrigin* origin, bool* rectsMustMatch, bool* rectsMustMatch, bool* disallowSubrect) const {
bool* disallowSubrect) const {
// By default, we don't require rects to match. // By default, we don't require rects to match.
*rectsMustMatch = false; *rectsMustMatch = false;
@ -2552,7 +2526,6 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
// If the src is a texture, we can implement the blit as a draw assuming the config is // If the src is a texture, we can implement the blit as a draw assuming the config is
// renderable. // renderable.
if (src->asTextureProxy() && !this->isConfigRenderable(src->config())) { if (src->asTextureProxy() && !this->isConfigRenderable(src->config())) {
*origin = kBottomLeft_GrSurfaceOrigin;
desc->fFlags = kRenderTarget_GrSurfaceFlag; desc->fFlags = kRenderTarget_GrSurfaceFlag;
desc->fConfig = src->config(); desc->fConfig = src->config();
return true; return true;
@ -2573,7 +2546,6 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
// possible and we return false to fallback to creating a render target dst for render-to- // 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 // 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. // creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
GrSurfaceOrigin originForBlitFramebuffer = kTopLeft_GrSurfaceOrigin;
bool rectsMustMatchForBlitFramebuffer = false; bool rectsMustMatchForBlitFramebuffer = false;
bool disallowSubrectForBlitFramebuffer = false; bool disallowSubrectForBlitFramebuffer = false;
if (src->numColorSamples() > 1 && if (src->numColorSamples() > 1 &&
@ -2581,14 +2553,9 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
rectsMustMatchForBlitFramebuffer = true; rectsMustMatchForBlitFramebuffer = true;
disallowSubrectForBlitFramebuffer = true; disallowSubrectForBlitFramebuffer = true;
// Mirroring causes rects to mismatch later, don't allow it. // Mirroring causes rects to mismatch later, don't allow it.
originForBlitFramebuffer = src->origin();
} else if (src->numColorSamples() > 1 && (this->blitFramebufferSupportFlags() & } else if (src->numColorSamples() > 1 && (this->blitFramebufferSupportFlags() &
kRectsMustMatchForMSAASrc_BlitFramebufferFlag)) { kRectsMustMatchForMSAASrc_BlitFramebufferFlag)) {
rectsMustMatchForBlitFramebuffer = true; rectsMustMatchForBlitFramebuffer = true;
// Mirroring causes rects to mismatch later, don't allow it.
originForBlitFramebuffer = src->origin();
} else if (this->blitFramebufferSupportFlags() & kNoScalingOrMirroring_BlitFramebufferFlag) {
originForBlitFramebuffer = src->origin();
} }
// Check for format issues with glCopyTexSubImage2D // Check for format issues with glCopyTexSubImage2D
@ -2596,7 +2563,6 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
// glCopyTexSubImage2D doesn't work with this config. If the bgra can be used with fbo blit // glCopyTexSubImage2D doesn't work with this config. If the bgra can be used with fbo blit
// then we set up for that, otherwise fail. // then we set up for that, otherwise fail.
if (this->canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) { if (this->canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) {
*origin = originForBlitFramebuffer;
desc->fConfig = kBGRA_8888_GrPixelConfig; desc->fConfig = kBGRA_8888_GrPixelConfig;
*rectsMustMatch = rectsMustMatchForBlitFramebuffer; *rectsMustMatch = rectsMustMatchForBlitFramebuffer;
*disallowSubrect = disallowSubrectForBlitFramebuffer; *disallowSubrect = disallowSubrectForBlitFramebuffer;
@ -2612,7 +2578,6 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
// It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO // It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO
// blit or fail. // blit or fail.
if (this->canConfigBeFBOColorAttachment(src->config())) { if (this->canConfigBeFBOColorAttachment(src->config())) {
*origin = originForBlitFramebuffer;
desc->fConfig = src->config(); desc->fConfig = src->config();
*rectsMustMatch = rectsMustMatchForBlitFramebuffer; *rectsMustMatch = rectsMustMatchForBlitFramebuffer;
*disallowSubrect = disallowSubrectForBlitFramebuffer; *disallowSubrect = disallowSubrectForBlitFramebuffer;
@ -2623,7 +2588,6 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
} }
// We'll do a CopyTexSubImage. Make the dst a plain old texture. // We'll do a CopyTexSubImage. Make the dst a plain old texture.
*origin = src->origin();
desc->fConfig = src->config(); desc->fConfig = src->config();
desc->fFlags = kNone_GrSurfaceFlags; desc->fFlags = kNone_GrSurfaceFlags;
return true; return true;

View File

@ -388,21 +388,18 @@ public:
} }
bool canCopyTexSubImage(GrPixelConfig dstConfig, bool dstHasMSAARenderBuffer, bool canCopyTexSubImage(GrPixelConfig dstConfig, bool dstHasMSAARenderBuffer,
bool dstIsTextureable, bool dstIsGLTexture2D, const GrTextureType* dstTypeIfTexture,
GrSurfaceOrigin dstOrigin,
GrPixelConfig srcConfig, bool srcHasMSAARenderBuffer, GrPixelConfig srcConfig, bool srcHasMSAARenderBuffer,
bool srcIsTextureable, bool srcIsGLTexture2D, const GrTextureType* srcTypeIfTexture) const;
GrSurfaceOrigin srcOrigin) const;
bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt,
bool dstIsTextureable, bool dstIsGLTexture2D, const GrTextureType* dstTypeIfTexture,
GrSurfaceOrigin dstOrigin,
GrPixelConfig srcConfig, int srcSampleCnt, GrPixelConfig srcConfig, int srcSampleCnt,
bool srcIsTextureable, bool srcIsGLTexture2D, const GrTextureType* srcTypeIfTexture,
GrSurfaceOrigin srcOrigin, const SkRect& srcBounds, const SkRect& srcBounds, bool srcBoundsExact,
const SkIRect& srcRect, const SkIPoint& dstPoint) const; const SkIRect& srcRect, const SkIPoint& dstPoint) const;
bool canCopyAsDraw(GrPixelConfig dstConfig, bool srcIsTextureable) const; bool canCopyAsDraw(GrPixelConfig dstConfig, bool srcIsTextureable) const;
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, GrSurfaceOrigin*, bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override; bool* rectsMustMatch, bool* disallowSubrect) const override;
bool programBinarySupport() const { return fProgramBinarySupport; } bool programBinarySupport() const { return fProgramBinarySupport; }

View File

@ -3230,12 +3230,11 @@ void GrGLGpu::bindTextureToScratchUnit(GrGLenum target, GrGLint textureID) {
} }
// Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface. // Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface.
static inline bool can_blit_framebuffer_for_copy_surface( static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst,
const GrSurface* dst, GrSurfaceOrigin dstOrigin, const GrSurface* src,
const GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
const SkIRect& srcRect, const SkIPoint& dstPoint,
const SkIPoint& dstPoint, const GrGLCaps& caps) {
const GrGLCaps& caps) {
int dstSampleCnt = 0; int dstSampleCnt = 0;
int srcSampleCnt = 0; int srcSampleCnt = 0;
if (const GrRenderTarget* rt = dst->asRenderTarget()) { if (const GrRenderTarget* rt = dst->asRenderTarget()) {
@ -3250,12 +3249,22 @@ static inline bool can_blit_framebuffer_for_copy_surface(
const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture()); const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture()); const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
bool dstIsGLTexture2D = dstTex ? GR_GL_TEXTURE_2D == dstTex->target() : false; GrTextureType dstTexType;
bool srcIsGLTexture2D = srcTex ? GR_GL_TEXTURE_2D == srcTex->target() : false; GrTextureType* dstTexTypePtr = nullptr;
GrTextureType srcTexType;
GrTextureType* srcTexTypePtr = nullptr;
if (dstTex) {
dstTexType = dstTex->texturePriv().textureType();
dstTexTypePtr = &dstTexType;
}
if (srcTex) {
srcTexType = srcTex->texturePriv().textureType();
srcTexTypePtr = &srcTexType;
}
return caps.canCopyAsBlit(dst->config(), dstSampleCnt, SkToBool(dstTex), dstIsGLTexture2D, return caps.canCopyAsBlit(dst->config(), dstSampleCnt, dstTexTypePtr,
dstOrigin, src->config(), srcSampleCnt, SkToBool(srcTex), src->config(), srcSampleCnt, srcTexTypePtr,
srcIsGLTexture2D, srcOrigin, src->getBoundsRect(), srcRect, dstPoint); src->getBoundsRect(), true, srcRect, dstPoint);
} }
static bool rt_has_msaa_render_buffer(const GrGLRenderTarget* rt, const GrGLCaps& glCaps) { static bool rt_has_msaa_render_buffer(const GrGLRenderTarget* rt, const GrGLCaps& glCaps) {
@ -3266,8 +3275,7 @@ static bool rt_has_msaa_render_buffer(const GrGLRenderTarget* rt, const GrGLCaps
return rt->numColorSamples() > 1 && glCaps.usesMSAARenderBuffers() && rt->renderFBOID() != 0; return rt->numColorSamples() > 1 && glCaps.usesMSAARenderBuffers() && rt->renderFBOID() != 0;
} }
static inline bool can_copy_texsubimage(const GrSurface* dst, GrSurfaceOrigin dstOrigin, static inline bool can_copy_texsubimage(const GrSurface* dst, const GrSurface* src,
const GrSurface* src, GrSurfaceOrigin srcOrigin,
const GrGLCaps& caps) { const GrGLCaps& caps) {
const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget()); const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget());
@ -3278,13 +3286,21 @@ static inline bool can_copy_texsubimage(const GrSurface* dst, GrSurfaceOrigin ds
bool dstHasMSAARenderBuffer = dstRT ? rt_has_msaa_render_buffer(dstRT, caps) : false; bool dstHasMSAARenderBuffer = dstRT ? rt_has_msaa_render_buffer(dstRT, caps) : false;
bool srcHasMSAARenderBuffer = srcRT ? rt_has_msaa_render_buffer(srcRT, caps) : false; bool srcHasMSAARenderBuffer = srcRT ? rt_has_msaa_render_buffer(srcRT, caps) : false;
bool dstIsGLTexture2D = dstTex ? GR_GL_TEXTURE_2D == dstTex->target() : false; GrTextureType dstTexType;
bool srcIsGLTexture2D = srcTex ? GR_GL_TEXTURE_2D == srcTex->target() : false; GrTextureType* dstTexTypePtr = nullptr;
GrTextureType srcTexType;
GrTextureType* srcTexTypePtr = nullptr;
if (dstTex) {
dstTexType = dstTex->texturePriv().textureType();
dstTexTypePtr = &dstTexType;
}
if (srcTex) {
srcTexType = srcTex->texturePriv().textureType();
srcTexTypePtr = &srcTexType;
}
return caps.canCopyTexSubImage(dst->config(), dstHasMSAARenderBuffer, SkToBool(dstTex), return caps.canCopyTexSubImage(dst->config(), dstHasMSAARenderBuffer, dstTexTypePtr,
dstIsGLTexture2D, dstOrigin, src->config(), src->config(), srcHasMSAARenderBuffer, srcTexTypePtr);
srcHasMSAARenderBuffer, SkToBool(srcTex), srcIsGLTexture2D,
srcOrigin);
} }
// If a temporary FBO was created, its non-zero ID is returned. // If a temporary FBO was created, its non-zero ID is returned.
@ -3375,38 +3391,34 @@ void GrGLGpu::deleteFramebuffer(GrGLuint fboid) {
} }
} }
bool GrGLGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrGLGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
const SkIRect& srcRect, const SkIPoint& dstPoint, // None of our copy methods can handle a swizzle.
bool canDiscardOutsideDstRect) {
// None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the
// swizzle.
if (this->caps()->shaderCaps()->configOutputSwizzle(src->config()) != if (this->caps()->shaderCaps()->configOutputSwizzle(src->config()) !=
this->caps()->shaderCaps()->configOutputSwizzle(dst->config())) { this->caps()->shaderCaps()->configOutputSwizzle(dst->config())) {
return false; return false;
} }
// Don't prefer copying as a draw if the dst doesn't already have a FBO object. // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
// This implicitly handles this->glCaps().useDrawInsteadOfAllRenderTargetWrites(). // This implicitly handles this->glCaps().useDrawInsteadOfAllRenderTargetWrites().
bool preferCopy = SkToBool(dst->asRenderTarget()); bool preferCopy = SkToBool(dst->asRenderTarget());
if (preferCopy && this->glCaps().canCopyAsDraw(dst->config(), SkToBool(src->asTexture()))) { if (preferCopy && this->glCaps().canCopyAsDraw(dst->config(), SkToBool(src->asTexture()))) {
if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) { if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
return true; return true;
} }
} }
if (can_copy_texsubimage(dst, dstOrigin, src, srcOrigin, this->glCaps())) { if (can_copy_texsubimage(dst, src, this->glCaps())) {
this->copySurfaceAsCopyTexSubImage(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint); this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint);
return true; return true;
} }
if (can_blit_framebuffer_for_copy_surface(dst, dstOrigin, src, srcOrigin, if (can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this->glCaps())) {
srcRect, dstPoint, this->glCaps())) { return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint);
return this->copySurfaceAsBlitFramebuffer(dst, dstOrigin, src, srcOrigin,
srcRect, dstPoint);
} }
if (!preferCopy && this->glCaps().canCopyAsDraw(dst->config(), SkToBool(src->asTexture()))) { if (!preferCopy && this->glCaps().canCopyAsDraw(dst->config(), SkToBool(src->asTexture()))) {
if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) { if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
return true; return true;
} }
} }
@ -3682,44 +3694,32 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
return true; return true;
} }
bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture()); GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
int progIdx = TextureToCopyProgramIdx(srcTex); int progIdx = TextureToCopyProgramIdx(srcTex);
if (!this->glCaps().canConfigBeFBOColorAttachment(dst->config())) { if (!this->glCaps().canConfigBeFBOColorAttachment(dst->config())) {
return false; return false;
} }
if (!fCopyPrograms[progIdx].fProgram) { if (!fCopyPrograms[progIdx].fProgram) {
if (!this->createCopyProgram(srcTex)) { if (!this->createCopyProgram(srcTex)) {
SkDebugf("Failed to create copy program.\n"); SkDebugf("Failed to create copy program.\n");
return false; return false;
} }
} }
int w = srcRect.width(); int w = srcRect.width();
int h = srcRect.height(); int h = srcRect.height();
this->bindTexture(0, GrSamplerState::ClampNearest(), srcTex); this->bindTexture(0, GrSamplerState::ClampNearest(), srcTex);
this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, kDst_TempFBOTarget); this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, kDst_TempFBOTarget);
this->flushViewport(dst->width(), dst->height()); this->flushViewport(dst->width(), dst->height());
fHWBoundRenderTargetUniqueID.makeInvalid(); fHWBoundRenderTargetUniqueID.makeInvalid();
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h); SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
this->flushProgram(fCopyPrograms[progIdx].fProgram); this->flushProgram(fCopyPrograms[progIdx].fProgram);
fHWVertexArrayState.setVertexArrayID(this, 0); fHWVertexArrayState.setVertexArrayID(this, 0);
GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this); GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
attribs->enableVertexArrays(this, 1); attribs->enableVertexArrays(this, 1);
attribs->set(this, 0, fCopyProgramArrayBuffer.get(), kFloat2_GrVertexAttribType, attribs->set(this, 0, fCopyProgramArrayBuffer.get(), kFloat2_GrVertexAttribType,
kFloat2_GrSLType, 2 * sizeof(GrGLfloat), 0); kFloat2_GrSLType, 2 * sizeof(GrGLfloat), 0);
// dst rect edges in NDC (-1 to 1) // dst rect edges in NDC (-1 to 1)
int dw = dst->width(); int dw = dst->width();
int dh = dst->height(); int dh = dst->height();
@ -3727,21 +3727,12 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrGLfloat dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f; GrGLfloat dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
GrGLfloat dy0 = 2.f * dstPoint.fY / dh - 1.f; GrGLfloat dy0 = 2.f * dstPoint.fY / dh - 1.f;
GrGLfloat dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f; GrGLfloat dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
dy0 = -dy0;
dy1 = -dy1;
}
GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft; GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft;
GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w); GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w);
GrGLfloat sy0 = (GrGLfloat)srcRect.fTop; GrGLfloat sy0 = (GrGLfloat)srcRect.fTop;
GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h); GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h);
int sw = src->width(); int sw = src->width();
int sh = src->height(); int sh = src->height();
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
sy0 = sh - sy0;
sy1 = sh - sy1;
}
if (srcTex->texturePriv().textureType() != GrTextureType::kRectangle) { if (srcTex->texturePriv().textureType() != GrTextureType::kRectangle) {
// src rect edges in normalized texture space (0 to 1) // src rect edges in normalized texture space (0 to 1)
sx0 /= sw; sx0 /= sw;
@ -3749,12 +3740,10 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
sy0 /= sh; sy0 /= sh;
sy1 /= sh; sy1 /= sh;
} }
GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0)); GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform, GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform,
sx1 - sx0, sy1 - sy0, sx0, sy0)); sx1 - sx0, sy1 - sy0, sx0, sy0));
GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0)); GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0));
GrXferProcessor::BlendInfo blendInfo; GrXferProcessor::BlendInfo blendInfo;
blendInfo.reset(); blendInfo.reset();
this->flushBlend(blendInfo, GrSwizzle::RGBA()); this->flushBlend(blendInfo, GrSwizzle::RGBA());
@ -3766,50 +3755,37 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
if (this->glCaps().srgbWriteControl()) { if (this->glCaps().srgbWriteControl()) {
this->flushFramebufferSRGB(true); this->flushFramebufferSRGB(true);
} }
GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4)); GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, dst); this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, dst);
this->didWriteToSurface(dst, dstOrigin, &dstRect); // The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
return true; return true;
} }
void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurfaceOrigin dstOrigin, void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
SkASSERT(can_copy_texsubimage(dst, dstOrigin, src, srcOrigin, this->glCaps())); SkASSERT(can_copy_texsubimage(dst, src, this->glCaps()));
this->bindSurfaceFBOForPixelOps(src, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget); this->bindSurfaceFBOForPixelOps(src, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture()); GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture());
SkASSERT(dstTex); SkASSERT(dstTex);
// We modified the bound FBO // We modified the bound FBO
fHWBoundRenderTargetUniqueID.makeInvalid(); fHWBoundRenderTargetUniqueID.makeInvalid();
GrGLIRect srcGLRect;
srcGLRect.setRelativeTo(src->height(), srcRect, srcOrigin);
this->bindTextureToScratchUnit(dstTex->target(), dstTex->textureID()); this->bindTextureToScratchUnit(dstTex->target(), dstTex->textureID());
GrGLint dstY;
if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
} else {
dstY = dstPoint.fY;
}
GL_CALL(CopyTexSubImage2D(dstTex->target(), 0, GL_CALL(CopyTexSubImage2D(dstTex->target(), 0,
dstPoint.fX, dstY, dstPoint.fX, dstPoint.fY,
srcGLRect.fLeft, srcGLRect.fBottom, srcRect.fLeft, srcRect.fTop,
srcGLRect.fWidth, srcGLRect.fHeight)); srcRect.width(), srcRect.height()));
this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, src); this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, src);
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
srcRect.width(), srcRect.height()); srcRect.width(), srcRect.height());
this->didWriteToSurface(dst, dstOrigin, &dstRect); // The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
} }
bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
SkASSERT(can_blit_framebuffer_for_copy_surface(dst, dstOrigin, src, srcOrigin, SkASSERT(can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this->glCaps()));
srcRect, dstPoint, this->glCaps()));
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
srcRect.width(), srcRect.height()); srcRect.width(), srcRect.height());
if (dst == src) { if (dst == src) {
@ -3822,37 +3798,25 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOr
this->bindSurfaceFBOForPixelOps(src, GR_GL_READ_FRAMEBUFFER, kSrc_TempFBOTarget); this->bindSurfaceFBOForPixelOps(src, GR_GL_READ_FRAMEBUFFER, kSrc_TempFBOTarget);
// We modified the bound FBO // We modified the bound FBO
fHWBoundRenderTargetUniqueID.makeInvalid(); fHWBoundRenderTargetUniqueID.makeInvalid();
GrGLIRect srcGLRect;
GrGLIRect dstGLRect;
srcGLRect.setRelativeTo(src->height(), srcRect, srcOrigin);
dstGLRect.setRelativeTo(dst->height(), dstRect, dstOrigin);
// BlitFrameBuffer respects the scissor, so disable it. // BlitFrameBuffer respects the scissor, so disable it.
this->disableScissor(); this->disableScissor();
this->disableWindowRectangles(); this->disableWindowRectangles();
GrGLint srcY0; GL_CALL(BlitFramebuffer(srcRect.fLeft,
GrGLint srcY1; srcRect.fTop,
// Does the blit need to y-mirror or not? srcRect.fRight,
if (srcOrigin == dstOrigin) { srcRect.fBottom,
srcY0 = srcGLRect.fBottom; dstRect.fLeft,
srcY1 = srcGLRect.fBottom + srcGLRect.fHeight; dstRect.fTop,
} else { dstRect.fRight,
srcY0 = srcGLRect.fBottom + srcGLRect.fHeight; dstRect.fBottom,
srcY1 = srcGLRect.fBottom;
}
GL_CALL(BlitFramebuffer(srcGLRect.fLeft,
srcY0,
srcGLRect.fLeft + srcGLRect.fWidth,
srcY1,
dstGLRect.fLeft,
dstGLRect.fBottom,
dstGLRect.fLeft + dstGLRect.fWidth,
dstGLRect.fBottom + dstGLRect.fHeight,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
this->unbindTextureFBOForPixelOps(GR_GL_DRAW_FRAMEBUFFER, dst); this->unbindTextureFBOForPixelOps(GR_GL_DRAW_FRAMEBUFFER, dst);
this->unbindTextureFBOForPixelOps(GR_GL_READ_FRAMEBUFFER, src); this->unbindTextureFBOForPixelOps(GR_GL_READ_FRAMEBUFFER, src);
this->didWriteToSurface(dst, dstOrigin, &dstRect);
// The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
return true; return true;
} }

View File

@ -255,10 +255,8 @@ private:
bool onRegenerateMipMapLevels(GrTexture*) override; bool onRegenerateMipMapLevels(GrTexture*) override;
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override;
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) override;
// binds texture unit in GL // binds texture unit in GL
void setTextureUnit(int unitIdx); void setTextureUnit(int unitIdx);
@ -301,15 +299,12 @@ private:
bool waitSync(GrGLsync, uint64_t timeout, bool flush); bool waitSync(GrGLsync, uint64_t timeout, bool flush);
bool copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool copySurfaceAsDraw(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint);
const SkIRect& srcRect, const SkIPoint& dstPoint); void copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
void copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurfaceOrigin dstOrigin, const SkIPoint& dstPoint);
GrSurface* src, GrSurfaceOrigin srcOrigin, bool copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIRect& srcRect, const SkIPoint& dstPoint); const SkIPoint& dstPoint);
bool copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint);
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);

View File

@ -21,9 +21,8 @@ class GrGLGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer {
public: public:
GrGLGpuTextureCommandBuffer(GrGLGpu* gpu) : fGpu(gpu) {} GrGLGpuTextureCommandBuffer(GrGLGpu* gpu) : fGpu(gpu) {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
const SkIPoint& dstPoint) override { fGpu->copySurface(fTexture, src, srcRect, dstPoint);
fGpu->copySurface(fTexture, fOrigin, src, srcOrigin, srcRect, dstPoint);
} }
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
@ -68,9 +67,8 @@ public:
state->doUpload(upload); state->doUpload(upload);
} }
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
const SkIPoint& dstPoint) override { fGpu->copySurface(fRenderTarget, src,srcRect, dstPoint);
fGpu->copySurface(fRenderTarget, fOrigin, src, srcOrigin, srcRect, dstPoint);
} }
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,

View File

@ -70,7 +70,7 @@ public:
bool surfaceSupportsReadPixels(const GrSurface*) const override { return true; } bool surfaceSupportsReadPixels(const GrSurface*) const override { return true; }
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, GrSurfaceOrigin*, bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override { bool* rectsMustMatch, bool* disallowSubrect) const override {
return false; return false;
} }

View File

@ -101,8 +101,7 @@ private:
GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override { GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override {
return true; return true;
} }
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src, bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override { const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override {
return true; return true;
} }

View File

@ -19,8 +19,7 @@ public:
~GrMockGpuTextureCommandBuffer() override {} ~GrMockGpuTextureCommandBuffer() override {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
const SkIPoint& dstPoint) override {}
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override {} GrGpuBuffer* transferBuffer, size_t offset) override {}
void insertEventMarker(const char*) override {} void insertEventMarker(const char*) override {}
@ -42,8 +41,7 @@ public:
void insertEventMarker(const char*) override {} void insertEventMarker(const char*) override {}
void begin() override {} void begin() override {}
void end() override {} void end() override {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
const SkIPoint& dstPoint) override {}
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override {} GrGpuBuffer* transferBuffer, size_t offset) override {}

View File

@ -46,18 +46,11 @@ public:
return fPreferredStencilFormat; return fPreferredStencilFormat;
} }
bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount, GrSurfaceOrigin dstOrigin, bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount, GrPixelConfig srcConfig,
GrPixelConfig srcConfig, int srcSampleCount, GrSurfaceOrigin srcOrigin, int srcSampleCount, const SkIRect& srcRect, const SkIPoint& dstPoint,
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool areDstSrcSameObj) const; bool areDstSrcSameObj) const;
bool canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable, bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
GrPixelConfig srcConfig, bool srcIsTextureable) const;
bool canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
bool srcIsTextureable) const;
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, GrSurfaceOrigin*,
bool* rectsMustMatch, bool* disallowSubrect) const override { bool* rectsMustMatch, bool* disallowSubrect) const override {
return false; return false;
} }

View File

@ -119,9 +119,7 @@ void GrMtlCaps::initFeatureSet(MTLFeatureSet featureSet) {
} }
bool GrMtlCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount, bool GrMtlCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount,
GrSurfaceOrigin dstOrigin,
GrPixelConfig srcConfig, int srcSampleCount, GrPixelConfig srcConfig, int srcSampleCount,
GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint, const SkIRect& srcRect, const SkIPoint& dstPoint,
bool areDstSrcSameObj) const { bool areDstSrcSameObj) const {
if (dstConfig != srcConfig) { if (dstConfig != srcConfig) {
@ -130,9 +128,6 @@ bool GrMtlCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount,
if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) { if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) {
return false; return false;
} }
if (dstOrigin != srcOrigin) {
return false;
}
if (areDstSrcSameObj) { if (areDstSrcSameObj) {
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(), SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
srcRect.width(), srcRect.height()); srcRect.width(), srcRect.height());
@ -143,38 +138,8 @@ bool GrMtlCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount,
return true; return true;
} }
bool GrMtlCaps::canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable,
GrPixelConfig srcConfig, bool srcIsTextureable) const {
// TODO: Make copySurfaceAsDraw handle the swizzle
if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
this->shaderCaps()->configOutputSwizzle(dstConfig)) {
return false;
}
if (!dstIsRenderable || !srcIsTextureable) {
return false;
}
return true;
}
bool GrMtlCaps::canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
bool srcIsTextureable) const {
// TODO: Make copySurfaceAsDraw handle the swizzle
if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
this->shaderCaps()->configOutputSwizzle(dstConfig)) {
return false;
}
if (!srcIsTextureable) {
return false;
}
return true;
}
bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src, bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
const SkIRect& srcRect, const SkIPoint& dstPoint) const { const SkIRect& srcRect, const SkIPoint& dstPoint) const {
GrSurfaceOrigin dstOrigin = dst->origin();
GrSurfaceOrigin srcOrigin = src->origin();
int dstSampleCnt = 0; int dstSampleCnt = 0;
int srcSampleCnt = 0; int srcSampleCnt = 0;
if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) { if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
@ -186,13 +151,8 @@ bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy
SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy())); SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy())); SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
return this->canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin, return this->canCopyAsBlit(dst->config(), dstSampleCnt, src->config(), srcSampleCnt, srcRect,
src->config(), srcSampleCnt, srcOrigin, dstPoint, dst == src);
srcRect, dstPoint, dst == src) ||
this->canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTargetProxy()),
src->config(), SkToBool(src->asTextureProxy())) ||
this->canCopyAsDrawThenBlit(dst->config(), src->config(),
SkToBool(src->asTextureProxy()));
} }
void GrMtlCaps::initGrCaps(const id<MTLDevice> device) { void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {

View File

@ -1,55 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrMtlCopyManager_DEFINED
#define GrMtlCopyManager_DEFINED
#include "include/gpu/GrTypes.h"
#import <metal/metal.h>
class GrMtlCopyPipelineState;
class GrMtlGpu;
class GrSurface;
struct SkIPoint;
struct SkIRect;
class GrMtlCopyManager {
public:
GrMtlCopyManager(GrMtlGpu* gpu) : fGpu(gpu) {}
bool copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect);
static bool IsCompatible(const GrMtlCopyPipelineState*, MTLPixelFormat dstPixelFormat);
void destroyResources();
private:
enum BufferIndex {
kUniform_BufferIndex,
kAttribute_BufferIndex,
};
void createCopyProgramBuffer();
void createCopyProgramShaders();
void createCopyProgramVertexDescriptor();
void createCopyProgram();
id<MTLSamplerState> fSamplerState;
id<MTLBuffer> fVertexAttributeBuffer;
id<MTLFunction> fVertexFunction;
id<MTLFunction> fFragmentFunction;
MTLVertexDescriptor* fVertexDescriptor;
GrMtlGpu* fGpu;
};
#endif

View File

@ -1,238 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/mtl/GrMtlCopyManager.h"
#include "include/gpu/GrSurface.h"
#include "src/gpu/mtl/GrMtlBuffer.h"
#include "src/gpu/mtl/GrMtlCommandBuffer.h"
#include "src/gpu/mtl/GrMtlCopyPipelineState.h"
#include "src/gpu/mtl/GrMtlGpu.h"
#include "src/gpu/mtl/GrMtlResourceProvider.h"
#include "src/gpu/mtl/GrMtlUtil.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "src/core/SkTraceEvent.h"
#import <simd/simd.h>
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
void GrMtlCopyManager::createCopyProgramBuffer() {
// Create per vertex attribute data for copy as draw
static const simd::float2 vdata[4] = {
{0, 0},
{0, 1},
{1, 0},
{1, 1},
};
sk_sp<GrMtlBuffer> mtlBuffer = GrMtlBuffer::Make(fGpu, sizeof(vdata), GrGpuBufferType::kVertex,
kStatic_GrAccessPattern, vdata);
fVertexAttributeBuffer = mtlBuffer->mtlBuffer();
}
void GrMtlCopyManager::createCopyProgramShaders() {
// Create shaders required by pipeline state
SkString vertShaderText;
vertShaderText.appendf(
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = %d"/*kUniform_BufferIndex*/", binding = 0) uniform vertexUniformBuffer {"
"float4 uPosXform;"
"float4 uTexCoordXform;"
"};"
"layout(location = 0) in float2 inPosition;"
"layout(location = 1) out float2 vTexCoord;"
"// Copy Program VS\n"
"void main() {"
"vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
"sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
"sk_Position.zw = float2(0, 1);"
"}",
kUniform_BufferIndex
);
SkString fragShaderText;
fragShaderText.append(
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = 1, binding = 0) uniform sampler2D uTexture;"
"layout(location = 1) in float2 vTexCoord;"
"// Copy Program FS\n"
"void main() {"
"sk_FragColor = texture(uTexture, vTexCoord);"
"}"
);
SkSL::Program::Settings settings;
SkSL::Program::Inputs inputs;
id<MTLLibrary> vertexLibrary = GrCompileMtlShaderLibrary(fGpu, vertShaderText.c_str(),
SkSL::Program::kVertex_Kind,
settings, &inputs);
SkASSERT(inputs.isEmpty());
SkASSERT(vertexLibrary);
id<MTLLibrary> fragmentLibrary = GrCompileMtlShaderLibrary(fGpu, fragShaderText.c_str(),
SkSL::Program::kFragment_Kind,
settings, &inputs);
SkASSERT(inputs.isEmpty());
SkASSERT(fragmentLibrary);
id<MTLFunction> vertexFunction = [vertexLibrary newFunctionWithName: @"vertexMain"];
id<MTLFunction> fragmentFunction = [fragmentLibrary newFunctionWithName: @"fragmentMain"];
SkASSERT(vertexFunction);
SkASSERT(fragmentFunction);
fVertexFunction = vertexFunction;
fFragmentFunction = fragmentFunction;
}
void GrMtlCopyManager::createCopyProgramVertexDescriptor() {
// Create vertex descriptor for pipeline state
// Expected [[stage_in]] (vertex attribute) MSL format for copies:
//
// struct Input {
// float2 inPosition [[attribute(0)]];
// };
MTLVertexDescriptor* vertexDescriptor = [[MTLVertexDescriptor alloc] init];
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2;
vertexDescriptor.attributes[0].offset = 0;
vertexDescriptor.attributes[0].bufferIndex = kAttribute_BufferIndex;
vertexDescriptor.layouts[kAttribute_BufferIndex].stepFunction = MTLVertexStepFunctionPerVertex;
vertexDescriptor.layouts[kAttribute_BufferIndex].stepRate = 1;
vertexDescriptor.layouts[kAttribute_BufferIndex].stride = sizeof(simd::float2);
fVertexDescriptor = vertexDescriptor;
}
void GrMtlCopyManager::createCopyProgram() {
TRACE_EVENT0("skia", TRACE_FUNC);
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
fSamplerState = [fGpu->device() newSamplerStateWithDescriptor: samplerDescriptor];
this->createCopyProgramBuffer();
this->createCopyProgramShaders();
this->createCopyProgramVertexDescriptor();
}
bool GrMtlCopyManager::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) {
SkASSERT(fGpu->mtlCaps().canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTarget()),
src->config(), SkToBool(src->asTexture())));
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst, false);
id<MTLTexture> srcTex = GrGetMTLTextureFromSurface(src, false);
SkASSERT(srcTex != dstTex);
if (fSamplerState == nil) {
SkASSERT(fVertexAttributeBuffer == nil);
SkASSERT(fVertexFunction == nil);
SkASSERT(fFragmentFunction == nil);
SkASSERT(fVertexDescriptor == nil);
this->createCopyProgram();
}
if (!(fSamplerState && fVertexAttributeBuffer && fVertexFunction &&
fFragmentFunction && fVertexDescriptor)) {
SkASSERT(false);
return false;
}
// UPDATE UNIFORM DESCRIPTOR SET
int w = srcRect.width();
int h = srcRect.height();
// dst rect edges in NDC (-1 to 1)
int dw = dstTex.width;
int dh = dstTex.height;
float dx0 = 2.f * dstPoint.fX / dw - 1.f;
float dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
float dy0 = 2.f * dstPoint.fY / dh - 1.f;
float dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
dy0 = -dy0;
dy1 = -dy1;
}
float sx0 = (float)srcRect.fLeft;
float sx1 = (float)(srcRect.fLeft + w);
float sy0 = (float)srcRect.fTop;
float sy1 = (float)(srcRect.fTop + h);
int sh = srcTex.height;
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
sy0 = sh - sy0;
sy1 = sh - sy1;
}
// src rect edges in normalized texture space (0 to 1).
int sw = srcTex.width;
sx0 /= sw;
sx1 /= sw;
sy0 /= sh;
sy1 /= sh;
const simd::float4 vertexUniformBuffer[2] = {
{dx1 - dx0, dy1 - dy0, dx0, dy0}, // posXform
{sx1 - sx0, sy1 - sy0, sx0, sy0}, // texCoordXform
};
MTLRenderPassDescriptor* renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDesc.colorAttachments[0].texture = dstTex;
renderPassDesc.colorAttachments[0].slice = 0;
renderPassDesc.colorAttachments[0].level = 0;
renderPassDesc.colorAttachments[0].loadAction = canDiscardOutsideDstRect ? MTLLoadActionDontCare
: MTLLoadActionLoad;
renderPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
id<MTLRenderCommandEncoder> renderCmdEncoder =
fGpu->commandBuffer()->getRenderCommandEncoder(renderPassDesc, nullptr);
GrMtlCopyPipelineState* copyPipelineState =
fGpu->resourceProvider().findOrCreateCopyPipelineState(dstTex.pixelFormat,
fVertexFunction,
fFragmentFunction,
fVertexDescriptor);
[renderCmdEncoder setRenderPipelineState: copyPipelineState->mtlCopyPipelineState()];
[renderCmdEncoder setVertexBuffer: fVertexAttributeBuffer
offset: 0
atIndex: kAttribute_BufferIndex];
[renderCmdEncoder setVertexBytes: vertexUniformBuffer
length: sizeof(vertexUniformBuffer)
atIndex: kUniform_BufferIndex];
[renderCmdEncoder setFragmentTexture: srcTex
atIndex: 0];
[renderCmdEncoder setFragmentSamplerState: fSamplerState
atIndex: 0];
[renderCmdEncoder drawPrimitives: MTLPrimitiveTypeTriangleStrip
vertexStart: 0
vertexCount: 4];
return true;
}
bool GrMtlCopyManager::IsCompatible(const GrMtlCopyPipelineState* pipelineState,
MTLPixelFormat dstPixelFormat) {
return pipelineState->fPixelFormat == dstPixelFormat;
}
void GrMtlCopyManager::destroyResources() {
fSamplerState = nil;
fVertexAttributeBuffer = nil;
fVertexFunction = nil;
fFragmentFunction = nil;
fVertexDescriptor = nil;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrMtlCopyPipelineState_DEFINED
#define GrMtlCopyPipelineState_DEFINED
#import <metal/metal.h>
class GrMtlGpu;
class GrMtlCopyPipelineState {
public:
static GrMtlCopyPipelineState* CreateCopyPipelineState(GrMtlGpu* gpu,
MTLPixelFormat dstPixelFormat,
id<MTLFunction> vertexFunction,
id<MTLFunction> fragmentFunction,
MTLVertexDescriptor* vertexDescriptor);
id<MTLRenderPipelineState> mtlCopyPipelineState() { return fPipelineState; }
private:
GrMtlCopyPipelineState(id<MTLRenderPipelineState> pipelineState,
MTLPixelFormat pixelFormat)
: fPipelineState(pipelineState)
, fPixelFormat(pixelFormat) {}
id<MTLRenderPipelineState> fPipelineState;
MTLPixelFormat fPixelFormat;
friend class GrMtlCopyManager;
};
#endif

View File

@ -1,41 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/mtl/GrMtlCopyPipelineState.h"
#include "src/gpu/mtl/GrMtlGpu.h"
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
GrMtlCopyPipelineState* GrMtlCopyPipelineState::CreateCopyPipelineState(
GrMtlGpu* gpu,
MTLPixelFormat dstPixelFormat,
id<MTLFunction> vertexFunction,
id<MTLFunction> fragmentFunction,
MTLVertexDescriptor* vertexDescriptor) {
// Create pipeline state for copy as draw
MTLRenderPipelineDescriptor* pipelineDescriptor = [MTLRenderPipelineDescriptor new];
pipelineDescriptor.vertexFunction = vertexFunction;
pipelineDescriptor.fragmentFunction = fragmentFunction;
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
pipelineDescriptor.colorAttachments[0].pixelFormat = dstPixelFormat;
NSError* error = nil;
id<MTLRenderPipelineState> pipelineState =
[gpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
error: &error];
if (error) {
SkDebugf("Error creating pipeline: %s\n",
[[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
return nil;
}
SkASSERT(pipelineState);
return new GrMtlCopyPipelineState(pipelineState, dstPixelFormat);
}

View File

@ -14,7 +14,6 @@
#include "src/gpu/GrSemaphore.h" #include "src/gpu/GrSemaphore.h"
#include "src/gpu/mtl/GrMtlCaps.h" #include "src/gpu/mtl/GrMtlCaps.h"
#include "src/gpu/mtl/GrMtlCopyManager.h"
#include "src/gpu/mtl/GrMtlResourceProvider.h" #include "src/gpu/mtl/GrMtlResourceProvider.h"
#include "src/gpu/mtl/GrMtlStencilAttachment.h" #include "src/gpu/mtl/GrMtlStencilAttachment.h"
@ -72,22 +71,11 @@ public:
void testingOnly_flushGpuAndSync() override; void testingOnly_flushGpuAndSync() override;
#endif #endif
bool copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool copySurfaceAsBlit(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint);
const SkIRect& srcRect, const SkIPoint& dstPoint);
// This function is needed when we want to copy between two surfaces with different origins and bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
// the destination surface is not a render target. We will first draw to a temporary render const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override;
// target to adjust for the different origins and then blit from there to the destination.
bool copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint);
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) override;
GrGpuRTCommandBuffer* getCommandBuffer( GrGpuRTCommandBuffer* getCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds, GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds,
@ -222,7 +210,6 @@ private:
std::unique_ptr<SkSL::Compiler> fCompiler; std::unique_ptr<SkSL::Compiler> fCompiler;
GrMtlCopyManager fCopyManager;
GrMtlResourceProvider fResourceProvider; GrMtlResourceProvider fResourceProvider;
bool fDisconnected; bool fDisconnected;

View File

@ -99,7 +99,6 @@ GrMtlGpu::GrMtlGpu(GrContext* context, const GrContextOptions& options,
, fQueue(queue) , fQueue(queue)
, fCmdBuffer(nullptr) , fCmdBuffer(nullptr)
, fCompiler(new SkSL::Compiler()) , fCompiler(new SkSL::Compiler())
, fCopyManager(this)
, fResourceProvider(this) , fResourceProvider(this)
, fDisconnected(false) { , fDisconnected(false) {
fMtlCaps.reset(new GrMtlCaps(options, fDevice, featureSet)); fMtlCaps.reset(new GrMtlCaps(options, fDevice, featureSet));
@ -121,8 +120,6 @@ void GrMtlGpu::disconnect(DisconnectType type) {
delete fCmdBuffer; delete fCmdBuffer;
fCmdBuffer = nullptr; fCmdBuffer = nullptr;
// We don't need to distinguish between abandon and destroy for these subsystems
fCopyManager.destroyResources();
fResourceProvider.destroyResources(); fResourceProvider.destroyResources();
fQueue = nil; fQueue = nil;
@ -135,8 +132,6 @@ void GrMtlGpu::disconnect(DisconnectType type) {
void GrMtlGpu::destroyResources() { void GrMtlGpu::destroyResources() {
// Will implicitly delete the command buffer // Will implicitly delete the command buffer
this->submitCommandBuffer(SyncQueue::kForce_SyncQueue); this->submitCommandBuffer(SyncQueue::kForce_SyncQueue);
fCopyManager.destroyResources();
fResourceProvider.destroyResources(); fResourceProvider.destroyResources();
fQueue = nil; fQueue = nil;
@ -871,126 +866,33 @@ static int get_surface_sample_cnt(GrSurface* surf) {
return 0; return 0;
} }
bool GrMtlGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrMtlGpu::copySurfaceAsBlit(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint) {
const SkIRect& srcRect, const SkIPoint& dstPoint) {
#ifdef SK_DEBUG #ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst); int dstSampleCnt = get_surface_sample_cnt(dst);
int srcSampleCnt = get_surface_sample_cnt(src); int srcSampleCnt = get_surface_sample_cnt(src);
SkASSERT(this->mtlCaps().canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin, SkASSERT(this->mtlCaps().canCopyAsBlit(dst->config(), dstSampleCnt, src->config(), srcSampleCnt,
src->config(), srcSampleCnt, srcOrigin,
srcRect, dstPoint, dst == src)); srcRect, dstPoint, dst == src));
#endif #endif
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst, false); id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst, false);
id<MTLTexture> srcTex = GrGetMTLTextureFromSurface(src, false); id<MTLTexture> srcTex = GrGetMTLTextureFromSurface(src, false);
// Flip rect if necessary
SkIRect srcMtlRect;
srcMtlRect.fLeft = srcRect.fLeft;
srcMtlRect.fRight = srcRect.fRight;
SkIRect dstRect;
dstRect.fLeft = dstPoint.fX;
dstRect.fRight = dstPoint.fX + srcRect.width();
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
srcMtlRect.fTop = srcTex.height - srcRect.fBottom;
srcMtlRect.fBottom = srcTex.height - srcRect.fTop;
} else {
srcMtlRect.fTop = srcRect.fTop;
srcMtlRect.fBottom = srcRect.fBottom;
}
if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
dstRect.fTop = dstTex.height - dstPoint.fY - srcMtlRect.height();
} else {
dstRect.fTop = dstPoint.fY;
}
dstRect.fBottom = dstRect.fTop + srcMtlRect.height();
id<MTLBlitCommandEncoder> blitCmdEncoder = this->commandBuffer()->getBlitCommandEncoder(); id<MTLBlitCommandEncoder> blitCmdEncoder = this->commandBuffer()->getBlitCommandEncoder();
[blitCmdEncoder copyFromTexture: srcTex [blitCmdEncoder copyFromTexture: srcTex
sourceSlice: 0 sourceSlice: 0
sourceLevel: 0 sourceLevel: 0
sourceOrigin: MTLOriginMake(srcMtlRect.x(), srcMtlRect.y(), 0) sourceOrigin: MTLOriginMake(srcRect.x(), srcRect.y(), 0)
sourceSize: MTLSizeMake(srcMtlRect.width(), srcMtlRect.height(), 1) sourceSize: MTLSizeMake(srcRect.width(), srcRect.height(), 1)
toTexture: dstTex toTexture: dstTex
destinationSlice: 0 destinationSlice: 0
destinationLevel: 0 destinationLevel: 0
destinationOrigin: MTLOriginMake(dstRect.x(), dstRect.y(), 0)]; destinationOrigin: MTLOriginMake(dstPoint.fX, dstPoint.fY, 0)];
return true; return true;
} }
bool GrMtlGpu::copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
const SkIRect& srcRect, const SkIPoint& dstPoint) {
#ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst);
int srcSampleCnt = get_surface_sample_cnt(src);
SkASSERT(dstSampleCnt == 0); // dst shouldn't be a render target
SkASSERT(!this->mtlCaps().canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin,
src->config(), srcSampleCnt, srcOrigin,
srcRect, dstPoint, dst == src));
SkASSERT(!this->mtlCaps().canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTarget()),
src->config(), SkToBool(src->asTexture())));
SkASSERT(this->mtlCaps().canCopyAsDrawThenBlit(dst->config(),src->config(),
SkToBool(src->asTexture())));
#endif
GrSurfaceDesc surfDesc;
surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
surfDesc.fWidth = srcRect.width();
surfDesc.fHeight = srcRect.height();
surfDesc.fConfig = dst->config();
surfDesc.fSampleCnt = 1;
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst, false);
MTLTextureDescriptor* textureDesc = GrGetMTLTextureDescriptor(dstTex);
textureDesc.width = srcRect.width();
textureDesc.height = srcRect.height();
textureDesc.mipmapLevelCount = 1;
textureDesc.usage |= MTLTextureUsageRenderTarget;
sk_sp<GrMtlTexture> transferTexture =
GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(this,
SkBudgeted::kYes,
surfDesc,
textureDesc,
GrMipMapsStatus::kNotAllocated);
GrSurfaceOrigin transferOrigin = dstOrigin;
SkASSERT(this->mtlCaps().canCopyAsDraw(transferTexture->config(),
SkToBool(transferTexture->asRenderTarget()),
src->config(),
SkToBool(src->asTexture())));
// TODO: Eventually we will need to handle resolves either in this function or make a separate
// copySurfaceAsResolveThenBlit().
if (!this->copySurface(transferTexture.get(), transferOrigin,
src, srcOrigin,
srcRect, SkIPoint::Make(0, 0))) {
return false;
}
SkIRect transferRect = SkIRect::MakeXYWH(0, 0, srcRect.width(), srcRect.height());
SkASSERT(this->mtlCaps().canCopyAsBlit(dst->config(),
get_surface_sample_cnt(dst),
dstOrigin,
transferTexture->config(),
get_surface_sample_cnt(transferTexture.get()),
transferOrigin,
transferRect, dstPoint, false));
if (!this->copySurface(dst, dstOrigin,
transferTexture.get(), transferOrigin,
transferRect, dstPoint)) {
return false;
}
return true;
}
bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) {
GrPixelConfig dstConfig = dst->config(); GrPixelConfig dstConfig = dst->config();
GrPixelConfig srcConfig = src->config(); GrPixelConfig srcConfig = src->config();
@ -1004,23 +906,15 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
} }
bool success = false; bool success = false;
if (this->mtlCaps().canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTarget()), if (this->mtlCaps().canCopyAsBlit(dstConfig, dstSampleCnt, srcConfig, srcSampleCnt, srcRect,
src->config(), SkToBool(src->asTexture()))) { dstPoint, dst == src)) {
success = fCopyManager.copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint, success = this->copySurfaceAsBlit(dst, src, srcRect, dstPoint);
canDiscardOutsideDstRect);
} else if (this->mtlCaps().canCopyAsBlit(dstConfig, dstSampleCnt, dstOrigin,
srcConfig, srcSampleCnt, srcOrigin,
srcRect, dstPoint, dst == src)) {
success = this->copySurfaceAsBlit(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
} else if (this->mtlCaps().canCopyAsDrawThenBlit(dst->config(), src->config(),
SkToBool(src->asTexture()))) {
success = this->copySurfaceAsDrawThenBlit(dst, dstOrigin, src, srcOrigin,
srcRect, dstPoint);
} }
if (success) { if (success) {
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(), SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
srcRect.width(), srcRect.height()); srcRect.width(), srcRect.height());
this->didWriteToSurface(dst, dstOrigin, &dstRect); // The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
} }
return success; return success;
} }

View File

@ -29,9 +29,8 @@ public:
~GrMtlGpuTextureCommandBuffer() override {} ~GrMtlGpuTextureCommandBuffer() override {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
const SkIPoint& dstPoint) override { fGpu->copySurface(fTexture, src, srcRect, dstPoint);
fGpu->copySurface(fTexture, fOrigin, src, srcOrigin, srcRect, dstPoint);
} }
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override { GrGpuBuffer* transferBuffer, size_t offset) override {
@ -68,8 +67,7 @@ public:
} }
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override; GrGpuBuffer* transferBuffer, size_t offset) override;
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
const SkIPoint& dstPoint) override;
void submit(); void submit();

View File

@ -92,12 +92,12 @@ void GrMtlGpuRTCommandBuffer::submit() {
fGpu->submitIndirectCommandBuffer(fRenderTarget, fOrigin, &iBounds); fGpu->submitIndirectCommandBuffer(fRenderTarget, fOrigin, &iBounds);
} }
void GrMtlGpuRTCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin, void GrMtlGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
const SkIRect& srcRect, const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
// We cannot have an active encoder when we call copy since it requires its own // We cannot have an active encoder when we call copy since it requires its own
// command encoder. // command encoder.
SkASSERT(nil == fActiveRenderCmdEncoder); SkASSERT(nil == fActiveRenderCmdEncoder);
fGpu->copySurface(fRenderTarget, fOrigin, src, srcOrigin, srcRect, dstPoint); fGpu->copySurface(fRenderTarget, src, srcRect, dstPoint);
} }
void GrMtlGpuRTCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void GrMtlGpuRTCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,

View File

@ -10,7 +10,6 @@
#include "include/private/SkTArray.h" #include "include/private/SkTArray.h"
#include "src/core/SkLRUCache.h" #include "src/core/SkLRUCache.h"
#include "src/gpu/mtl/GrMtlCopyPipelineState.h"
#include "src/gpu/mtl/GrMtlDepthStencil.h" #include "src/gpu/mtl/GrMtlDepthStencil.h"
#include "src/gpu/mtl/GrMtlPipelineStateBuilder.h" #include "src/gpu/mtl/GrMtlPipelineStateBuilder.h"
#include "src/gpu/mtl/GrMtlSampler.h" #include "src/gpu/mtl/GrMtlSampler.h"
@ -23,11 +22,6 @@ class GrMtlResourceProvider {
public: public:
GrMtlResourceProvider(GrMtlGpu* gpu); GrMtlResourceProvider(GrMtlGpu* gpu);
GrMtlCopyPipelineState* findOrCreateCopyPipelineState(MTLPixelFormat dstPixelFormat,
id<MTLFunction> vertexFunction,
id<MTLFunction> fragmentFunction,
MTLVertexDescriptor* vertexDescriptor);
GrMtlPipelineState* findOrCreateCompatiblePipelineState( GrMtlPipelineState* findOrCreateCompatiblePipelineState(
GrRenderTarget*, GrSurfaceOrigin, GrRenderTarget*, GrSurfaceOrigin,
const GrPipeline&, const GrPipeline&,
@ -89,8 +83,6 @@ private:
#endif #endif
}; };
SkTArray<std::unique_ptr<GrMtlCopyPipelineState>> fCopyPipelineStateCache;
GrMtlGpu* fGpu; GrMtlGpu* fGpu;
// Cache of GrMtlPipelineStates // Cache of GrMtlPipelineStates

View File

@ -8,7 +8,6 @@
#include "src/gpu/mtl/GrMtlResourceProvider.h" #include "src/gpu/mtl/GrMtlResourceProvider.h"
#include "src/gpu/mtl/GrMtlCommandBuffer.h" #include "src/gpu/mtl/GrMtlCommandBuffer.h"
#include "src/gpu/mtl/GrMtlCopyManager.h"
#include "src/gpu/mtl/GrMtlGpu.h" #include "src/gpu/mtl/GrMtlGpu.h"
#include "src/gpu/mtl/GrMtlPipelineState.h" #include "src/gpu/mtl/GrMtlPipelineState.h"
#include "src/gpu/mtl/GrMtlUtil.h" #include "src/gpu/mtl/GrMtlUtil.h"
@ -25,23 +24,6 @@ GrMtlResourceProvider::GrMtlResourceProvider(GrMtlGpu* gpu)
fPipelineStateCache.reset(new PipelineStateCache(gpu)); fPipelineStateCache.reset(new PipelineStateCache(gpu));
} }
GrMtlCopyPipelineState* GrMtlResourceProvider::findOrCreateCopyPipelineState(
MTLPixelFormat dstPixelFormat,
id<MTLFunction> vertexFunction,
id<MTLFunction> fragmentFunction,
MTLVertexDescriptor* vertexDescriptor) {
for (const auto& copyPipelineState: fCopyPipelineStateCache) {
if (GrMtlCopyManager::IsCompatible(copyPipelineState.get(), dstPixelFormat)) {
return copyPipelineState.get();
}
}
fCopyPipelineStateCache.emplace_back(GrMtlCopyPipelineState::CreateCopyPipelineState(
fGpu, dstPixelFormat, vertexFunction, fragmentFunction, vertexDescriptor));
return fCopyPipelineStateCache.back().get();
}
GrMtlPipelineState* GrMtlResourceProvider::findOrCreateCompatiblePipelineState( GrMtlPipelineState* GrMtlResourceProvider::findOrCreateCompatiblePipelineState(
GrRenderTarget* renderTarget, GrSurfaceOrigin origin, GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
const GrPipeline& pipeline, const GrPrimitiveProcessor& proc, const GrPipeline& pipeline, const GrPrimitiveProcessor& proc,

View File

@ -11,57 +11,7 @@
#include "src/gpu/GrGpu.h" #include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h" #include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/geometry/GrRect.h"
// returns true if the read/written rect intersects the src/dst and false if not.
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;
// clip the left edge to src and dst bounds, adjusting dstPoint if necessary
if (clippedSrcRect->fLeft < 0) {
clippedDstPoint->fX -= clippedSrcRect->fLeft;
clippedSrcRect->fLeft = 0;
}
if (clippedDstPoint->fX < 0) {
clippedSrcRect->fLeft -= clippedDstPoint->fX;
clippedDstPoint->fX = 0;
}
// clip the top edge to src and dst bounds, adjusting dstPoint if necessary
if (clippedSrcRect->fTop < 0) {
clippedDstPoint->fY -= clippedSrcRect->fTop;
clippedSrcRect->fTop = 0;
}
if (clippedDstPoint->fY < 0) {
clippedSrcRect->fTop -= clippedDstPoint->fY;
clippedDstPoint->fY = 0;
}
// clip the right edge to the src and dst bounds.
if (clippedSrcRect->fRight > src->width()) {
clippedSrcRect->fRight = src->width();
}
if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
}
// clip the bottom edge to the src and dst bounds.
if (clippedSrcRect->fBottom > src->height()) {
clippedSrcRect->fBottom = src->height();
}
if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
}
// The above clipping steps may have inverted the rect if it didn't intersect either the src or
// dst bounds.
return !clippedSrcRect->isEmpty();
}
std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrRecordingContext* context, std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrRecordingContext* context,
GrSurfaceProxy* dstProxy, GrSurfaceProxy* dstProxy,
@ -73,22 +23,54 @@ std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrRecordingContext* context,
SkIRect clippedSrcRect; SkIRect clippedSrcRect;
SkIPoint clippedDstPoint; SkIPoint clippedDstPoint;
// If the rect is outside the srcProxy or dstProxy then we've already succeeded. // 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, if (!GrClipSrcRectAndDstPoint(dstProxy->isize(), srcProxy->isize(), srcRect, dstPoint,
&clippedSrcRect, &clippedDstPoint)) { &clippedSrcRect, &clippedDstPoint)) {
return nullptr; return nullptr;
} }
if (GrPixelConfigIsCompressed(dstProxy->config())) { if (GrPixelConfigIsCompressed(dstProxy->config())) {
return nullptr; return nullptr;
} }
SkASSERT(dstProxy->origin() == srcProxy->origin());
SkIRect adjSrcRect;
adjSrcRect.fLeft = clippedSrcRect.fLeft;
adjSrcRect.fRight = clippedSrcRect.fRight;
SkIPoint adjDstPoint;
adjDstPoint.fX = clippedDstPoint.fX;
// If it is bottom left origin we must flip the rects.
SkASSERT(dstProxy->origin() == srcProxy->origin());
if (kBottomLeft_GrSurfaceOrigin == srcProxy->origin()) {
adjSrcRect.fTop = srcProxy->height() - clippedSrcRect.fBottom;
adjSrcRect.fBottom = srcProxy->height() - clippedSrcRect.fTop;
adjDstPoint.fY = dstProxy->height() - clippedDstPoint.fY - clippedSrcRect.height();
} else {
adjSrcRect.fTop = clippedSrcRect.fTop;
adjSrcRect.fBottom = clippedSrcRect.fBottom;
adjDstPoint.fY = clippedDstPoint.fY;
}
GrOpMemoryPool* pool = context->priv().opMemoryPool(); GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<GrCopySurfaceOp>(srcProxy, clippedSrcRect, clippedDstPoint); return pool->allocate<GrCopySurfaceOp>(srcProxy, dstProxy, adjSrcRect, adjDstPoint);
} }
void GrCopySurfaceOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) { void GrCopySurfaceOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
SkASSERT(fSrc.get()->isInstantiated()); SkASSERT(fSrc.get()->isInstantiated());
state->commandBuffer()->copy(fSrc.get()->peekSurface(), fSrc.get()->origin(), fSrcRect, // If we are using approx surfaces we may need to adjust our srcRect or dstPoint if the origin
fDstPoint); // is bottom left.
GrSurfaceProxy* src = fSrc.get();
if (src->origin() == kBottomLeft_GrSurfaceOrigin) {
GrSurfaceProxy* dst = fDst.get();
SkASSERT(dst->isInstantiated());
if (src->height() != src->peekSurface()->height()) {
fSrcRect.offset(0, src->peekSurface()->height() - src->height());
}
if (dst->height() != dst->peekSurface()->height()) {
fDstPoint.fY = fDstPoint.fY + (dst->peekSurface()->height() - dst->height());
}
}
state->commandBuffer()->copy(fSrc.get()->peekSurface(), fSrcRect, fDstPoint);
} }

View File

@ -45,9 +45,11 @@ public:
private: private:
friend class GrOpMemoryPool; // for ctor friend class GrOpMemoryPool; // for ctor
GrCopySurfaceOp(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) GrCopySurfaceOp(GrSurfaceProxy* src, GrSurfaceProxy* dst, const SkIRect& srcRect,
const SkIPoint& dstPoint)
: INHERITED(ClassID()) : INHERITED(ClassID())
, fSrc(src) , fSrc(src)
, fDst(dst)
, fSrcRect(srcRect) , fSrcRect(srcRect)
, fDstPoint(dstPoint) { , fDstPoint(dstPoint) {
SkRect bounds = SkRect bounds =
@ -61,6 +63,7 @@ private:
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fSrc; GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fSrc;
GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fDst;
SkIRect fSrcRect; SkIRect fSrcRect;
SkIPoint fDstPoint; SkIPoint fDstPoint;

View File

@ -54,8 +54,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface*
} }
bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
GrSurfaceOrigin* origin, bool* rectsMustMatch, bool* rectsMustMatch, bool* disallowSubrect) const {
bool* disallowSubrect) const {
// Vk doesn't use rectsMustMatch or disallowSubrect. Always return false. // Vk doesn't use rectsMustMatch or disallowSubrect. Always return false.
*rectsMustMatch = false; *rectsMustMatch = false;
*disallowSubrect = false; *disallowSubrect = false;
@ -63,7 +62,6 @@ bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
// We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa). // 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 // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
// render target as well. // render target as well.
*origin = src->origin();
desc->fConfig = src->config(); desc->fConfig = src->config();
if (src->numColorSamples() > 1 || src->asTextureProxy()) { if (src->numColorSamples() > 1 || src->asTextureProxy()) {
desc->fFlags = kRenderTarget_GrSurfaceFlag; desc->fFlags = kRenderTarget_GrSurfaceFlag;
@ -120,9 +118,8 @@ static int get_compatible_format_class(GrPixelConfig config) {
return 0; return 0;
} }
bool GrVkCaps::canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, GrSurfaceOrigin dstOrigin, bool GrVkCaps::canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt, GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
GrSurfaceOrigin srcOrigin, bool srcHasYcbcr) const {
if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) { if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
return false; return false;
} }
@ -133,8 +130,7 @@ bool GrVkCaps::canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, GrSurface
// We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
// as image usage flags. // as image usage flags.
if (srcOrigin != dstOrigin || if (get_compatible_format_class(srcConfig) != get_compatible_format_class(dstConfig)) {
get_compatible_format_class(srcConfig) != get_compatible_format_class(dstConfig)) {
return false; return false;
} }
@ -179,10 +175,8 @@ bool GrVkCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dst
return true; return true;
} }
bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
GrSurfaceOrigin dstOrigin, bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt, bool srcHasYcbcr) const {
GrPixelConfig srcConfig, int srcSampleCnt,
GrSurfaceOrigin srcOrigin, bool srcHasYcbcr) const {
// The src surface must be multisampled. // The src surface must be multisampled.
if (srcSampleCnt <= 1) { if (srcSampleCnt <= 1) {
return false; return false;
@ -198,11 +192,6 @@ bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt,
return false; return false;
} }
// Surfaces must have the same origin.
if (srcOrigin != dstOrigin) {
return false;
}
if (dstHasYcbcr || srcHasYcbcr) { if (dstHasYcbcr || srcHasYcbcr) {
return false; return false;
} }
@ -210,32 +199,8 @@ bool GrVkCaps::canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt,
return true; return true;
} }
bool GrVkCaps::canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable, bool dstHasYcbcr,
GrPixelConfig srcConfig, bool srcIsTextureable,
bool srcHasYcbcr) const {
// TODO: Make copySurfaceAsDraw handle the swizzle
if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
this->shaderCaps()->configOutputSwizzle(dstConfig)) {
return false;
}
// Make sure the dst is a render target and the src is a texture.
if (!dstIsRenderable || !srcIsTextureable) {
return false;
}
if (dstHasYcbcr) {
return false;
}
return true;
}
bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src, bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
const SkIRect& srcRect, const SkIPoint& dstPoint) const { const SkIRect& srcRect, const SkIPoint& dstPoint) const {
GrSurfaceOrigin dstOrigin = dst->origin();
GrSurfaceOrigin srcOrigin = src->origin();
GrPixelConfig dstConfig = dst->config(); GrPixelConfig dstConfig = dst->config();
GrPixelConfig srcConfig = src->config(); GrPixelConfig srcConfig = src->config();
@ -283,14 +248,12 @@ bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy*
} }
} }
return this->canCopyImage(dstConfig, dstSampleCnt, dstOrigin, dstHasYcbcr, return this->canCopyImage(dstConfig, dstSampleCnt, dstHasYcbcr,
srcConfig, srcSampleCnt, srcOrigin, srcHasYcbcr) || srcConfig, srcSampleCnt, srcHasYcbcr) ||
this->canCopyAsBlit(dstConfig, dstSampleCnt, dstIsLinear, dstHasYcbcr, this->canCopyAsBlit(dstConfig, dstSampleCnt, dstIsLinear, dstHasYcbcr,
srcConfig, srcSampleCnt, srcIsLinear, srcHasYcbcr) || srcConfig, srcSampleCnt, srcIsLinear, srcHasYcbcr) ||
this->canCopyAsResolve(dstConfig, dstSampleCnt, dstOrigin, dstHasYcbcr, this->canCopyAsResolve(dstConfig, dstSampleCnt, dstHasYcbcr,
srcConfig, srcSampleCnt, srcOrigin, srcHasYcbcr) || srcConfig, srcSampleCnt, srcHasYcbcr);
this->canCopyAsDraw(dstConfig, dstSampleCnt > 0, dstHasYcbcr,
srcConfig, SkToBool(src->asTextureProxy()), srcHasYcbcr);
} }
template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features, template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features,

View File

@ -139,22 +139,17 @@ public:
* the surface is not a render target, otherwise it is the number of samples in the render * the surface is not a render target, otherwise it is the number of samples in the render
* target. * target.
*/ */
bool canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, GrSurfaceOrigin dstOrigin, bool canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSamplecnt, GrPixelConfig srcConfig, int srcSamplecnt, bool srcHasYcbcr) const;
GrSurfaceOrigin srcOrigin, bool srcHasYcbcr) const;
bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dstIsLinear, bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dstIsLinear,
bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt, bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt,
bool srcIsLinear, bool srcHasYcbcr) const; bool srcIsLinear, bool srcHasYcbcr) const;
bool canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, GrSurfaceOrigin dstOrigin, bool canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, bool dstHasYcbcr,
bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSamplecnt, GrPixelConfig srcConfig, int srcSamplecnt, bool srcHasYcbcr) const;
GrSurfaceOrigin srcOrigin, bool srcHasYcbcr) const;
bool canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable, bool dstHasYcbcr, bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
GrPixelConfig srcConfig, bool srcIsTextureable, bool srcHasYcbcr) const;
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, GrSurfaceOrigin*,
bool* rectsMustMatch, bool* disallowSubrect) const override; bool* rectsMustMatch, bool* disallowSubrect) const override;
GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&, GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,

View File

@ -1,458 +0,0 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/vk/GrVkCopyManager.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/gpu/GrSamplerState.h"
#include "include/gpu/GrSurface.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GrRenderTargetPriv.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/vk/GrVkCommandBuffer.h"
#include "src/gpu/vk/GrVkCommandPool.h"
#include "src/gpu/vk/GrVkCopyPipeline.h"
#include "src/gpu/vk/GrVkDescriptorSet.h"
#include "src/gpu/vk/GrVkGpu.h"
#include "src/gpu/vk/GrVkImageView.h"
#include "src/gpu/vk/GrVkPipelineLayout.h"
#include "src/gpu/vk/GrVkRenderTarget.h"
#include "src/gpu/vk/GrVkResourceProvider.h"
#include "src/gpu/vk/GrVkSampler.h"
#include "src/gpu/vk/GrVkTexture.h"
#include "src/gpu/vk/GrVkUniformBuffer.h"
#include "src/gpu/vk/GrVkVertexBuffer.h"
GrVkCopyManager::GrVkCopyManager()
: fVertShaderModule(VK_NULL_HANDLE)
, fFragShaderModule(VK_NULL_HANDLE)
, fPipelineLayout(nullptr) {}
GrVkCopyManager::~GrVkCopyManager() {}
bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) {
TRACE_EVENT0("skia", TRACE_FUNC);
SkSL::String vertShaderText;
vertShaderText.append(
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
"half4 uPosXform;"
"half4 uTexCoordXform;"
"};"
"layout(location = 0) in float2 inPosition;"
"layout(location = 1) out half2 vTexCoord;"
"// Copy Program VS\n"
"void main() {"
"vTexCoord = half2(inPosition * uTexCoordXform.xy + uTexCoordXform.zw);"
"sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
"sk_Position.zw = half2(0, 1);"
"}"
);
SkSL::String fragShaderText;
fragShaderText.append(
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
"layout(location = 1) in half2 vTexCoord;"
"// Copy Program FS\n"
"void main() {"
"sk_FragColor = texture(uTextureSampler, vTexCoord);"
"}"
);
SkSL::Program::Settings settings;
SkSL::String spirv;
SkSL::Program::Inputs inputs;
if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT,
&fVertShaderModule, &fShaderStageInfo[0], settings, &spirv,
&inputs)) {
this->destroyResources(gpu);
return false;
}
SkASSERT(inputs.isEmpty());
if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT,
&fFragShaderModule, &fShaderStageInfo[1], settings, &spirv,
&inputs)) {
this->destroyResources(gpu);
return false;
}
SkASSERT(inputs.isEmpty());
VkDescriptorSetLayout dsLayout[2];
GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
uint32_t samplerVisibility = kFragment_GrShaderFlag;
SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1);
resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
visibilityArray, &fSamplerDSHandle);
dsLayout[GrVkUniformHandler::kSamplerDescSet] =
resourceProvider.getSamplerDSLayout(fSamplerDSHandle);
// Create the VkPipelineLayout
VkPipelineLayoutCreateInfo layoutCreateInfo;
memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layoutCreateInfo.pNext = 0;
layoutCreateInfo.flags = 0;
layoutCreateInfo.setLayoutCount = 2;
layoutCreateInfo.pSetLayouts = dsLayout;
layoutCreateInfo.pushConstantRangeCount = 0;
layoutCreateInfo.pPushConstantRanges = nullptr;
VkPipelineLayout pipelineLayout;
VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
&layoutCreateInfo,
nullptr,
&pipelineLayout));
if (err) {
this->destroyResources(gpu);
return false;
}
fPipelineLayout = new GrVkPipelineLayout(pipelineLayout);
static const float vdata[] = {
0, 0,
0, 1,
1, 0,
1, 1
};
fVertexBuffer = GrVkVertexBuffer::Make(gpu, sizeof(vdata), false);
SkASSERT(fVertexBuffer.get());
fVertexBuffer->updateData(vdata, sizeof(vdata));
// We use 2 float4's for uniforms
fUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, 8 * sizeof(float)));
SkASSERT(fUniformBuffer.get());
return true;
}
bool GrVkCopyManager::copySurfaceAsDraw(GrVkGpu* gpu,
GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) {
// None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the
// swizzle.
if (gpu->caps()->shaderCaps()->configOutputSwizzle(src->config()) !=
gpu->caps()->shaderCaps()->configOutputSwizzle(dst->config())) {
return false;
}
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
if (!rt) {
return false;
}
GrVkTexture* srcTex = static_cast<GrVkTexture*>(src->asTexture());
if (!srcTex) {
return false;
}
if (VK_NULL_HANDLE == fVertShaderModule) {
SkASSERT(VK_NULL_HANDLE == fFragShaderModule &&
nullptr == fPipelineLayout &&
nullptr == fVertexBuffer.get() &&
nullptr == fUniformBuffer.get());
if (!this->createCopyProgram(gpu)) {
SkDebugf("Failed to create copy program.\n");
return false;
}
}
SkASSERT(fPipelineLayout);
GrVkResourceProvider& resourceProv = gpu->resourceProvider();
GrVkCopyPipeline* pipeline = resourceProv.findOrCreateCopyPipeline(rt,
fShaderStageInfo,
fPipelineLayout->layout());
if (!pipeline) {
return false;
}
// UPDATE UNIFORM DESCRIPTOR SET
int w = srcRect.width();
int h = srcRect.height();
// dst rect edges in NDC (-1 to 1)
int dw = dst->width();
int dh = dst->height();
float dx0 = 2.f * dstPoint.fX / dw - 1.f;
float dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
float dy0 = 2.f * dstPoint.fY / dh - 1.f;
float dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
dy0 = -dy0;
dy1 = -dy1;
}
float sx0 = (float)srcRect.fLeft;
float sx1 = (float)(srcRect.fLeft + w);
float sy0 = (float)srcRect.fTop;
float sy1 = (float)(srcRect.fTop + h);
int sh = src->height();
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
sy0 = sh - sy0;
sy1 = sh - sy1;
}
// src rect edges in normalized texture space (0 to 1).
int sw = src->width();
sx0 /= sw;
sx1 /= sw;
sy0 /= sh;
sy1 /= sh;
float uniData[] = { dx1 - dx0, dy1 - dy0, dx0, dy0, // posXform
sx1 - sx0, sy1 - sy0, sx0, sy0 }; // texCoordXform
fUniformBuffer->updateData(gpu, uniData, sizeof(uniData), nullptr);
const GrVkDescriptorSet* uniformDS = resourceProv.getUniformDescriptorSet();
SkASSERT(uniformDS);
VkDescriptorBufferInfo uniBufferInfo;
uniBufferInfo.buffer = fUniformBuffer->buffer();
uniBufferInfo.offset = fUniformBuffer->offset();
uniBufferInfo.range = fUniformBuffer->size();
VkWriteDescriptorSet descriptorWrites;
descriptorWrites.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites.pNext = nullptr;
descriptorWrites.dstSet = uniformDS->descriptorSet();
descriptorWrites.dstBinding = GrVkUniformHandler::kGeometryBinding;
descriptorWrites.dstArrayElement = 0;
descriptorWrites.descriptorCount = 1;
descriptorWrites.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites.pImageInfo = nullptr;
descriptorWrites.pBufferInfo = &uniBufferInfo;
descriptorWrites.pTexelBufferView = nullptr;
GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
1,
&descriptorWrites,
0, nullptr));
// UPDATE SAMPLER DESCRIPTOR SET
const GrVkDescriptorSet* samplerDS =
gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
GrSamplerState samplerState = GrSamplerState::ClampNearest();
GrVkSampler* sampler = resourceProv.findOrCreateCompatibleSampler(
samplerState, GrVkYcbcrConversionInfo());
VkDescriptorImageInfo imageInfo;
memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
imageInfo.sampler = sampler->sampler();
imageInfo.imageView = srcTex->textureView()->imageView();
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkWriteDescriptorSet writeInfo;
memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr;
writeInfo.dstSet = samplerDS->descriptorSet();
writeInfo.dstBinding = 0;
writeInfo.dstArrayElement = 0;
writeInfo.descriptorCount = 1;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writeInfo.pImageInfo = &imageInfo;
writeInfo.pBufferInfo = nullptr;
writeInfo.pTexelBufferView = nullptr;
GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
1,
&writeInfo,
0, nullptr));
VkDescriptorSet vkDescSets[] = { uniformDS->descriptorSet(), samplerDS->descriptorSet() };
GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(srcTex->asRenderTarget());
if (texRT) {
gpu->resolveRenderTargetNoFlush(texRT);
}
// TODO: Make tighter bounds and then adjust bounds for origin and granularity if we see
// any perf issues with using the whole bounds
SkIRect bounds = SkIRect::MakeWH(rt->width(), rt->height());
// Change layouts of rt and texture. We aren't blending so we don't need color attachment read
// access for blending.
GrVkImage* targetImage = rt->msaaImage() ? rt->msaaImage() : rt;
VkAccessFlags dstAccessFlags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
if (!canDiscardOutsideDstRect) {
// We need to load the color attachment so need to be able to read it.
dstAccessFlags |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
}
targetImage->setImageLayout(gpu,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
dstAccessFlags,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
false);
srcTex->setImageLayout(gpu,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
false);
GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
if (stencil) {
GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
// We aren't actually using the stencil but we still load and store it so we need
// appropriate barriers.
// TODO: Once we refactor surface and how we conntect stencil to RTs, we should not even
// have the stencil on this render pass if possible.
vkStencil->setImageLayout(gpu,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
false);
}
VkAttachmentLoadOp loadOp = canDiscardOutsideDstRect ? VK_ATTACHMENT_LOAD_OP_DONT_CARE
: VK_ATTACHMENT_LOAD_OP_LOAD;
GrVkRenderPass::LoadStoreOps vkColorOps(loadOp, VK_ATTACHMENT_STORE_OP_STORE);
GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE);
const GrVkRenderPass* renderPass;
const GrVkResourceProvider::CompatibleRPHandle& rpHandle = rt->compatibleRenderPassHandle();
if (rpHandle.isValid()) {
renderPass = gpu->resourceProvider().findRenderPass(rpHandle,
vkColorOps,
vkStencilOps);
} else {
renderPass = gpu->resourceProvider().findRenderPass(*rt,
vkColorOps,
vkStencilOps);
}
SkASSERT(renderPass->isCompatible(*rt->simpleRenderPass()));
GrVkPrimaryCommandBuffer* cmdBuffer = gpu->currentCommandBuffer();
cmdBuffer->beginRenderPass(gpu, renderPass, nullptr, *rt, bounds, true);
GrVkSecondaryCommandBuffer* secondary = gpu->cmdPool()->findOrCreateSecondaryCommandBuffer(gpu);
if (!secondary) {
return false;
}
secondary->begin(gpu, rt->framebuffer(), renderPass);
secondary->bindPipeline(gpu, pipeline);
// Uniform DescriptorSet, Sampler DescriptorSet, and vertex shader uniformBuffer
SkSTArray<3, const GrVkRecycledResource*> descriptorRecycledResources;
descriptorRecycledResources.push_back(uniformDS);
descriptorRecycledResources.push_back(samplerDS);
descriptorRecycledResources.push_back(fUniformBuffer->resource());
// One sampler, texture view, and texture
SkSTArray<3, const GrVkResource*> descriptorResources;
descriptorResources.push_back(sampler);
descriptorResources.push_back(srcTex->textureView());
descriptorResources.push_back(srcTex->resource());
secondary->bindDescriptorSets(gpu,
descriptorRecycledResources,
descriptorResources,
fPipelineLayout,
0,
2,
vkDescSets,
0,
nullptr);
// Set Dynamic viewport and stencil
// We always use one viewport the size of the RT
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = SkIntToScalar(rt->width());
viewport.height = SkIntToScalar(rt->height());
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
secondary->setViewport(gpu, 0, 1, &viewport);
// We assume the scissor is not enabled so just set it to the whole RT
VkRect2D scissor;
scissor.extent.width = rt->width();
scissor.extent.height = rt->height();
scissor.offset.x = 0;
scissor.offset.y = 0;
secondary->setScissor(gpu, 0, 1, &scissor);
secondary->bindInputBuffer(gpu, 0, fVertexBuffer.get());
secondary->draw(gpu, 4, 1, 0, 0);
secondary->end(gpu);
cmdBuffer->executeCommands(gpu, secondary);
cmdBuffer->endRenderPass(gpu);
secondary->unref(gpu);
// Release all temp resources which should now be reffed by the cmd buffer
pipeline->unref(gpu);
uniformDS->unref(gpu);
samplerDS->unref(gpu);
sampler->unref(gpu);
renderPass->unref(gpu);
return true;
}
void GrVkCopyManager::destroyResources(GrVkGpu* gpu) {
if (VK_NULL_HANDLE != fVertShaderModule) {
GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule,
nullptr));
fVertShaderModule = VK_NULL_HANDLE;
}
if (VK_NULL_HANDLE != fFragShaderModule) {
GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule,
nullptr));
fFragShaderModule = VK_NULL_HANDLE;
}
if (fPipelineLayout) {
fPipelineLayout->unref(gpu);
fPipelineLayout = nullptr;
}
if (fUniformBuffer) {
fUniformBuffer->release(gpu);
fUniformBuffer.reset();
}
}
void GrVkCopyManager::abandonResources() {
fVertShaderModule = VK_NULL_HANDLE;
fFragShaderModule = VK_NULL_HANDLE;
if (fPipelineLayout) {
fPipelineLayout->unrefAndAbandon();
fPipelineLayout = nullptr;
}
if (fUniformBuffer) {
fUniformBuffer->abandon();
fUniformBuffer.reset();
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrVkCopyManager_DEFINED
#define GrVkCopyManager_DEFINED
#include "include/gpu/GrTypes.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "src/gpu/vk/GrVkDescriptorSetManager.h"
class GrSurface;
class GrVkCopyPipeline;
class GrVkGpu;
class GrVkPipelineLayout;
class GrVkUniformBuffer;
class GrVkVertexBuffer;
struct SkIPoint;
struct SkIRect;
class GrVkCopyManager {
public:
GrVkCopyManager();
~GrVkCopyManager();
bool copySurfaceAsDraw(GrVkGpu* gpu,
GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect);
void destroyResources(GrVkGpu* gpu);
void abandonResources();
private:
bool createCopyProgram(GrVkGpu* gpu);
// Everything below is only created once and shared by all copy draws/pipelines
VkShaderModule fVertShaderModule;
VkShaderModule fFragShaderModule;
VkPipelineShaderStageCreateInfo fShaderStageInfo[2];
GrVkDescriptorSetManager::Handle fSamplerDSHandle;
GrVkPipelineLayout* fPipelineLayout;
sk_sp<GrVkVertexBuffer> fVertexBuffer;
std::unique_ptr<GrVkUniformBuffer> fUniformBuffer;
};
#endif

View File

@ -1,202 +0,0 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/vk/GrVkCopyPipeline.h"
#include "include/private/SkOnce.h"
#include "src/gpu/vk/GrVkGpu.h"
#include "src/gpu/vk/GrVkUtil.h"
#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
#include <sanitizer/lsan_interface.h>
#endif
static void setup_multisample_state(int numSamples,
VkPipelineMultisampleStateCreateInfo* multisampleInfo) {
memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampleInfo->pNext = nullptr;
multisampleInfo->flags = 0;
SkAssertResult(GrSampleCountToVkSampleCount(numSamples,
&multisampleInfo->rasterizationSamples));
multisampleInfo->sampleShadingEnable = VK_FALSE;
multisampleInfo->minSampleShading = 0.0f;
multisampleInfo->pSampleMask = nullptr;
multisampleInfo->alphaToCoverageEnable = VK_FALSE;
multisampleInfo->alphaToOneEnable = VK_FALSE;
}
GrVkCopyPipeline* GrVkCopyPipeline::Create(GrVkGpu* gpu,
VkPipelineShaderStageCreateInfo* shaderStageInfo,
VkPipelineLayout pipelineLayout,
int numSamples,
const GrVkRenderPass& renderPass,
VkPipelineCache cache) {
static const VkVertexInputAttributeDescription attributeDesc = {
0, // location
0, // binding
VK_FORMAT_R32G32_SFLOAT, // format
0, // offset
};
static const VkVertexInputBindingDescription bindingDesc = {
0, // binding
2 * sizeof(float), // stride
VK_VERTEX_INPUT_RATE_VERTEX // inputRate
};
static const VkPipelineVertexInputStateCreateInfo vertexInputInfo = {
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
1, // vertexBindingDescriptionCount
&bindingDesc, // pVertexBindingDescriptions
1, // vertexAttributeDescriptionCnt
&attributeDesc, // pVertexAttributeDescriptions
};
static const VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = {
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // topology
VK_FALSE // primitiveRestartEnable
};
static const VkStencilOpState dummyStencilState = {
VK_STENCIL_OP_KEEP, // failOp
VK_STENCIL_OP_KEEP, // passOp
VK_STENCIL_OP_KEEP, // depthFailOp
VK_COMPARE_OP_NEVER, // compareOp
0, // compareMask
0, // writeMask
0 // reference
};
static const VkPipelineDepthStencilStateCreateInfo stencilInfo = {
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
VK_FALSE, // depthTestEnable
VK_FALSE, // depthWriteEnable
VK_COMPARE_OP_ALWAYS, // depthCompareOp
VK_FALSE, // depthBoundsTestEnable
VK_FALSE, // stencilTestEnable
dummyStencilState, // front
dummyStencilState, // bakc
0.0f, // minDepthBounds
1.0f // maxDepthBounds
};
static const VkPipelineViewportStateCreateInfo viewportInfo = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
1, // viewportCount
nullptr, // pViewports
1, // scissorCount
nullptr // pScissors
};
static const VkPipelineColorBlendAttachmentState attachmentState = {
VK_FALSE, // blendEnable
VK_BLEND_FACTOR_ONE, // srcColorBlendFactor
VK_BLEND_FACTOR_ZERO, // dstColorBlendFactor
VK_BLEND_OP_ADD, // colorBlendOp
VK_BLEND_FACTOR_ONE, // srcAlphaBlendFactor
VK_BLEND_FACTOR_ZERO, // dstAlphaBlendFactor
VK_BLEND_OP_ADD, // alphaBlendOp
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // colorWriteMask
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT // colorWriteMask
};
static const VkPipelineColorBlendStateCreateInfo colorBlendInfo = {
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
VK_FALSE, // logicOpEnable
VK_LOGIC_OP_CLEAR, // logicOp
1, // attachmentCount
&attachmentState, // pAttachments
{ 0.f, 0.f, 0.f, 0.f } // blendConstants[4]
};
static const VkPipelineRasterizationStateCreateInfo rasterInfo = {
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
VK_FALSE, // depthClampEnable
VK_FALSE, // rasterizerDiscardEnabled
VK_POLYGON_MODE_FILL, // polygonMode
VK_CULL_MODE_NONE, // cullMode
VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
VK_FALSE, // depthBiasEnable
0.0f, // depthBiasConstantFactor
0.0f, // depthBiasClamp
0.0f, // depthBiasSlopeFactor
1.0f // lineWidth
};
static const VkDynamicState dynamicStates[2] = { VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR };
static const VkPipelineDynamicStateCreateInfo dynamicInfo = {
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType
nullptr, // pNext
0, // flags
2, // dynamicStateCount
dynamicStates // pDynamicStates
};
VkPipelineMultisampleStateCreateInfo multisampleInfo;
setup_multisample_state(numSamples, &multisampleInfo);
VkGraphicsPipelineCreateInfo pipelineCreateInfo;
memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineCreateInfo.pNext = nullptr;
pipelineCreateInfo.flags = 0;
pipelineCreateInfo.stageCount = 2;
pipelineCreateInfo.pStages = shaderStageInfo;
pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
pipelineCreateInfo.pTessellationState = nullptr;
pipelineCreateInfo.pViewportState = &viewportInfo;
pipelineCreateInfo.pRasterizationState = &rasterInfo;
pipelineCreateInfo.pMultisampleState = &multisampleInfo;
pipelineCreateInfo.pDepthStencilState = &stencilInfo;
pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
pipelineCreateInfo.pDynamicState = &dynamicInfo;
pipelineCreateInfo.layout = pipelineLayout;
pipelineCreateInfo.renderPass = renderPass.vkRenderPass();
pipelineCreateInfo.subpass = 0;
pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineCreateInfo.basePipelineIndex = -1;
VkPipeline vkPipeline;
VkResult err;
{
#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
// skia:8712
__lsan::ScopedDisabler lsanDisabler;
#endif
err = GR_VK_CALL(gpu->vkInterface(), CreateGraphicsPipelines(gpu->device(),
cache, 1,
&pipelineCreateInfo,
nullptr, &vkPipeline));
}
if (err) {
SkDebugf("Failed to create copy pipeline. Error: %d\n", err);
return nullptr;
}
return new GrVkCopyPipeline(vkPipeline, &renderPass);
}
bool GrVkCopyPipeline::isCompatible(const GrVkRenderPass& rp) const {
return rp.isCompatible(*fRenderPass);
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrVkCopyPipeline_DEFINED
#define GrVkCopyPipeline_DEFINED
#include "src/gpu/vk/GrVkPipeline.h"
class GrVkCopyPipeline : public GrVkPipeline {
public:
// We expect the passed in renderPass to be stored on the GrVkResourceProvider and not a local
// object of the client.
static GrVkCopyPipeline* Create(GrVkGpu* gpu,
VkPipelineShaderStageCreateInfo* shaderStageInfo,
VkPipelineLayout pipelineLayout,
int numSamples,
const GrVkRenderPass& renderPass,
VkPipelineCache cache);
bool isCompatible(const GrVkRenderPass& rp) const;
#ifdef SK_TRACE_VK_RESOURCES
void dumpInfo() const override {
SkDebugf("GrVkCopyPipeline: %d (%d refs)\n", fPipeline, this->getRefCnt());
}
#endif
private:
GrVkCopyPipeline(VkPipeline pipeline, const GrVkRenderPass* renderPass)
: INHERITED(pipeline)
, fRenderPass(renderPass) {
}
const GrVkRenderPass* fRenderPass;
typedef GrVkPipeline INHERITED;
};
#endif

View File

@ -262,9 +262,6 @@ void GrVkGpu::destroyResources() {
} }
fSemaphoresToSignal.reset(); fSemaphoresToSignal.reset();
fCopyManager.destroyResources(this);
// must call this just before we destroy the command pool and VkDevice // must call this just before we destroy the command pool and VkDevice
fResourceProvider.destroyResources(VK_ERROR_DEVICE_LOST == res); fResourceProvider.destroyResources(VK_ERROR_DEVICE_LOST == res);
@ -299,7 +296,6 @@ void GrVkGpu::disconnect(DisconnectType type) {
for (int i = 0; i < fSemaphoresToSignal.count(); ++i) { for (int i = 0; i < fSemaphoresToSignal.count(); ++i) {
fSemaphoresToSignal[i]->unrefAndAbandon(); fSemaphoresToSignal[i]->unrefAndAbandon();
} }
fCopyManager.abandonResources();
// must call this just before we destroy the command pool and VkDevice // must call this just before we destroy the command pool and VkDevice
fResourceProvider.abandonResources(); fResourceProvider.abandonResources();
@ -783,6 +779,11 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int widt
// R8G8B8A8_UNORM image and then copy it. // R8G8B8A8_UNORM image and then copy it.
sk_sp<GrVkTexture> copyTexture; sk_sp<GrVkTexture> copyTexture;
if (dataColorType == GrColorType::kRGB_888x && tex->imageFormat() == VK_FORMAT_R8G8B8_UNORM) { if (dataColorType == GrColorType::kRGB_888x && tex->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
bool dstHasYcbcr = tex->ycbcrConversionInfo().isValid();
if (!this->vkCaps().canCopyAsBlit(tex->config(), 1, false, dstHasYcbcr,
kRGBA_8888_GrPixelConfig, 1, false, false)) {
return false;
}
GrSurfaceDesc surfDesc; GrSurfaceDesc surfDesc;
surfDesc.fFlags = kRenderTarget_GrSurfaceFlag; surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
surfDesc.fWidth = width; surfDesc.fWidth = width;
@ -811,16 +812,6 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int widt
return false; return false;
} }
bool dstHasYcbcr = tex->ycbcrConversionInfo().isValid();
if (!this->vkCaps().canCopyAsBlit(tex->config(), 1, false, dstHasYcbcr,
copyTexture->config(), 1, false,
false) &&
!this->vkCaps().canCopyAsDraw(tex->config(), SkToBool(tex->asRenderTarget()),
dstHasYcbcr,
copyTexture->config(), true, false)) {
return false;
}
uploadTexture = copyTexture.get(); uploadTexture = copyTexture.get();
uploadLeft = 0; uploadLeft = 0;
uploadTop = 0; uploadTop = 0;
@ -881,10 +872,8 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int widt
// now. // now.
if (copyTexture.get()) { if (copyTexture.get()) {
SkASSERT(dataColorType == GrColorType::kRGB_888x); SkASSERT(dataColorType == GrColorType::kRGB_888x);
static const GrSurfaceOrigin kOrigin = kTopLeft_GrSurfaceOrigin; SkAssertResult(this->copySurface(tex, copyTexture.get(), SkIRect::MakeWH(width, height),
SkAssertResult(this->copySurface(tex, kOrigin, copyTexture.get(), kOrigin, SkIPoint::Make(left, top), false));
SkIRect::MakeWH(width, height), SkIPoint::Make(left, top),
false));
} }
if (1 == mipLevelCount) { if (1 == mipLevelCount) {
tex->texturePriv().markMipMapsDirty(); tex->texturePriv().markMipMapsDirty();
@ -2102,19 +2091,16 @@ static int get_surface_sample_cnt(GrSurface* surf) {
return 0; return 0;
} }
void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurfaceOrigin dstOrigin, void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
GrSurface* src, GrSurfaceOrigin srcOrigin, GrVkImage* srcImage, const SkIRect& srcRect,
GrVkImage* dstImage,
GrVkImage* srcImage,
const SkIRect& srcRect,
const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
#ifdef SK_DEBUG #ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst); int dstSampleCnt = get_surface_sample_cnt(dst);
int srcSampleCnt = get_surface_sample_cnt(src); int srcSampleCnt = get_surface_sample_cnt(src);
bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid(); bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid(); bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
SkASSERT(this->vkCaps().canCopyImage(dst->config(), dstSampleCnt, dstOrigin, dstHasYcbcr, SkASSERT(this->vkCaps().canCopyImage(dst->config(), dstSampleCnt, dstHasYcbcr,
src->config(), srcSampleCnt, srcOrigin, srcHasYcbcr)); src->config(), srcSampleCnt, srcHasYcbcr));
#endif #endif
@ -2132,24 +2118,13 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
false); false);
// Flip rect if necessary
SkIRect srcVkRect = srcRect;
int32_t dstY = dstPoint.fY;
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
SkASSERT(kBottomLeft_GrSurfaceOrigin == dstOrigin);
srcVkRect.fTop = src->height() - srcRect.fBottom;
srcVkRect.fBottom = src->height() - srcRect.fTop;
dstY = dst->height() - dstPoint.fY - srcVkRect.height();
}
VkImageCopy copyRegion; VkImageCopy copyRegion;
memset(&copyRegion, 0, sizeof(VkImageCopy)); memset(&copyRegion, 0, sizeof(VkImageCopy));
copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 }; copyRegion.srcOffset = { srcRect.fLeft, srcRect.fTop, 0 };
copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
copyRegion.dstOffset = { dstPoint.fX, dstY, 0 }; copyRegion.dstOffset = { dstPoint.fX, dstPoint.fY, 0 };
copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 }; copyRegion.extent = { (uint32_t)srcRect.width(), (uint32_t)srcRect.height(), 1 };
fCurrentCmdBuffer->copyImage(this, fCurrentCmdBuffer->copyImage(this,
srcImage, srcImage,
@ -2161,14 +2136,12 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
srcRect.width(), srcRect.height()); srcRect.width(), srcRect.height());
this->didWriteToSurface(dst, dstOrigin, &dstRect); // The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
} }
void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin, void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
GrSurface* src, GrSurfaceOrigin srcOrigin, GrVkImage* srcImage, const SkIRect& srcRect,
GrVkImage* dstImage,
GrVkImage* srcImage,
const SkIRect& srcRect,
const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
#ifdef SK_DEBUG #ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst); int dstSampleCnt = get_surface_sample_cnt(dst);
@ -2193,40 +2166,14 @@ void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
false); false);
// Flip rect if necessary // Flip rect if necessary
SkIRect srcVkRect; SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, srcRect.width(),
srcVkRect.fLeft = srcRect.fLeft; srcRect.height());
srcVkRect.fRight = srcRect.fRight;
SkIRect dstRect;
dstRect.fLeft = dstPoint.fX;
dstRect.fRight = dstPoint.fX + srcRect.width();
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
srcVkRect.fTop = src->height() - srcRect.fBottom;
srcVkRect.fBottom = src->height() - srcRect.fTop;
} else {
srcVkRect.fTop = srcRect.fTop;
srcVkRect.fBottom = srcRect.fBottom;
}
if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
} else {
dstRect.fTop = dstPoint.fY;
}
dstRect.fBottom = dstRect.fTop + srcVkRect.height();
// If we have different origins, we need to flip the top and bottom of the dst rect so that we
// get the correct origintation of the copied data.
if (srcOrigin != dstOrigin) {
using std::swap;
swap(dstRect.fTop, dstRect.fBottom);
}
VkImageBlit blitRegion; VkImageBlit blitRegion;
memset(&blitRegion, 0, sizeof(VkImageBlit)); memset(&blitRegion, 0, sizeof(VkImageBlit));
blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 }; blitRegion.srcOffsets[0] = { srcRect.fLeft, srcRect.fTop, 0 };
blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 1 }; blitRegion.srcOffsets[1] = { srcRect.fRight, srcRect.fBottom, 1 };
blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 }; blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 }; blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 };
@ -2238,32 +2185,22 @@ void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
&blitRegion, &blitRegion,
VK_FILTER_NEAREST); // We never scale so any filter works here VK_FILTER_NEAREST); // We never scale so any filter works here
dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, srcRect.width(), srcRect.height()); // The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, dstOrigin, &dstRect); this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
} }
void GrVkGpu::copySurfaceAsResolve(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src, void GrVkGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurfaceOrigin srcOrigin, const SkIRect& origSrcRect, const SkIPoint& dstPoint) {
const SkIPoint& origDstPoint) {
GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget()); GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
SkIRect srcRect = origSrcRect;
SkIPoint dstPoint = origDstPoint;
if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
SkASSERT(kBottomLeft_GrSurfaceOrigin == dstOrigin);
srcRect = {origSrcRect.fLeft, src->height() - origSrcRect.fBottom,
origSrcRect.fRight, src->height() - origSrcRect.fTop};
dstPoint.fY = dst->height() - dstPoint.fY - srcRect.height();
}
this->resolveImage(dst, srcRT, srcRect, dstPoint); this->resolveImage(dst, srcRT, srcRect, dstPoint);
SkIRect dstRect = SkIRect::MakeXYWH(origDstPoint.fX, origDstPoint.fY, SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
srcRect.width(), srcRect.height()); srcRect.width(), srcRect.height());
this->didWriteToSurface(dst, dstOrigin, &dstRect); // The rect is already in device space so we pass in kTopLeft so no flip is done.
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
} }
bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
const SkIRect& srcRect, const SkIPoint& dstPoint,
bool canDiscardOutsideDstRect) {
#ifdef SK_DEBUG #ifdef SK_DEBUG
if (GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget())) { if (GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget())) {
SkASSERT(!srcRT->wrapsSecondaryCommandBuffer()); SkASSERT(!srcRT->wrapsSecondaryCommandBuffer());
@ -2304,33 +2241,22 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid(); bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid(); bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
if (this->vkCaps().canCopyAsResolve(dstConfig, dstSampleCnt, dstOrigin, dstHasYcbcr, if (this->vkCaps().canCopyAsResolve(dstConfig, dstSampleCnt, dstHasYcbcr,
srcConfig, srcSampleCnt, srcOrigin, srcHasYcbcr)) { srcConfig, srcSampleCnt, srcHasYcbcr)) {
this->copySurfaceAsResolve(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint); this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
return true; return true;
} }
if (this->vkCaps().canCopyAsDraw(dstConfig, SkToBool(dst->asRenderTarget()), dstHasYcbcr, if (this->vkCaps().canCopyImage(dstConfig, dstSampleCnt, dstHasYcbcr,
srcConfig, SkToBool(src->asTexture()), srcHasYcbcr)) { srcConfig, srcSampleCnt, srcHasYcbcr)) {
SkAssertResult(fCopyManager.copySurfaceAsDraw(this, dst, dstOrigin, src, srcOrigin, srcRect, this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
dstPoint, canDiscardOutsideDstRect));
auto dstRect = srcRect.makeOffset(dstPoint.fX, dstPoint.fY);
this->didWriteToSurface(dst, dstOrigin, &dstRect);
return true;
}
if (this->vkCaps().canCopyImage(dstConfig, dstSampleCnt, dstOrigin, dstHasYcbcr,
srcConfig, srcSampleCnt, srcOrigin, srcHasYcbcr)) {
this->copySurfaceAsCopyImage(dst, dstOrigin, src, srcOrigin, dstImage, srcImage,
srcRect, dstPoint);
return true; return true;
} }
if (this->vkCaps().canCopyAsBlit(dstConfig, dstSampleCnt, dstImage->isLinearTiled(), if (this->vkCaps().canCopyAsBlit(dstConfig, dstSampleCnt, dstImage->isLinearTiled(),
dstHasYcbcr, srcConfig, srcSampleCnt, dstHasYcbcr, srcConfig, srcSampleCnt,
srcImage->isLinearTiled(), srcHasYcbcr)) { srcImage->isLinearTiled(), srcHasYcbcr)) {
this->copySurfaceAsBlit(dst, dstOrigin, src, srcOrigin, dstImage, srcImage, this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
srcRect, dstPoint);
return true; return true;
} }
@ -2380,6 +2306,17 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
if (dstColorType == GrColorType::kRGB_888x && image->imageFormat() == VK_FORMAT_R8G8B8_UNORM) { if (dstColorType == GrColorType::kRGB_888x && image->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
SkASSERT(surface->config() == kRGB_888_GrPixelConfig); SkASSERT(surface->config() == kRGB_888_GrPixelConfig);
int srcSampleCount = 0;
if (rt) {
srcSampleCount = rt->numColorSamples();
}
bool srcHasYcbcr = image->ycbcrConversionInfo().isValid();
if (!this->vkCaps().canCopyAsBlit(kRGBA_8888_GrPixelConfig, 1, false, false,
surface->config(), srcSampleCount, image->isLinearTiled(),
srcHasYcbcr)) {
return false;
}
// Make a new surface that is RGBA to copy the RGB surface into. // Make a new surface that is RGBA to copy the RGB surface into.
GrSurfaceDesc surfDesc; GrSurfaceDesc surfDesc;
surfDesc.fFlags = kRenderTarget_GrSurfaceFlag; surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
@ -2410,25 +2347,9 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
return false; return false;
} }
int srcSampleCount = 0;
if (rt) {
srcSampleCount = rt->numColorSamples();
}
bool srcHasYcbcr = image->ycbcrConversionInfo().isValid();
if (!this->vkCaps().canCopyAsBlit(copySurface->config(), 1, false, false,
surface->config(), srcSampleCount, image->isLinearTiled(),
srcHasYcbcr) &&
!this->vkCaps().canCopyAsDraw(copySurface->config(), false, false,
surface->config(), SkToBool(surface->asTexture()),
srcHasYcbcr)) {
return false;
}
SkIRect srcRect = SkIRect::MakeXYWH(left, top, width, height); SkIRect srcRect = SkIRect::MakeXYWH(left, top, width, height);
static const GrSurfaceOrigin kOrigin = kTopLeft_GrSurfaceOrigin; SkAssertResult(this->copySurface(copySurface.get(), surface, srcRect, SkIPoint::Make(0,0)));
if (!this->copySurface(copySurface.get(), kOrigin, surface, kOrigin,
srcRect, SkIPoint::Make(0,0))) {
return false;
}
top = 0; top = 0;
left = 0; left = 0;
dstColorType = GrColorType::kRGBA_8888; dstColorType = GrColorType::kRGBA_8888;

View File

@ -12,7 +12,6 @@
#include "include/gpu/vk/GrVkTypes.h" #include "include/gpu/vk/GrVkTypes.h"
#include "src/gpu/GrGpu.h" #include "src/gpu/GrGpu.h"
#include "src/gpu/vk/GrVkCaps.h" #include "src/gpu/vk/GrVkCaps.h"
#include "src/gpu/vk/GrVkCopyManager.h"
#include "src/gpu/vk/GrVkIndexBuffer.h" #include "src/gpu/vk/GrVkIndexBuffer.h"
#include "src/gpu/vk/GrVkMemory.h" #include "src/gpu/vk/GrVkMemory.h"
#include "src/gpu/vk/GrVkResourceProvider.h" #include "src/gpu/vk/GrVkResourceProvider.h"
@ -222,8 +221,7 @@ private:
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height, bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override; GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override;
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src, bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override; const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override;
void onFinishFlush(GrSurfaceProxy*[], int, SkSurface::BackendSurfaceAccess access, void onFinishFlush(GrSurfaceProxy*[], int, SkSurface::BackendSurfaceAccess access,
@ -240,21 +238,14 @@ private:
void internalResolveRenderTarget(GrRenderTarget*, bool requiresSubmit); void internalResolveRenderTarget(GrRenderTarget*, bool requiresSubmit);
void copySurfaceAsCopyImage(GrSurface* dst, GrSurfaceOrigin dstOrigin, void copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
GrSurface* src, GrSurfaceOrigin srcOrigin, GrVkImage* srcImage, const SkIRect& srcRect,
GrVkImage* dstImage, GrVkImage* srcImage,
const SkIRect& srcRect,
const SkIPoint& dstPoint); const SkIPoint& dstPoint);
void copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin, void copySurfaceAsBlit(GrSurface* dst, GrSurface* src, GrVkImage* dstImage, GrVkImage* srcImage,
GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, const SkIPoint& dstPoint);
GrVkImage* dstImage, GrVkImage* srcImage,
const SkIRect& srcRect,
const SkIPoint& dstPoint);
void copySurfaceAsResolve(GrSurface* dst, GrSurfaceOrigin dstOrigin, void copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
const SkIPoint& dstPoint); const SkIPoint& dstPoint);
// helpers for onCreateTexture and writeTexturePixels // helpers for onCreateTexture and writeTexturePixels
@ -298,8 +289,6 @@ private:
VkPhysicalDeviceProperties fPhysDevProps; VkPhysicalDeviceProperties fPhysDevProps;
VkPhysicalDeviceMemoryProperties fPhysDevMemProps; VkPhysicalDeviceMemoryProperties fPhysDevMemProps;
GrVkCopyManager fCopyManager;
// compiler used for compiling sksl into spirv. We only want to create the compiler once since // compiler used for compiling sksl into spirv. We only want to create the compiler once since
// there is significant overhead to the first compile of any compiler. // there is significant overhead to the first compile of any compiler.
SkSL::Compiler* fCompiler; SkSL::Compiler* fCompiler;

View File

@ -46,23 +46,19 @@ private:
class Copy : public GrVkPrimaryCommandBufferTask { class Copy : public GrVkPrimaryCommandBufferTask {
public: public:
Copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, Copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint, bool shouldDiscardDst)
const SkIPoint& dstPoint, bool shouldDiscardDst)
: fSrc(src) : fSrc(src)
, fSrcOrigin(srcOrigin)
, fSrcRect(srcRect) , fSrcRect(srcRect)
, fDstPoint(dstPoint) , fDstPoint(dstPoint)
, fShouldDiscardDst(shouldDiscardDst) {} , fShouldDiscardDst(shouldDiscardDst) {}
void execute(const Args& args) override { void execute(const Args& args) override {
args.fGpu->copySurface(args.fSurface, args.fOrigin, fSrc.get(), fSrcOrigin, fSrcRect, args.fGpu->copySurface(args.fSurface, fSrc.get(), fSrcRect, fDstPoint, fShouldDiscardDst);
fDstPoint, fShouldDiscardDst);
} }
private: private:
using Src = GrPendingIOResource<GrSurface, kRead_GrIOType>; using Src = GrPendingIOResource<GrSurface, kRead_GrIOType>;
Src fSrc; Src fSrc;
GrSurfaceOrigin fSrcOrigin;
SkIRect fSrcRect; SkIRect fSrcRect;
SkIPoint fDstPoint; SkIPoint fDstPoint;
bool fShouldDiscardDst; bool fShouldDiscardDst;
@ -94,9 +90,9 @@ private:
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin, void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
const SkIRect& srcRect, const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
fTasks.emplace<Copy>(src, srcOrigin, srcRect, dstPoint, false); fTasks.emplace<Copy>(src, srcRect, dstPoint, false);
} }
void GrVkGpuTextureCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void GrVkGpuTextureCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
@ -109,7 +105,7 @@ void GrVkGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
} }
void GrVkGpuTextureCommandBuffer::submit() { void GrVkGpuTextureCommandBuffer::submit() {
GrVkPrimaryCommandBufferTask::Args taskArgs{fGpu, fTexture, fOrigin}; GrVkPrimaryCommandBufferTask::Args taskArgs{fGpu, fTexture};
for (auto& task : fTasks) { for (auto& task : fTasks) {
task.execute(taskArgs); task.execute(taskArgs);
} }
@ -231,7 +227,7 @@ void GrVkGpuRTCommandBuffer::submit() {
GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment(); GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment();
auto currPreCmd = fPreCommandBufferTasks.begin(); auto currPreCmd = fPreCommandBufferTasks.begin();
GrVkPrimaryCommandBufferTask::Args taskArgs{fGpu, fRenderTarget, fOrigin}; GrVkPrimaryCommandBufferTask::Args taskArgs{fGpu, fRenderTarget};
for (int i = 0; i < fCommandBufferInfos.count(); ++i) { for (int i = 0; i < fCommandBufferInfos.count(); ++i) {
CommandBufferInfo& cbInfo = fCommandBufferInfos[i]; CommandBufferInfo& cbInfo = fCommandBufferInfos[i];
@ -612,7 +608,7 @@ void GrVkGpuRTCommandBuffer::inlineUpload(GrOpFlushState* state,
++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds; ++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds;
} }
void GrVkGpuRTCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void GrVkGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
const SkIPoint& dstPoint) { const SkIPoint& dstPoint) {
CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo]; CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
if (!cbInfo.fIsEmpty || LoadStoreState::kStartsWithClear == cbInfo.fLoadStoreState) { if (!cbInfo.fIsEmpty || LoadStoreState::kStartsWithClear == cbInfo.fLoadStoreState) {
@ -620,8 +616,7 @@ void GrVkGpuRTCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin, con
} }
fPreCommandBufferTasks.emplace<Copy>( fPreCommandBufferTasks.emplace<Copy>(
src, srcOrigin, srcRect, dstPoint, src, srcRect, dstPoint, LoadStoreState::kStartsWithDiscard == cbInfo.fLoadStoreState);
LoadStoreState::kStartsWithDiscard == cbInfo.fLoadStoreState);
++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds; ++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds;
if (LoadStoreState::kLoadAndStore != cbInfo.fLoadStoreState) { if (LoadStoreState::kLoadAndStore != cbInfo.fLoadStoreState) {

View File

@ -31,7 +31,6 @@ public:
struct Args { struct Args {
GrGpu* fGpu; GrGpu* fGpu;
GrSurface* fSurface; GrSurface* fSurface;
GrSurfaceOrigin fOrigin;
}; };
virtual void execute(const Args& args) = 0; virtual void execute(const Args& args) = 0;
@ -46,8 +45,7 @@ class GrVkGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer {
public: public:
GrVkGpuTextureCommandBuffer(GrVkGpu* gpu) : fGpu(gpu) {} GrVkGpuTextureCommandBuffer(GrVkGpu* gpu) : fGpu(gpu) {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
const SkIPoint& dstPoint) override;
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override; GrGpuBuffer* transferBuffer, size_t offset) override;
@ -105,8 +103,7 @@ public:
void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override; void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override;
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
const SkIPoint& dstPoint) override;
void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType, void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override; GrGpuBuffer* transferBuffer, size_t offset) override;

View File

@ -12,7 +12,6 @@
#include "src/gpu/GrContextPriv.h" #include "src/gpu/GrContextPriv.h"
#include "src/gpu/vk/GrVkCommandBuffer.h" #include "src/gpu/vk/GrVkCommandBuffer.h"
#include "src/gpu/vk/GrVkCommandPool.h" #include "src/gpu/vk/GrVkCommandPool.h"
#include "src/gpu/vk/GrVkCopyPipeline.h"
#include "src/gpu/vk/GrVkGpu.h" #include "src/gpu/vk/GrVkGpu.h"
#include "src/gpu/vk/GrVkPipeline.h" #include "src/gpu/vk/GrVkPipeline.h"
#include "src/gpu/vk/GrVkRenderTarget.h" #include "src/gpu/vk/GrVkRenderTarget.h"
@ -107,33 +106,6 @@ GrVkPipeline* GrVkResourceProvider::createPipeline(int numColorSamples,
shaderStageCount, primitiveType, compatibleRenderPass, layout, this->pipelineCache()); shaderStageCount, primitiveType, compatibleRenderPass, layout, this->pipelineCache());
} }
GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
const GrVkRenderTarget* dst,
VkPipelineShaderStageCreateInfo* shaderStageInfo,
VkPipelineLayout pipelineLayout) {
// Find or Create a compatible pipeline
GrVkCopyPipeline* pipeline = nullptr;
for (int i = 0; i < fCopyPipelines.count() && !pipeline; ++i) {
if (fCopyPipelines[i]->isCompatible(*dst->simpleRenderPass())) {
pipeline = fCopyPipelines[i];
}
}
if (!pipeline) {
pipeline = GrVkCopyPipeline::Create(fGpu, shaderStageInfo,
pipelineLayout,
dst->numColorSamples(),
*dst->simpleRenderPass(),
this->pipelineCache());
if (!pipeline) {
return nullptr;
}
fCopyPipelines.push_back(pipeline);
}
SkASSERT(pipeline);
pipeline->ref();
return pipeline;
}
// To create framebuffers, we first need to create a simple RenderPass that is // To create framebuffers, we first need to create a simple RenderPass that is
// only used for framebuffer creation. When we actually render we will create // only used for framebuffer creation. When we actually render we will create
// RenderPasses as needed that are compatible with the framebuffer. // RenderPasses as needed that are compatible with the framebuffer.
@ -404,11 +376,6 @@ void GrVkResourceProvider::destroyResources(bool deviceLost) {
taskGroup->wait(); taskGroup->wait();
} }
// Release all copy pipelines
for (int i = 0; i < fCopyPipelines.count(); ++i) {
fCopyPipelines[i]->unref(fGpu);
}
// loop over all render pass sets to make sure we destroy all the internal VkRenderPasses // loop over all render pass sets to make sure we destroy all the internal VkRenderPasses
for (int i = 0; i < fRenderPassArray.count(); ++i) { for (int i = 0; i < fRenderPassArray.count(); ++i) {
fRenderPassArray[i].releaseResources(fGpu); fRenderPassArray[i].releaseResources(fGpu);
@ -477,11 +444,6 @@ void GrVkResourceProvider::abandonResources() {
} }
fAvailableCommandPools.reset(); fAvailableCommandPools.reset();
// Abandon all copy pipelines
for (int i = 0; i < fCopyPipelines.count(); ++i) {
fCopyPipelines[i]->unrefAndAbandon();
}
// loop over all render pass sets to make sure we destroy all the internal VkRenderPasses // loop over all render pass sets to make sure we destroy all the internal VkRenderPasses
for (int i = 0; i < fRenderPassArray.count(); ++i) { for (int i = 0; i < fRenderPassArray.count(); ++i) {
fRenderPassArray[i].abandonResources(); fRenderPassArray[i].abandonResources();

View File

@ -27,7 +27,6 @@
#include <thread> #include <thread>
class GrVkCommandPool; class GrVkCommandPool;
class GrVkCopyPipeline;
class GrVkGpu; class GrVkGpu;
class GrVkPipeline; class GrVkPipeline;
class GrVkPipelineState; class GrVkPipelineState;
@ -55,10 +54,6 @@ public:
VkRenderPass compatibleRenderPass, VkRenderPass compatibleRenderPass,
VkPipelineLayout layout); VkPipelineLayout layout);
GrVkCopyPipeline* findOrCreateCopyPipeline(const GrVkRenderTarget* dst,
VkPipelineShaderStageCreateInfo*,
VkPipelineLayout);
GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle); GR_DEFINE_RESOURCE_HANDLE_CLASS(CompatibleRPHandle);
// Finds or creates a simple render pass that matches the target, increments the refcount, // Finds or creates a simple render pass that matches the target, increments the refcount,
@ -269,9 +264,6 @@ private:
// Central cache for creating pipelines // Central cache for creating pipelines
VkPipelineCache fPipelineCache; VkPipelineCache fPipelineCache;
// Cache of previously created copy pipelines
SkTArray<GrVkCopyPipeline*> fCopyPipelines;
SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray; SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray;
SkTArray<const GrVkRenderPass*> fExternalRenderPasses; SkTArray<const GrVkRenderPass*> fExternalRenderPasses;

View File

@ -112,31 +112,17 @@ sk_sp<SkImage> SkImage_GpuBase::onMakeSubset(GrRecordingContext* context,
sk_sp<GrSurfaceProxy> proxy = this->asTextureProxyRef(context); sk_sp<GrSurfaceProxy> proxy = this->asTextureProxyRef(context);
GrSurfaceDesc desc; sk_sp<GrTextureProxy> copyProxy = GrSurfaceProxy::Copy(
desc.fWidth = subset.width(); context, proxy.get(), GrMipMapped::kNo, subset, SkBackingFit::kExact,
desc.fHeight = subset.height(); proxy->isBudgeted());
desc.fConfig = proxy->config();
GrBackendFormat format = proxy->backendFormat().makeTexture2D(); if (!copyProxy) {
if (!format.isValid()) {
return nullptr;
}
// TODO: Should this inherit our proxy's budgeted status?
sk_sp<GrSurfaceContext> sContext(context->priv().makeDeferredSurfaceContext(
format, desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact,
proxy->isBudgeted()));
if (!sContext) {
return nullptr;
}
if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
return nullptr; return nullptr;
} }
// MDB: this call is okay bc we know 'sContext' was kExact // MDB: this call is okay bc we know 'sContext' was kExact
return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(), return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
sContext->asTextureProxyRef(), this->refColorSpace()); std::move(copyProxy), this->refColorSpace());
} }
static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) { static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {

View File

@ -19,6 +19,7 @@
#include "src/core/SkUtils.h" #include "src/core/SkUtils.h"
#include "src/gpu/GrCaps.h" #include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextPriv.h" #include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrSurfaceContext.h" #include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"
#include "tests/Test.h" #include "tests/Test.h"
@ -106,7 +107,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
sk_sp<GrSurfaceContext> dstContext = sk_sp<GrSurfaceContext> dstContext =
context->priv().makeWrappedSurfaceContext(std::move(dst)); context->priv().makeWrappedSurfaceContext(std::move(dst));
bool result = dstContext->copy(src.get(), srcRect, dstPoint); bool result = false;
if (sOrigin == dOrigin) {
result = dstContext->testCopy(src.get(), srcRect, dstPoint);
} else if (dRenderable == GrRenderable::kYes) {
SkASSERT(dstContext->asRenderTargetContext());
result = dstContext->asRenderTargetContext()->blitTexture(
src.get(), srcRect, dstPoint);
}
bool expectedResult = true; bool expectedResult = true;
SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft, SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft,
@ -132,6 +140,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
!copiedDstRect.intersect(SkIRect::MakeWH(kW, kH))) { !copiedDstRect.intersect(SkIRect::MakeWH(kW, kH))) {
expectedResult = false; expectedResult = false;
} }
if (sOrigin != dOrigin && dRenderable == GrRenderable::kNo) {
expectedResult = false;
}
// To make the copied src rect correct we would apply any dst // To make the copied src rect correct we would apply any dst
// clipping back to the src rect, but we don't use it again so // clipping back to the src rect, but we don't use it again so
// don't bother. // don't bother.

View File

@ -194,7 +194,7 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(EGLImageTest, reporter, ctxInfo) {
// Only test RT-config // Only test RT-config
// TODO: why do we always need to draw to copy from an external texture? // TODO: why do we always need to draw to copy from an external texture?
test_copy_from_surface(reporter, context0, surfaceContext->asSurfaceProxy(), test_copy_from_surface(reporter, context0, surfaceContext->asSurfaceProxy(),
pixels.get(), true, "EGLImageTest-copy"); pixels.get(), "EGLImageTest-copy");
cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image); cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
} }

View File

@ -323,13 +323,13 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
SkImage::MakeFromRaster(write, nullptr, nullptr), kNone_GrSurfaceFlags, 1, SkImage::MakeFromRaster(write, nullptr, nullptr), kNone_GrSurfaceFlags, 1,
SkBudgeted::kYes, SkBackingFit::kExact); SkBudgeted::kYes, SkBackingFit::kExact);
REPORTER_ASSERT(reporter, copySrc); REPORTER_ASSERT(reporter, copySrc);
auto copyResult = surfContext->copy(copySrc.get()); auto copyResult = surfContext->testCopy(copySrc.get());
REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType)); REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType));
// Try the low level copy. // Try the low level copy.
context->flush(); context->flush();
auto gpuCopyResult = context->priv().getGpu()->copySurface( auto gpuCopyResult = context->priv().getGpu()->copySurface(
proxy->peekTexture(), kTopLeft_GrSurfaceOrigin, copySrc->peekTexture(), proxy->peekTexture(), copySrc->peekTexture(), SkIRect::MakeWH(kSize, kSize),
kTopLeft_GrSurfaceOrigin, SkIRect::MakeWH(kSize, kSize), {0, 0}); {0, 0});
REPORTER_ASSERT(reporter, gpuCopyResult == (ioType == kRW_GrIOType)); REPORTER_ASSERT(reporter, gpuCopyResult == (ioType == kRW_GrIOType));
// Mip regen should not work with a read only texture. // Mip regen should not work with a read only texture.
@ -351,9 +351,12 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
} }
} }
static const int kSurfSize = 10;
static sk_sp<GrTexture> make_wrapped_texture(GrContext* context, GrRenderable renderable) { static sk_sp<GrTexture> make_wrapped_texture(GrContext* context, GrRenderable renderable) {
auto backendTexture = context->createBackendTexture( auto backendTexture = context->createBackendTexture(
10, 10, kRGBA_8888_SkColorType, SkColors::kTransparent, GrMipMapped::kNo, renderable); kSurfSize, kSurfSize, kRGBA_8888_SkColorType, SkColors::kTransparent, GrMipMapped::kNo,
renderable);
sk_sp<GrTexture> texture; sk_sp<GrTexture> texture;
if (GrRenderable::kYes == renderable) { if (GrRenderable::kYes == renderable) {
texture = context->priv().resourceProvider()->wrapRenderableBackendTexture( texture = context->priv().resourceProvider()->wrapRenderableBackendTexture(
@ -380,7 +383,7 @@ static sk_sp<GrTexture> make_wrapped_texture(GrContext* context, GrRenderable re
static sk_sp<GrTexture> make_normal_texture(GrContext* context, GrRenderable renderable) { static sk_sp<GrTexture> make_normal_texture(GrContext* context, GrRenderable renderable) {
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fConfig = kRGBA_8888_GrPixelConfig; desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fWidth = desc.fHeight = 10; desc.fWidth = desc.fHeight = kSurfSize;
desc.fFlags = GrRenderable::kYes == renderable ? kRenderTarget_GrSurfaceFlag desc.fFlags = GrRenderable::kYes == renderable ? kRenderTarget_GrSurfaceFlag
: kNone_GrSurfaceFlags; : kNone_GrSurfaceFlags;
return context->priv().resourceProvider()->createTexture( return context->priv().resourceProvider()->createTexture(
@ -725,14 +728,14 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TextureIdleStateTest, reporter, contextInfo) {
// Insert a copy from idleTexture to another texture so that we have some queued IO on // Insert a copy from idleTexture to another texture so that we have some queued IO on
// idleTexture. // idleTexture.
auto proxy = context->priv().proxyProvider()->testingOnly_createWrapped( SkImageInfo info = SkImageInfo::Make(kSurfSize, kSurfSize, kRGBA_8888_SkColorType,
std::move(idleTexture), kTopLeft_GrSurfaceOrigin); kPremul_SkAlphaType);
SkImageInfo info = SkImageInfo::Make(proxy->width(), proxy->height(),
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
auto rt = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr); auto rt = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr);
auto rtc = rt->getCanvas()->internal_private_accessTopLayerRenderTargetContext(); auto rtc = rt->getCanvas()->internal_private_accessTopLayerRenderTargetContext();
auto proxy = context->priv().proxyProvider()->testingOnly_createWrapped(
std::move(idleTexture), rtc->asSurfaceProxy()->origin());
context->flush(); context->flush();
rtc->copy(proxy.get()); SkAssertResult(rtc->testCopy(proxy.get()));
proxy.reset(); proxy.reset();
REPORTER_ASSERT(reporter, flags == 0); REPORTER_ASSERT(reporter, flags == 0);

View File

@ -13,9 +13,9 @@
#include "src/gpu/GrContextPriv.h" #include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrSurfaceContextPriv.h"
#include "src/gpu/GrSurfacePriv.h" #include "src/gpu/GrSurfacePriv.h"
#include "src/gpu/GrTexturePriv.h" #include "src/gpu/GrTexturePriv.h"
#include "src/gpu/GrTextureProxyPriv.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"
#include "src/gpu/gl/GrGLGpu.h" #include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLUtil.h" #include "src/gpu/gl/GrGLUtil.h"
@ -93,12 +93,38 @@ static void test_clear(skiatest::Reporter* reporter, GrSurfaceContext* rectConte
} }
} }
static void test_copy_to_surface(skiatest::Reporter* reporter,
GrContext* context,
GrSurfaceContext* dstContext,
const char* testName) {
int pixelCnt = dstContext->width() * dstContext->height();
SkAutoTMalloc<uint32_t> pixels(pixelCnt);
for (int y = 0; y < dstContext->width(); ++y) {
for (int x = 0; x < dstContext->height(); ++x) {
pixels.get()[y * dstContext->width() + x] =
SkColorToPremulGrColor(SkColorSetARGB(2*y, y, x, x * y));
}
}
for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
auto origin = dstContext->asSurfaceProxy()->origin();
auto src = sk_gpu_test::MakeTextureProxyFromData(
context, renderable, dstContext->width(),
dstContext->height(), kRGBA_8888_SkColorType, origin, pixels.get(), 0);
// If this assert ever fails we can add a fallback to do copy as draw, but until then we can
// be more restrictive.
SkAssertResult(dstContext->testCopy(src.get()));
test_read_pixels(reporter, dstContext, pixels.get(), testName);
}
}
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) { DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext(); GrContext* context = ctxInfo.grContext();
GrProxyProvider* proxyProvider = context->priv().proxyProvider(); GrProxyProvider* proxyProvider = context->priv().proxyProvider();
sk_gpu_test::GLTestContext* glContext = ctxInfo.glContext(); sk_gpu_test::GLTestContext* glContext = ctxInfo.glContext();
static const int kWidth = 13; static const int kWidth = 16;
static const int kHeight = 13; static const int kHeight = 16;
GrColor pixels[kWidth * kHeight]; GrColor pixels[kWidth * kHeight];
for (int y = 0; y < kHeight; ++y) { for (int y = 0; y < kHeight; ++y) {
@ -159,7 +185,7 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) {
// Test copy to both a texture and RT // Test copy to both a texture and RT
test_copy_from_surface(reporter, context, rectProxy.get(), refPixels, test_copy_from_surface(reporter, context, rectProxy.get(), refPixels,
false, "RectangleTexture-copy-from"); "RectangleTexture-copy-from");
sk_sp<GrSurfaceContext> rectContext = context->priv().makeWrappedSurfaceContext( sk_sp<GrSurfaceContext> rectContext = context->priv().makeWrappedSurfaceContext(
std::move(rectProxy)); std::move(rectProxy));

View File

@ -13,11 +13,11 @@
#include "include/utils/SkBase64.h" #include "include/utils/SkBase64.h"
#include "src/core/SkUtils.h" #include "src/core/SkUtils.h"
#include "src/gpu/GrContextPriv.h" #include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrGpu.h" #include "src/gpu/GrGpu.h"
#include "src/gpu/GrSurfaceContext.h" #include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrSurfaceContextPriv.h" #include "src/gpu/GrTextureContext.h"
#include "src/gpu/SkGr.h" #include "src/gpu/SkGr.h"
#include "tools/gpu/ProxyUtils.h"
void test_read_pixels(skiatest::Reporter* reporter, void test_read_pixels(skiatest::Reporter* reporter,
GrSurfaceContext* srcContext, uint32_t expectedPixelValues[], GrSurfaceContext* srcContext, uint32_t expectedPixelValues[],
@ -74,51 +74,16 @@ void test_write_pixels(skiatest::Reporter* reporter,
void test_copy_from_surface(skiatest::Reporter* reporter, GrContext* context, void test_copy_from_surface(skiatest::Reporter* reporter, GrContext* context,
GrSurfaceProxy* proxy, uint32_t expectedPixelValues[], GrSurfaceProxy* proxy, uint32_t expectedPixelValues[],
bool onlyTestRTConfig, const char* testName) { const char* testName) {
GrSurfaceDesc copyDstDesc; sk_sp<GrTextureProxy> dstProxy = GrSurfaceProxy::Copy(context, proxy, GrMipMapped::kNo,
copyDstDesc.fWidth = proxy->width(); SkBackingFit::kExact, SkBudgeted::kYes);
copyDstDesc.fHeight = proxy->height(); SkASSERT(dstProxy);
copyDstDesc.fConfig = kRGBA_8888_GrPixelConfig;
for (auto flags : { kNone_GrSurfaceFlags, kRenderTarget_GrSurfaceFlag }) { sk_sp<GrSurfaceContext> dstContext =
if (kNone_GrSurfaceFlags == flags && onlyTestRTConfig) { context->priv().makeWrappedSurfaceContext(std::move(dstProxy));
continue; SkASSERT(dstContext.get());
}
copyDstDesc.fFlags = flags; test_read_pixels(reporter, dstContext.get(), expectedPixelValues, testName);
auto origin = (kNone_GrSurfaceFlags == flags) ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin;
sk_sp<GrSurfaceContext> dstContext(
GrSurfaceProxy::TestCopy(context, copyDstDesc, origin, proxy));
test_read_pixels(reporter, dstContext.get(), expectedPixelValues, testName);
}
}
void test_copy_to_surface(skiatest::Reporter* reporter,
GrContext* context,
GrSurfaceContext* dstContext,
const char* testName) {
int pixelCnt = dstContext->width() * dstContext->height();
SkAutoTMalloc<uint32_t> pixels(pixelCnt);
for (int y = 0; y < dstContext->width(); ++y) {
for (int x = 0; x < dstContext->height(); ++x) {
pixels.get()[y * dstContext->width() + x] =
SkColorToPremulGrColor(SkColorSetARGB(2*y, y, x, x * y));
}
}
for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
for (auto origin : {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
auto src = sk_gpu_test::MakeTextureProxyFromData(
context, renderable, dstContext->width(),
dstContext->height(), kRGBA_8888_SkColorType, origin, pixels.get(), 0);
dstContext->copy(src.get());
test_read_pixels(reporter, dstContext, pixels.get(), testName);
}
}
} }
void fill_pixel_data(int width, int height, GrColor* data) { void fill_pixel_data(int width, int height, GrColor* data) {

View File

@ -26,11 +26,7 @@ void test_write_pixels(skiatest::Reporter*,
// texture-backed and rendertarget-backed). // texture-backed and rendertarget-backed).
void test_copy_from_surface(skiatest::Reporter*, GrContext*, void test_copy_from_surface(skiatest::Reporter*, GrContext*,
GrSurfaceProxy* proxy, uint32_t expectedPixelValues[], GrSurfaceProxy* proxy, uint32_t expectedPixelValues[],
bool onlyTestRTConfig, const char* testName); const char* testName);
// Ensure that RGBA 8888 pixels can be copied into 'dstContext'
void test_copy_to_surface(skiatest::Reporter*, GrContext*,
GrSurfaceContext* dstContext, const char* testName);
// Fills data with a red-green gradient // Fills data with a red-green gradient
void fill_pixel_data(int width, int height, GrColor* data); void fill_pixel_data(int width, int height, GrColor* data);

View File

@ -1,190 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This is a GPU-backend specific test. It relies on static intializers to work
#include "include/core/SkTypes.h"
#if defined(SK_VULKAN)
#include "include/gpu/vk/GrVkVulkan.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrTexture.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/vk/GrVkCopyPipeline.h"
#include "src/gpu/vk/GrVkGpu.h"
#include "src/gpu/vk/GrVkRenderTarget.h"
#include "src/gpu/vk/GrVkUtil.h"
#include "tests/Test.h"
#include "tools/gpu/GrContextFactory.h"
using sk_gpu_test::GrContextFactory;
class TestVkCopyProgram {
public:
TestVkCopyProgram()
: fVertShaderModule(VK_NULL_HANDLE)
, fFragShaderModule(VK_NULL_HANDLE)
, fPipelineLayout(VK_NULL_HANDLE) {}
void test(GrVkGpu* gpu, skiatest::Reporter* reporter) {
const char vertShaderText[] =
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
"half4 uPosXform;"
"half4 uTexCoordXform;"
"};"
"layout(location = 0) in float2 inPosition;"
"layout(location = 1) out half2 vTexCoord;"
"// Copy Program VS\n"
"void main() {"
"vTexCoord = half2(inPosition * uTexCoordXform.xy + uTexCoordXform.zw);"
"sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
"sk_Position.zw = half2(0, 1);"
"}";
const char fragShaderText[] =
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
"layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
"layout(location = 1) in half2 vTexCoord;"
"// Copy Program FS\n"
"void main() {"
"sk_FragColor = texture(uTextureSampler, vTexCoord);"
"}";
SkSL::Program::Settings settings;
SkSL::String spirv;
SkSL::Program::Inputs inputs;
if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT,
&fVertShaderModule, &fShaderStageInfo[0], settings,
&spirv, &inputs)) {
this->destroyResources(gpu);
REPORTER_ASSERT(reporter, false);
return;
}
SkASSERT(inputs.isEmpty());
if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT,
&fFragShaderModule, &fShaderStageInfo[1], settings,
&spirv, &inputs)) {
this->destroyResources(gpu);
REPORTER_ASSERT(reporter, false);
return;
}
VkDescriptorSetLayout dsLayout[2];
GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
uint32_t samplerVisibility = kFragment_GrShaderFlag;
SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1);
resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
visibilityArray, &fSamplerDSHandle);
dsLayout[GrVkUniformHandler::kSamplerDescSet] =
resourceProvider.getSamplerDSLayout(fSamplerDSHandle);
// Create the VkPipelineLayout
VkPipelineLayoutCreateInfo layoutCreateInfo;
memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layoutCreateInfo.pNext = 0;
layoutCreateInfo.flags = 0;
layoutCreateInfo.setLayoutCount = 2;
layoutCreateInfo.pSetLayouts = dsLayout;
layoutCreateInfo.pushConstantRangeCount = 0;
layoutCreateInfo.pPushConstantRanges = nullptr;
VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
&layoutCreateInfo,
nullptr,
&fPipelineLayout));
if (err) {
this->destroyResources(gpu);
REPORTER_ASSERT(reporter, false);
return;
}
GrSurfaceDesc surfDesc;
surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
surfDesc.fWidth = 16;
surfDesc.fHeight = 16;
surfDesc.fConfig = kRGBA_8888_GrPixelConfig;
surfDesc.fSampleCnt = 1;
sk_sp<GrTexture> tex = gpu->createTexture(surfDesc, SkBudgeted::kNo);
if (!tex) {
this->destroyResources(gpu);
REPORTER_ASSERT(reporter, tex.get());
return;
}
GrRenderTarget* rt = tex->asRenderTarget();
REPORTER_ASSERT(reporter, rt);
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
GrVkCopyPipeline* copyPipeline = GrVkCopyPipeline::Create(gpu,
fShaderStageInfo,
fPipelineLayout,
1,
*vkRT->simpleRenderPass(),
VK_NULL_HANDLE);
REPORTER_ASSERT(reporter, copyPipeline);
if (copyPipeline) {
copyPipeline->unref(gpu);
}
this->destroyResources(gpu);
}
void destroyResources(GrVkGpu* gpu) {
if (VK_NULL_HANDLE != fVertShaderModule) {
GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule,
nullptr));
fVertShaderModule = VK_NULL_HANDLE;
}
if (VK_NULL_HANDLE != fFragShaderModule) {
GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule,
nullptr));
fFragShaderModule = VK_NULL_HANDLE;
}
if (VK_NULL_HANDLE != fPipelineLayout) {
GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout,
nullptr));
fPipelineLayout = VK_NULL_HANDLE;
}
}
VkShaderModule fVertShaderModule;
VkShaderModule fFragShaderModule;
VkPipelineShaderStageCreateInfo fShaderStageInfo[2];
GrVkDescriptorSetManager::Handle fSamplerDSHandle;
VkPipelineLayout fPipelineLayout;
};
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkMakeCopyPipelineTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
GrVkGpu* gpu = static_cast<GrVkGpu*>(context->priv().getGpu());
TestVkCopyProgram copyProgram;
copyProgram.test(gpu, reporter);
}
#endif