blob: 5c49be8a154306ab45a6d9218d43f64d202a3d82 [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkVMBlitter_DEFINED
#define SkVMBlitter_DEFINED
#include "include/core/SkPixmap.h"
#include "src/base/SkArenaAlloc.h"
#include "src/base/SkTLazy.h"
#include "src/core/SkBlitter.h"
#include "src/core/SkLRUCache.h"
#include "src/core/SkVM.h"
class SkVMBlitter final : public SkBlitter {
public:
static SkVMBlitter* Make(const SkPixmap& dst,
const SkPaint&,
const SkMatrix& ctm,
SkArenaAlloc*,
sk_sp<SkShader> clipShader);
static SkVMBlitter* Make(const SkPixmap& dst,
const SkPaint&,
const SkPixmap& sprite,
int left, int top,
SkArenaAlloc*,
sk_sp<SkShader> clipShader);
SkVMBlitter(const SkPixmap& device,
const SkPaint& paint,
const SkPixmap* sprite,
SkIPoint spriteOffset,
const SkMatrix& ctm,
sk_sp<SkShader> clip,
bool* ok);
~SkVMBlitter() override;
private:
enum Coverage { Full, UniformF, MaskA8, MaskLCD16, Mask3D, kCount };
struct Key {
uint64_t shader,
clip,
blender,
colorSpace;
uint8_t colorType,
alphaType,
coverage;
uint8_t padding8{0};
uint32_t padding{0};
// Params::{paint,quality,matrices} are only passed to {shader,clip}->program(),
// not used here by the blitter itself. No need to include them in the key;
// they'll be folded into the shader key if used.
bool operator==(const Key& that) const;
Key withCoverage(Coverage c) const;
};
struct Params {
sk_sp<SkShader> shader;
sk_sp<SkShader> clip;
sk_sp<SkBlender> blender; // never null
SkColorInfo dst;
Coverage coverage;
SkColor4f paint;
SkMatrix ctm;
Params withCoverage(Coverage c) const;
};
static Params EffectiveParams(const SkPixmap& device,
const SkPixmap* sprite,
SkPaint paint,
const SkMatrix& ctm,
sk_sp<SkShader> clip);
static skvm::Color DstColor(skvm::Builder* p, const Params& params);
static void BuildProgram(skvm::Builder* p, const Params& params,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc);
static Key CacheKey(const Params& params,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc, bool* ok);
static SkLRUCache<Key, skvm::Program>* TryAcquireProgramCache();
static SkString DebugName(const Key& key);
static void ReleaseProgramCache();
skvm::Program* buildProgram(Coverage coverage);
void updateUniforms(int right, int y);
const void* isSprite(int x, int y) const;
void blitH(int x, int y, int w) override;
void blitAntiH(int x, int y, const SkAlpha cov[], const int16_t runs[]) override;
private:
void blitMask(const SkMask& mask, const SkIRect& clip) override;
SkPixmap fDevice;
const SkPixmap fSprite; // See isSprite().
const SkIPoint fSpriteOffset;
skvm::Uniforms fUniforms; // Most data is copied directly into fUniforms,
SkArenaAlloc fAlloc{2*sizeof(void*)}; // but a few effects need to ref large content.
const Params fParams;
const Key fKey;
bool fStoreToCache = false;
skvm::Program* fProgramPtrs[Coverage::kCount] = {nullptr};
SkTLazy<skvm::Program> fPrograms[Coverage::kCount];
friend class Viewer;
};
#endif // SkVMBlitter_DEFINED