Reland "Reland "Remove support for copyAsDraw in gpu copySurface.""
This reverts commit4c6f9b7670
. 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 commit84ea04949c
. > > Reason for revert: nexus 7 and android one broken > > Original change's description: > > Reland "Remove support for copyAsDraw in gpu copySurface." > > > > This reverts commitc5167c053b
. > > > > Reason for revert: fixed > > > > Original change's description: > > > Revert "Remove support for copyAsDraw in gpu copySurface." > > > > > > This reverts commit6565506463
. > > > > > > 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:
parent
33a6f7c0a8
commit
46cfbc67f6
@ -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:
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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;)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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()) {
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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; }
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 {}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -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);
|
|
||||||
}
|
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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&,
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
|
|
@ -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(©Region, 0, sizeof(VkImageCopy));
|
memset(©Region, 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;
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user