39 size_t samples_per_frame,
40 float shutter_angle,
float shutter_phase) {
41 if (!samples_per_frame || shutter_angle <= 0) {
47 const auto samples_duration = shutter_angle / 360,
48 phase = shutter_phase / 360,
49 dt = samples_duration / (samples_per_frame - 1);
59 size_t samples,
float phase,
float dt)
61 , fAnimator(std::move(animator))
62 , fSampleCount(samples)
70SkRect MotionBlurEffect::seekToSample(
size_t sample_idx,
const SkMatrix& ctm)
const {
72 fAnimator->seek(fT + fPhase + fDT * sample_idx);
75 return this->
children()[0]->revalidate(
nullptr, ctm);
80 fVisibleSampleCount = 0;
82 for (
size_t i = 0; i < fSampleCount; ++i) {
90void MotionBlurEffect::renderToRaster8888Pow2Samples(
SkCanvas* canvas,
91 const RenderContext* ctx)
const {
96 const int shift =
SkNextLog2(fVisibleSampleCount);
97 SkASSERT((
size_t(1)<<shift) == fVisibleSampleCount);
113 std::vector<uint64_t> accum(
info.width() *
info.height());
116 bool needs_clear =
false;
117 for (
size_t i = 0; i < fSampleCount; ++i) {
120 if (!child->isVisible()) {
129 child->render(canvas, ctx);
133 const uint32_t* src = layer;
134 uint64_t* dst = accum.data();
136 for (
int y = 0;
y <
info.height();
y++) {
138 int n =
info.width();
139 const auto row = src;
144 (
d + skvx::cast<uint16_t>(
s)).
store(dst);
154 (
d + skvx::cast<uint16_t>(
s)).
store(dst);
160 src = (
const uint32_t*)( (
const char*)row + rowBytes );
163 SkASSERT(frames_rendered == fVisibleSampleCount);
166 const uint64_t*
src = accum.data();
167 uint32_t*
dst = layer;
168 for (
int y = 0;
y <
info.height();
y++) {
170 int n =
info.width();
171 const auto row =
dst;
174 skvx::cast<uint8_t>(
s >> shift).store(dst);
182 skvx::cast<uint8_t>(
s >> shift).store(dst);
189 dst = (uint32_t*)( (
char*)row + rowBytes );
194 if (!fVisibleSampleCount) {
199 const auto& child = this->
children()[0];
209 this->renderToRaster8888Pow2Samples(canvas, ctx);
218 const float frame_alpha = 1.0f / fVisibleSampleCount;
225 const bool isolate_frames = !!frame_ctx->
fBlender;
226 if (isolate_frames) {
235 for (
size_t i = 0; i < fSampleCount; ++i) {
238 if (!child->isVisible()) {
243 if (isolate_frames) {
244 canvas->
saveLayer(
nullptr, &frame_paint);
247 child->render(canvas, frame_ctx);
251 SkASSERT(frames_rendered == fVisibleSampleCount);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
static int SkNextLog2(uint32_t value)
constexpr bool SkIsPow2(T value)
#define INHERITED(method,...)
constexpr size_t SkToSizeT(S x)
static sk_sp< SkBlender > Mode(SkBlendMode mode)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
bool peekPixels(SkPixmap *pixmap)
void clear(SkColor color)
SkMatrix getTotalMatrix() const
SkImageInfo imageInfo() const
void * accessTopLayerPixels(SkImageInfo *info, size_t *rowBytes, SkIPoint *origin=nullptr)
void setBlendMode(SkBlendMode mode)
AutoInvalBlocker(const MotionBlurEffect *mb, const sk_sp< RenderNode > &child)
void onRender(SkCanvas *canvas, const RenderContext *ctx) const override
static sk_sp< MotionBlurEffect > Make(sk_sp< Animator > animator, sk_sp< sksg::RenderNode > child, size_t samples_per_frame, float shutter_angle, float shutter_phase)
const RenderNode * onNodeAt(const SkPoint &) const override
SkRect onRevalidate(sksg::InvalidationController *ic, const SkMatrix &ctm) override
const std::vector< sk_sp< RenderNode > > & children() const
void observeInval(const sk_sp< Node > &)
void unobserveInval(const sk_sp< Node > &)
const SkRect & bounds() const
ScopedRenderContext && modulateOpacity(float opacity)
ScopedRenderContext && modulateBlender(sk_sp< SkBlender >)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
SkColorType colorType() const
static constexpr SkRect MakeEmpty()
void join(const SkRect &r)
sk_sp< SkBlender > fBlender
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)