[graphite] Add Image::Copy to handle both blit and draw copies
Bug: b/333909822
Change-Id: I5dbc33aa9b72b6509d9cd503eaf4f7a8dcde5669
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/838236
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/graphite/Device.cpp b/src/gpu/graphite/Device.cpp
index 21e0b4a..34ae40c 100644
--- a/src/gpu/graphite/Device.cpp
+++ b/src/gpu/graphite/Device.cpp
@@ -40,7 +40,6 @@
#include "src/gpu/graphite/geom/IntersectionTree.h"
#include "src/gpu/graphite/geom/Shape.h"
#include "src/gpu/graphite/geom/Transform_graphite.h"
-#include "src/gpu/graphite/task/CopyTask.h"
#include "src/gpu/graphite/text/TextAtlasManager.h"
#include "include/core/SkColorSpace.h"
@@ -423,73 +422,7 @@
colorInfo.colorType(), this->target()->textureInfo());
srcView = {sk_ref_sp(this->target()), readSwizzle};
}
- TextureProxyView copiedView = TextureProxyView::Copy(fRecorder,
- colorInfo,
- srcView,
- subset,
- budgeted,
- mipmapped,
- backingFit);
- if (!copiedView) {
- // The surface didn't support read pixels, so copy-as-draw using the image view
- sk_sp<Image> sampleableSurface = Image::WrapDevice(sk_ref_sp(this));
- if (sampleableSurface) {
- return sampleableSurface->copyImage(fRecorder, subset, budgeted, mipmapped, backingFit);
- }
- // Cannot be copied by blit nor by a draw, so cannot be done.
- return nullptr;
- }
-
- return sk_make_sp<Image>(std::move(copiedView), colorInfo);
-}
-
-TextureProxyView TextureProxyView::Copy(Recorder* recorder,
- const SkColorInfo& srcColorInfo,
- const TextureProxyView& srcView,
- SkIRect srcRect,
- Budgeted budgeted,
- Mipmapped mipmapped,
- SkBackingFit backingFit) {
- SkASSERT(!(mipmapped == Mipmapped::kYes && backingFit == SkBackingFit::kApprox));
-
- SkASSERT(srcView.proxy()->isFullyLazy() ||
- SkIRect::MakeSize(srcView.proxy()->dimensions()).contains(srcRect));
-
- if (!recorder->priv().caps()->supportsReadPixels(srcView.proxy()->textureInfo())) {
- // Caller is responsible for copy-as-draw fallbacks
- return {};
- }
-
- skgpu::graphite::TextureInfo textureInfo =
- recorder->priv().caps()->getTextureInfoForSampledCopy(srcView.proxy()->textureInfo(),
- mipmapped);
-
- sk_sp<TextureProxy> dest = TextureProxy::Make(
- recorder->priv().caps(),
- backingFit == SkBackingFit::kApprox ? GetApproxSize(srcRect.size()) : srcRect.size(),
- textureInfo,
- budgeted);
- if (!dest) {
- return {};
- }
-
- sk_sp<CopyTextureToTextureTask> copyTask = CopyTextureToTextureTask::Make(srcView.refProxy(),
- srcRect,
- dest,
- {0, 0});
- if (!copyTask) {
- return {};
- }
-
- recorder->priv().add(std::move(copyTask));
-
- if (mipmapped == Mipmapped::kYes) {
- if (!GenerateMipmaps(recorder, dest, srcColorInfo)) {
- SKGPU_LOG_W("TextureProxyView::Copy: Failed to generate mipmaps");
- }
- }
-
- return { std::move(dest), srcView.swizzle() };
+ return Image::Copy(fRecorder, srcView, colorInfo, subset, budgeted, mipmapped, backingFit);
}
bool Device::onReadPixels(const SkPixmap& pm, int srcX, int srcY) {
diff --git a/src/gpu/graphite/Image_Graphite.cpp b/src/gpu/graphite/Image_Graphite.cpp
index 6437a89..4576e22 100644
--- a/src/gpu/graphite/Image_Graphite.cpp
+++ b/src/gpu/graphite/Image_Graphite.cpp
@@ -23,6 +23,8 @@
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/Texture.h"
+#include "src/gpu/graphite/TextureUtils.h"
+#include "src/gpu/graphite/task/CopyTask.h"
#if defined(GRAPHITE_TEST_UTILS)
#include "include/gpu/graphite/Context.h"
@@ -53,6 +55,62 @@
return image;
}
+sk_sp<Image> Image::Copy(Recorder* recorder,
+ const TextureProxyView& srcView,
+ const SkColorInfo& srcColorInfo,
+ const SkIRect& subset,
+ Budgeted budgeted,
+ Mipmapped mipmapped,
+ SkBackingFit backingFit) {
+ SkASSERT(!(mipmapped == Mipmapped::kYes && backingFit == SkBackingFit::kApprox));
+ if (!srcView) {
+ return nullptr;
+ }
+
+ SkASSERT(srcView.proxy()->isFullyLazy() ||
+ SkIRect::MakeSize(srcView.proxy()->dimensions()).contains(subset));
+
+ if (!recorder->priv().caps()->supportsReadPixels(srcView.proxy()->textureInfo())) {
+ if (!recorder->priv().caps()->isTexturable(srcView.proxy()->textureInfo())) {
+ // The texture is not blittable nor texturable so copying cannot be done.
+ return nullptr;
+ }
+ // Copy-as-draw
+ sk_sp<Image> srcImage(new Image(srcView, srcColorInfo));
+ return CopyAsDraw(recorder, srcImage.get(), subset, budgeted, mipmapped, backingFit);
+ }
+
+
+ skgpu::graphite::TextureInfo textureInfo =
+ recorder->priv().caps()->getTextureInfoForSampledCopy(srcView.proxy()->textureInfo(),
+ mipmapped);
+
+ sk_sp<TextureProxy> dst = TextureProxy::Make(
+ recorder->priv().caps(),
+ backingFit == SkBackingFit::kApprox ? GetApproxSize(subset.size()) : subset.size(),
+ textureInfo,
+ budgeted);
+ if (!dst) {
+ return nullptr;
+ }
+
+ auto copyTask = CopyTextureToTextureTask::Make(srcView.refProxy(), subset, dst, {0, 0});
+ if (!copyTask) {
+ return nullptr;
+ }
+
+ recorder->priv().add(std::move(copyTask));
+
+ if (mipmapped == Mipmapped::kYes) {
+ if (!GenerateMipmaps(recorder, dst, srcColorInfo)) {
+ SKGPU_LOG_W("Image::Copy failed to generate mipmaps");
+ return nullptr;
+ }
+ }
+
+ return sk_sp<Image>(new Image({std::move(dst), srcView.swizzle()}, srcColorInfo));
+}
+
size_t Image::textureSize() const {
if (!fTextureProxyView.proxy()) {
return 0;
@@ -104,30 +162,9 @@
Budgeted budgeted,
Mipmapped mipmapped,
SkBackingFit backingFit) const {
- SkASSERT(!(mipmapped == Mipmapped::kYes && backingFit == SkBackingFit::kApprox));
- const TextureProxyView& srcView = this->textureProxyView();
- if (!srcView) {
- return nullptr;
- }
-
- // Attempt copying as a blit first.
- const SkColorInfo& colorInfo = this->imageInfo().colorInfo();
this->notifyInUse(recorder);
- TextureProxyView copiedView = TextureProxyView::Copy(recorder,
- colorInfo,
- srcView,
- subset,
- budgeted,
- mipmapped,
- backingFit);
- if (copiedView) {
- return sk_make_sp<Image>(std::move(copiedView), colorInfo);
- }
-
- // Perform the copy as a draw; since the proxy has been wrapped in an Image, it should be
- // texturable.
- SkASSERT(recorder->priv().caps()->isTexturable(srcView.proxy()->textureInfo()));
- return CopyAsDraw(recorder, this, subset, budgeted, mipmapped, backingFit);
+ return Image::Copy(recorder, fTextureProxyView, this->imageInfo().colorInfo(),
+ subset, budgeted, mipmapped, backingFit);
}
sk_sp<SkImage> Image::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
diff --git a/src/gpu/graphite/Image_Graphite.h b/src/gpu/graphite/Image_Graphite.h
index 66da222..7f7e075 100644
--- a/src/gpu/graphite/Image_Graphite.h
+++ b/src/gpu/graphite/Image_Graphite.h
@@ -32,6 +32,16 @@
// pending tasks when the Image is used in a draw to another canvas.
static sk_sp<Image> WrapDevice(sk_sp<Device> device);
+ // Create an Image by copying the provided texture proxy view into a new texturable proxy.
+ // The source texture does not have to be texturable if it is blittable.
+ static sk_sp<Image> Copy(Recorder*,
+ const TextureProxyView& srcView,
+ const SkColorInfo&,
+ const SkIRect& subset,
+ Budgeted,
+ Mipmapped,
+ SkBackingFit);
+
const TextureProxyView& textureProxyView() const { return fTextureProxyView; }
// Always copy this image, even if 'subset' and mipmapping match this image exactly.
diff --git a/src/gpu/graphite/TextureProxyView.h b/src/gpu/graphite/TextureProxyView.h
index 96f28a3..5addb14 100644
--- a/src/gpu/graphite/TextureProxyView.h
+++ b/src/gpu/graphite/TextureProxyView.h
@@ -89,17 +89,6 @@
return std::move(fProxy);
}
- // This Copy does not perform any copy-as-draw fallbacks; if 'srcView' does not support reading
- // pixels, then this will return an empty proxy view. On success, the proxy view will be
- // sampleable.
- static TextureProxyView Copy(Recorder*,
- const SkColorInfo& srcColorInfo,
- const TextureProxyView& srcView,
- SkIRect srcRect,
- Budgeted,
- Mipmapped,
- SkBackingFit);
-
private:
sk_sp<TextureProxy> fProxy;
Swizzle fSwizzle;