Defer making skshader until we know quality (#24376) (#24494)
Co-authored-by: Michael Reed <mike@reedtribe.org>
diff --git a/flow/paint_utils.cc b/flow/paint_utils.cc
index 38fc179..647ca3d 100644
--- a/flow/paint_utils.cc
+++ b/flow/paint_utils.cc
@@ -20,7 +20,8 @@
bm.eraseColor(c1);
bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
- return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
+ return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
+ SkSamplingOptions());
}
} // anonymous namespace
diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc
index b9d96ea..d1d8f00 100644
--- a/lib/ui/compositing/scene_builder.cc
+++ b/lib/ui/compositing/scene_builder.cc
@@ -183,8 +183,10 @@
int blendMode) {
SkRect rect = SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight,
maskRectBottom);
+ // TODO: should this come from the caller?
+ SkFilterQuality quality = kNone_SkFilterQuality;
auto layer = std::make_shared<flutter::ShaderMaskLayer>(
- shader->shader(), rect, static_cast<SkBlendMode>(blendMode));
+ shader->shader(quality), rect, static_cast<SkBlendMode>(blendMode));
PushLayer(layer);
EngineLayer::MakeRetained(layer_handle, layer);
}
diff --git a/lib/ui/painting/gradient.cc b/lib/ui/painting/gradient.cc
index d71e75a..0d2d2fc 100644
--- a/lib/ui/painting/gradient.cc
+++ b/lib/ui/painting/gradient.cc
@@ -58,10 +58,10 @@
sk_matrix = ToSkMatrix(matrix4);
}
- set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeLinear(
+ sk_shader_ = UIDartState::CreateGPUObject(SkGradientShader::MakeLinear(
reinterpret_cast<const SkPoint*>(end_points.data()),
reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
- colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr)));
+ colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr));
}
void CanvasGradient::initRadial(double center_x,
@@ -83,10 +83,10 @@
sk_matrix = ToSkMatrix(matrix4);
}
- set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeRadial(
+ sk_shader_ = UIDartState::CreateGPUObject(SkGradientShader::MakeRadial(
SkPoint::Make(center_x, center_y), radius,
reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
- colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr)));
+ colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr));
}
void CanvasGradient::initSweep(double center_x,
@@ -109,11 +109,11 @@
sk_matrix = ToSkMatrix(matrix4);
}
- set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeSweep(
+ sk_shader_ = UIDartState::CreateGPUObject(SkGradientShader::MakeSweep(
center_x, center_y, reinterpret_cast<const SkColor*>(colors.data()),
color_stops.data(), colors.num_elements(), tile_mode,
start_angle * 180.0 / M_PI, end_angle * 180.0 / M_PI, 0,
- has_matrix ? &sk_matrix : nullptr)));
+ has_matrix ? &sk_matrix : nullptr));
}
void CanvasGradient::initTwoPointConical(double start_x,
@@ -138,11 +138,13 @@
sk_matrix = ToSkMatrix(matrix4);
}
- set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeTwoPointConical(
- SkPoint::Make(start_x, start_y), start_radius,
- SkPoint::Make(end_x, end_y), end_radius,
- reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
- colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr)));
+ sk_shader_ =
+ UIDartState::CreateGPUObject(SkGradientShader::MakeTwoPointConical(
+ SkPoint::Make(start_x, start_y), start_radius,
+ SkPoint::Make(end_x, end_y), end_radius,
+ reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
+ colors.num_elements(), tile_mode, 0,
+ has_matrix ? &sk_matrix : nullptr));
}
CanvasGradient::CanvasGradient() = default;
diff --git a/lib/ui/painting/gradient.h b/lib/ui/painting/gradient.h
index a0d142a..e3dc70e 100644
--- a/lib/ui/painting/gradient.h
+++ b/lib/ui/painting/gradient.h
@@ -62,10 +62,13 @@
SkTileMode tile_mode,
const tonic::Float64List& matrix4);
+ sk_sp<SkShader> shader(SkFilterQuality) override { return sk_shader_.get(); }
+
static void RegisterNatives(tonic::DartLibraryNatives* natives);
private:
CanvasGradient();
+ flutter::SkiaGPUObject<SkShader> sk_shader_;
};
} // namespace flutter
diff --git a/lib/ui/painting/image_shader.cc b/lib/ui/painting/image_shader.cc
index 95c27a6..5e64e46 100644
--- a/lib/ui/painting/image_shader.cc
+++ b/lib/ui/painting/image_shader.cc
@@ -43,11 +43,23 @@
ToDart("ImageShader constructor called with non-genuine Image."));
return;
}
- SkMatrix sk_matrix = ToSkMatrix(matrix4);
- set_shader(UIDartState::CreateGPUObject(
- image->image()->makeShader(tmx, tmy, &sk_matrix)));
+ sk_image_ = image->image();
+ tmx_ = tmx;
+ tmy_ = tmy;
+ local_matrix_ = ToSkMatrix(matrix4);
}
+sk_sp<SkShader> ImageShader::shader(SkFilterQuality quality) {
+ if (!cached_shader_.get() || cached_quality_ != quality) {
+ SkSamplingOptions sampling(quality,
+ SkSamplingOptions::kMedium_asMipmapLinear);
+
+ cached_quality_ = quality;
+ cached_shader_ = UIDartState::CreateGPUObject(
+ sk_image_->makeShader(tmx_, tmy_, sampling, &local_matrix_));
+ }
+ return cached_shader_.get();
+}
ImageShader::ImageShader() = default;
ImageShader::~ImageShader() = default;
diff --git a/lib/ui/painting/image_shader.h b/lib/ui/painting/image_shader.h
index e57a7a5..afbfe7f 100644
--- a/lib/ui/painting/image_shader.h
+++ b/lib/ui/painting/image_shader.h
@@ -33,10 +33,20 @@
SkTileMode tmy,
const tonic::Float64List& matrix4);
+ sk_sp<SkShader> shader(SkFilterQuality) override;
+
static void RegisterNatives(tonic::DartLibraryNatives* natives);
private:
ImageShader();
+
+ sk_sp<SkImage> sk_image_;
+ SkTileMode tmx_;
+ SkTileMode tmy_;
+ SkMatrix local_matrix_;
+
+ SkFilterQuality cached_quality_ = kNone_SkFilterQuality;
+ flutter::SkiaGPUObject<SkShader> cached_shader_;
};
} // namespace flutter
diff --git a/lib/ui/painting/paint.cc b/lib/ui/painting/paint.cc
index d3e49ad..c511269 100644
--- a/lib/ui/painting/paint.cc
+++ b/lib/ui/painting/paint.cc
@@ -71,6 +71,12 @@
return;
}
+ tonic::DartByteData byte_data(paint_data);
+ FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
+
+ const uint32_t* uint_data = static_cast<const uint32_t*>(byte_data.data());
+ const float* float_data = static_cast<const float*>(byte_data.data());
+
Dart_Handle values[kObjectCount];
if (!Dart_IsNull(paint_objects)) {
FML_DCHECK(Dart_IsList(paint_objects));
@@ -86,7 +92,9 @@
Dart_Handle shader = values[kShaderIndex];
if (!Dart_IsNull(shader)) {
Shader* decoded = tonic::DartConverter<Shader*>::FromDart(shader);
- paint_.setShader(decoded->shader());
+ uint32_t filter_quality = uint_data[kFilterQualityIndex];
+ paint_.setShader(
+ decoded->shader(static_cast<SkFilterQuality>(filter_quality)));
}
Dart_Handle color_filter = values[kColorFilterIndex];
@@ -104,12 +112,6 @@
}
}
- tonic::DartByteData byte_data(paint_data);
- FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
-
- const uint32_t* uint_data = static_cast<const uint32_t*>(byte_data.data());
- const float* float_data = static_cast<const float*>(byte_data.data());
-
paint_.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
uint32_t encoded_color = uint_data[kColorIndex];
@@ -149,11 +151,6 @@
paint_.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
}
- uint32_t filter_quality = uint_data[kFilterQualityIndex];
- if (filter_quality) {
- paint_.setFilterQuality(static_cast<SkFilterQuality>(filter_quality));
- }
-
if (uint_data[kInvertColorIndex]) {
sk_sp<SkColorFilter> invert_filter =
ColorFilter::MakeColorMatrixFilter255(invert_colors);
diff --git a/lib/ui/painting/shader.cc b/lib/ui/painting/shader.cc
index c6f0e6b..e350033 100644
--- a/lib/ui/painting/shader.cc
+++ b/lib/ui/painting/shader.cc
@@ -10,9 +10,6 @@
IMPLEMENT_WRAPPERTYPEINFO(ui, Shader);
-Shader::Shader(flutter::SkiaGPUObject<SkShader> shader)
- : shader_(std::move(shader)) {}
-
Shader::~Shader() = default;
} // namespace flutter
diff --git a/lib/ui/painting/shader.h b/lib/ui/painting/shader.h
index cb9043a..509a06a 100644
--- a/lib/ui/painting/shader.h
+++ b/lib/ui/painting/shader.h
@@ -8,6 +8,7 @@
#include "flutter/flow/skia_gpu_object.h"
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/ui_dart_state.h"
+#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkShader.h"
namespace flutter {
@@ -19,17 +20,13 @@
public:
~Shader() override;
- sk_sp<SkShader> shader() { return shader_.get(); }
-
- void set_shader(flutter::SkiaGPUObject<SkShader> shader) {
- shader_ = std::move(shader);
- }
+ virtual sk_sp<SkShader> shader(SkFilterQuality) = 0;
protected:
- Shader(flutter::SkiaGPUObject<SkShader> shader = {});
+ Shader() {}
private:
- flutter::SkiaGPUObject<SkShader> shader_;
+ // flutter::SkiaGPUObject<SkShader> shader_;
};
} // namespace flutter