aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Ludwig <michaelludwig@google.com>2023-12-11 09:33:52 -0500
committerSkCQ <skcq-be@skia-corp.google.com.iam.gserviceaccount.com>2023-12-12 21:21:43 +0000
commite7e8a521abc8803b1f54642997eb592485627081 (patch)
treebc0483fb1b42d453889a7dca42fa6e05406b1cfd
parent49e32eb178a7b6ed5c598182329bf4f21e51157d (diff)
downloadskia-e7e8a521abc8803b1f54642997eb592485627081.tar.gz
[skif] Add non-strict asShader() to SkSpecialImage
Moves the replicate definitions of onAsShader() for Graphite and Ganesh to the base class. The raster special image overrides it so that it can subset the SkBitmap instead of going through SkImageShader::MakeSubset(), which does not support bitmaps yet. Adds a non-strict flag variant of asShader(), the variant that does not take a tilemode. Right now, the only uses of asShader() are the full parameter list, so the very simple signature is removed. Under the assumption that the coordinates will not be outside of the subset coords, a tilemode is unnecessary, hence the different signature. I could be easily convinced to give it a different name if there are any suggestions. Bug: b/315351386 Change-Id: I61ae7428a68fa3d76b23a4082fd65797102d03d5 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/787918 Reviewed-by: James Godfrey-Kittle <jamesgk@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
-rw-r--r--src/core/SkSpecialImage.cpp62
-rw-r--r--src/core/SkSpecialImage.h12
-rw-r--r--src/gpu/ganesh/image/SkSpecialImage_Ganesh.cpp23
-rw-r--r--src/gpu/graphite/SpecialImage_Graphite.cpp18
4 files changed, 58 insertions, 57 deletions
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index bedb563d83..1a61e27035 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -12,11 +12,13 @@
#include "include/core/SkColorType.h"
#include "include/core/SkImage.h"
#include "include/core/SkMatrix.h"
+#include "include/core/SkPoint.h"
#include "include/core/SkShader.h"
#include "include/core/SkTileMode.h"
#include "include/private/base/SkAssert.h"
#include "src/core/SkNextID.h"
#include "src/image/SkImage_Base.h"
+#include "src/shaders/SkImageShader.h"
// Currently, the raster imagefilters can only handle certain imageinfos. Call this to know if
// a given info is supported.
@@ -49,16 +51,40 @@ void SkSpecialImage::draw(SkCanvas* canvas,
sk_sp<SkShader> SkSpecialImage::asShader(SkTileMode tileMode,
const SkSamplingOptions& sampling,
const SkMatrix& lm) const {
- return this->onAsShader(tileMode, sampling, lm);
+ return this->onAsShader(tileMode, sampling, lm, /*strict=*/true);
}
-sk_sp<SkShader> SkSpecialImage::asShader(const SkSamplingOptions& sampling) const {
- return this->asShader(sampling, SkMatrix::I());
+sk_sp<SkShader> SkSpecialImage::asShaderFast(const SkSamplingOptions& sampling,
+ const SkMatrix& lm) const {
+ // Since this should only be used when safely sampling within the subset, the tile mode is
+ // irrelevant, but kClamp is a good default.
+ return this->onAsShader(SkTileMode::kClamp, sampling, lm, /*strict=*/false);
}
-sk_sp<SkShader> SkSpecialImage::asShader(const SkSamplingOptions& sampling,
- const SkMatrix& lm) const {
- return this->asShader(SkTileMode::kClamp, sampling, lm);
+// TODO(skbug.com/12784): Once bitmap images work with SkImageShader::MakeSubset(), this does not
+// need to be virtual anymore.
+sk_sp<SkShader> SkSpecialImage::onAsShader(SkTileMode tileMode,
+ const SkSamplingOptions& sampling,
+ const SkMatrix& lm,
+ bool strict) const {
+ // The special image's logical (0,0) is at its subset's topLeft() so we need to account for
+ // that in the local matrix used when sampling.
+ SkMatrix subsetOrigin = SkMatrix::Translate(-this->subset().topLeft());
+ subsetOrigin.postConcat(lm);
+
+ if (strict) {
+ // However, we don't need to modify the subset itself since that is defined with respect
+ // to the base image, and the local matrix is applied before any tiling/clamping.
+ const SkRect subset = SkRect::Make(this->subset());
+
+ // asImage() w/o a subset makes no copy; create the SkImageShader directly to remember
+ // the subset used to access the image.
+ return SkImageShader::MakeSubset(
+ this->asImage(), subset, tileMode, tileMode, sampling, &subsetOrigin);
+ } else {
+ // Ignore 'subset' other than its origin translation applied to the local matrix.
+ return this->asImage()->makeShader(tileMode, tileMode, sampling, subsetOrigin);
+ }
}
class SkSpecialImage_Raster final : public SkSpecialImage {
@@ -85,14 +111,24 @@ public:
sk_sp<SkShader> onAsShader(SkTileMode tileMode,
const SkSamplingOptions& sampling,
- const SkMatrix& lm) const override {
- // TODO(skbug.com/12784): SkImage::makeShader() doesn't support a subset yet, but SkBitmap
- // supports subset views so create the shader from the subset bitmap instead of fBitmap.
- SkBitmap subsetBM;
- if (!this->getROPixels(&subsetBM)) {
- return nullptr;
+ const SkMatrix& lm,
+ bool strict) const override {
+ if (strict) {
+ // TODO(skbug.com/12784): SkImage::makeShader() doesn't support a subset yet, but
+ // SkBitmap supports subset views so create the shader from the subset bitmap instead of
+ // fBitmap.
+ SkBitmap subsetBM;
+ if (!this->getROPixels(&subsetBM)) {
+ return nullptr;
+ }
+ return subsetBM.makeShader(tileMode, tileMode, sampling, lm);
+ } else {
+ // The special image's logical (0,0) is at its subset's topLeft() so we need to
+ // account for that in the local matrix used when sampling.
+ SkMatrix subsetOrigin = SkMatrix::Translate(-this->subset().topLeft());
+ subsetOrigin.postConcat(lm);
+ return fBitmap.makeShader(tileMode, tileMode, sampling, subsetOrigin);
}
- return subsetBM.asImage()->makeShader(tileMode, tileMode, sampling, lm);
}
private:
diff --git a/src/core/SkSpecialImage.h b/src/core/SkSpecialImage.h
index 89c82bbb91..6a08f74236 100644
--- a/src/core/SkSpecialImage.h
+++ b/src/core/SkSpecialImage.h
@@ -104,8 +104,12 @@ public:
* any sample that falls outside its internal subset.
*/
sk_sp<SkShader> asShader(SkTileMode, const SkSamplingOptions&, const SkMatrix& lm) const;
- sk_sp<SkShader> asShader(const SkSamplingOptions& sampling) const;
- sk_sp<SkShader> asShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
+ /**
+ * Create an SkShader that samples the contents of this special image, assuming that the
+ * coords it's evaluated at will not access pixels beyond its subset
+ * (i.e., non-strict sampling).
+ */
+ sk_sp<SkShader> asShaderFast(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
/**
* If the SpecialImage is backed by a gpu texture, return true.
@@ -128,9 +132,11 @@ protected:
// from the content rect by the non-virtual makeSubset().
virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
+ // The default implementation calls `asImage()` or `SkImageShader::MakeSubset` based on `strict`
virtual sk_sp<SkShader> onAsShader(SkTileMode,
const SkSamplingOptions&,
- const SkMatrix&) const = 0;
+ const SkMatrix&,
+ bool strict) const;
private:
const SkIRect fSubset;
diff --git a/src/gpu/ganesh/image/SkSpecialImage_Ganesh.cpp b/src/gpu/ganesh/image/SkSpecialImage_Ganesh.cpp
index 2b61fe2510..bc7babe496 100644
--- a/src/gpu/ganesh/image/SkSpecialImage_Ganesh.cpp
+++ b/src/gpu/ganesh/image/SkSpecialImage_Ganesh.cpp
@@ -10,12 +10,10 @@
#include "include/core/SkColorSpace.h" // IWYU pragma: keep
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
-#include "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/private/base/SkAssert.h"
-#include "include/private/base/SkPoint_impl.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkSpecialImage.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
@@ -23,15 +21,11 @@
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/image/GrImageUtils.h"
#include "src/gpu/ganesh/image/SkImage_Ganesh.h"
-#include "src/shaders/SkImageShader.h"
#include <cstddef>
#include <utility>
-class SkShader;
-struct SkSamplingOptions;
enum SkColorType : int;
-enum class SkTileMode;
class SkSpecialImage_Gpu final : public SkSpecialImage {
public:
@@ -64,23 +58,6 @@ public:
sk_ref_sp(fContext), this->uniqueID(), fView, this->colorInfo());
}
- sk_sp<SkShader> onAsShader(SkTileMode tileMode,
- const SkSamplingOptions& sampling,
- const SkMatrix& lm) const override {
- // The special image's logical (0,0) is at its subset's topLeft() so we need to account for
- // that in the local matrix used when sampling.
- SkMatrix subsetOrigin = SkMatrix::Translate(-this->subset().topLeft());
- subsetOrigin.postConcat(lm);
- // However, we don't need to modify the subset itself since that is defined with respect to
- // the base image, and the local matrix is applied before any tiling/clamping.
- const SkRect subset = SkRect::Make(this->subset());
-
- // asImage() w/o a subset makes no copy; create the SkImageShader directly to remember the
- // subset used to access the image.
- return SkImageShader::MakeSubset(
- this->asImage(), subset, tileMode, tileMode, sampling, &subsetOrigin);
- }
-
private:
GrRecordingContext* fContext;
GrSurfaceProxyView fView;
diff --git a/src/gpu/graphite/SpecialImage_Graphite.cpp b/src/gpu/graphite/SpecialImage_Graphite.cpp
index c44438e3b8..fe1c48b963 100644
--- a/src/gpu/graphite/SpecialImage_Graphite.cpp
+++ b/src/gpu/graphite/SpecialImage_Graphite.cpp
@@ -14,7 +14,6 @@
#include "src/gpu/graphite/Image_Graphite.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/gpu/graphite/TextureUtils.h"
-#include "src/shaders/SkImageShader.h"
namespace skgpu::graphite {
@@ -50,23 +49,6 @@ public:
return sk_make_sp<Image>(this->uniqueID(), fTextureProxyView, this->colorInfo());
}
- sk_sp<SkShader> onAsShader(SkTileMode tileMode,
- const SkSamplingOptions& sampling,
- const SkMatrix& lm) const override {
- // The special image's logical (0,0) is at its subset's topLeft() so we need to account for
- // that in the local matrix used when sampling.
- SkMatrix subsetOrigin = SkMatrix::Translate(-this->subset().topLeft());
- subsetOrigin.postConcat(lm);
- // However, we don't need to modify the subset itself since that is defined with respect to
- // the base image, and the local matrix is applied before any tiling/clamping.
- const SkRect subset = SkRect::Make(this->subset());
-
- // asImage() w/o a subset makes no copy; create the SkImageShader directly to remember the
- // subset used to access the image.
- return SkImageShader::MakeSubset(this->asImage(), subset, tileMode, tileMode,
- sampling, &subsetOrigin);
- }
-
private:
TextureProxyView fTextureProxyView;
};