draw atlas: using skvm
Bug=skia:12225
Change-Id: I1b6816e234cbaa49035bcedfeff894a8d2c31133
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/434680
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/src/core/SkDraw_atlas.cpp b/src/core/SkDraw_atlas.cpp
index 069a300..8ead762 100644
--- a/src/core/SkDraw_atlas.cpp
+++ b/src/core/SkDraw_atlas.cpp
@@ -6,6 +6,7 @@
*/
#include "include/core/SkColorFilter.h"
+#include "include/core/SkMatrix.h"
#include "include/core/SkRSXform.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
@@ -16,10 +17,11 @@
#include "src/core/SkRasterClip.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkScan.h"
-#include "src/shaders/SkShaderBase.h"
-
-#include "include/core/SkMatrix.h"
#include "src/core/SkScan.h"
+#include "src/core/SkVM.h"
+#include "src/core/SkVMBlitter.h"
+#include "src/shaders/SkComposeShader.h"
+#include "src/shaders/SkShaderBase.h"
static void fill_rect(const SkMatrix& ctm, const SkRasterClip& rc,
const SkRect& r, SkBlitter* blitter, SkPath* scratchPath) {
@@ -46,6 +48,44 @@
ctx->rgba[3] = SkScalarRoundToInt(rgba[3]*255); ctx->a = rgba[3];
}
+extern bool gUseSkVMBlitter;
+
+class UpdatableColorShader : public SkShaderBase {
+public:
+ explicit UpdatableColorShader(SkColorSpace* cs)
+ : fSteps{sk_srgb_singleton(), kUnpremul_SkAlphaType, cs, kUnpremul_SkAlphaType} {}
+ skvm::Color onProgram(
+ skvm::Builder* builder, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& provider, const SkMatrix* localM, const SkColorInfo& dst,
+ skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
+ skvm::Uniform color = uniforms->pushPtr(fValues);
+ skvm::F32 r = builder->arrayF(color, 0);
+ skvm::F32 g = builder->arrayF(color, 1);
+ skvm::F32 b = builder->arrayF(color, 2);
+ skvm::F32 a = builder->arrayF(color, 3);
+
+ return {r, g, b, a};
+ }
+
+ void updateColor(SkColor c) const {
+ SkColor4f c4 = SkColor4f::FromColor(c);
+ fSteps.apply(c4.vec());
+ auto cp4 = c4.premul();
+ fValues[0] = cp4.fR;
+ fValues[1] = cp4.fG;
+ fValues[2] = cp4.fB;
+ fValues[3] = cp4.fA;
+ }
+
+private:
+ // For serialization. This will never be called.
+ Factory getFactory() const override { return nullptr; }
+ const char* getTypeName() const override { return nullptr; }
+
+ SkColorSpaceXformSteps fSteps;
+ mutable float fValues[4];
+};
+
void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect textures[],
const SkColor colors[], int count, SkBlendMode bmode,
const SkSamplingOptions& sampling, const SkPaint& paint) {
@@ -54,13 +94,45 @@
return;
}
+ SkSTArenaAlloc<256> alloc;
+
SkPaint p(paint);
p.setAntiAlias(false); // we never respect this for drawAtlas(or drawVertices)
p.setStyle(SkPaint::kFill_Style);
p.setShader(nullptr);
p.setMaskFilter(nullptr);
- SkSTArenaAlloc<256> alloc;
+ if (gUseSkVMBlitter) {
+ auto updateShader = as_SB(atlasShader)->updatableShader(&alloc);
+ UpdatableColorShader* colorShader = nullptr;
+ SkShaderBase* shader = nullptr;
+ if (colors) {
+ colorShader = alloc.make<UpdatableColorShader>(fDst.colorSpace());
+ shader = alloc.make<SkShader_Blend>(
+ bmode, sk_ref_sp(colorShader), sk_ref_sp(updateShader));
+ } else {
+ shader = as_SB(updateShader);
+ }
+ p.setShader(sk_ref_sp(shader));
+ if (auto blitter = SkVMBlitter::Make(fDst, p,*fMatrixProvider, &alloc, fRC->clipShader())) {
+ SkPath scratchPath;
+ for (int i = 0; i < count; ++i) {
+ if (colorShader) {
+ colorShader->updateColor(colors[i]);
+ }
+
+ SkMatrix mx;
+ mx.setRSXform(xform[i]);
+ mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
+ mx.postConcat(fMatrixProvider->localToDevice());
+ if (updateShader->update(mx)) {
+ fill_rect(mx, *fRC, textures[i], blitter, &scratchPath);
+ }
+ }
+ return;
+ }
+ } // gUseSkVMBlitter
+
SkRasterPipeline pipeline(&alloc);
SkStageRec rec = {
&pipeline, &alloc, fDst.colorType(), fDst.colorSpace(), p, nullptr, *fMatrixProvider
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 3f948d7..d126df0 100755
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -741,7 +741,8 @@
return {};
}
auto [upper, upperInv] = access->level();
- if (!sampling.useCubic) {
+ // If we are using a coordShader, then we can't make guesses about the state of the matrix.
+ if (!sampling.useCubic && !coordShader) {
// TODO: can tweak_sampling sometimes for cubic too when B=0
if (matrices.localToDeviceHitsPixelCenters()) {
sampling = tweak_sampling(sampling, upperInv);