blitters for sRGB and float16
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1697863002 Review URL: https://codereview.chromium.org/1697863002
This commit is contained in:
parent
bd6366a69e
commit
a34be68a7e
@ -41,9 +41,12 @@ public:
|
||||
fSurfaceProps = props;
|
||||
}
|
||||
|
||||
SkImageInfo info() const { return fBitmap.info(); }
|
||||
const SkBitmap& getBitmap() const { return fBitmap; }
|
||||
|
||||
void resize(int width, int height);
|
||||
void resize(const SkImageInfo&);
|
||||
void setColorType(SkColorType, SkColorProfileType);
|
||||
|
||||
bool isDirty() const { return !fDirtyRgn.isEmpty(); }
|
||||
bool update(SkIRect* updateArea);
|
||||
|
@ -42,6 +42,25 @@
|
||||
class GrContext;
|
||||
#endif
|
||||
|
||||
const struct {
|
||||
SkColorType fColorType;
|
||||
SkColorProfileType fProfileType;
|
||||
const char* fName;
|
||||
} gConfig[] = {
|
||||
{ kN32_SkColorType, kLinear_SkColorProfileType, "L32" },
|
||||
{ kN32_SkColorType, kSRGB_SkColorProfileType, "S32" },
|
||||
{ kRGBA_F16_SkColorType, kLinear_SkColorProfileType, "F16" },
|
||||
};
|
||||
|
||||
static const char* find_config_name(const SkImageInfo& info) {
|
||||
for (const auto& config : gConfig) {
|
||||
if (config.fColorType == info.colorType() && config.fProfileType == info.profileType()) {
|
||||
return config.fName;
|
||||
}
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
||||
// Should be 3x + 1
|
||||
#define kMaxFatBitsScale 28
|
||||
|
||||
@ -876,6 +895,10 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
|
||||
fAppMenu->setTitle("Global Settings");
|
||||
int itemID;
|
||||
|
||||
itemID = fAppMenu->appendList("ColorType", "ColorType", sinkID, 0,
|
||||
gConfig[0].fName, gConfig[1].fName, gConfig[2].fName, nullptr);
|
||||
fAppMenu->assignKeyEquivalentToItem(itemID, 'C');
|
||||
|
||||
itemID = fAppMenu->appendList("Device Type", "Device Type", sinkID, 0,
|
||||
"Raster",
|
||||
"OpenGL",
|
||||
@ -1557,6 +1580,10 @@ bool SampleWindow::onEvent(const SkEvent& evt) {
|
||||
this->setDeviceType((DeviceType)selected);
|
||||
return true;
|
||||
}
|
||||
if (SkOSMenu::FindListIndex(evt, "ColorType", &selected)) {
|
||||
this->setDeviceColorType(gConfig[selected].fColorType, gConfig[selected].fProfileType);
|
||||
return true;
|
||||
}
|
||||
if (SkOSMenu::FindSwitchState(evt, "Slide Show", nullptr)) {
|
||||
this->toggleSlideshow();
|
||||
return true;
|
||||
@ -1761,13 +1788,24 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
|
||||
void SampleWindow::setDeviceType(DeviceType type) {
|
||||
if (type == fDeviceType)
|
||||
return;
|
||||
|
||||
fDevManager->tearDownBackend(this);
|
||||
|
||||
fDeviceType = type;
|
||||
|
||||
fDevManager->setUpBackend(this, fMSAASampleCount);
|
||||
|
||||
this->updateTitle();
|
||||
this->inval(nullptr);
|
||||
}
|
||||
|
||||
void SampleWindow::setDeviceColorType(SkColorType ct, SkColorProfileType pt) {
|
||||
this->setColorType(ct, pt);
|
||||
|
||||
fDevManager->tearDownBackend(this);
|
||||
|
||||
fDeviceType = type;
|
||||
|
||||
|
||||
fDevManager->setUpBackend(this, fMSAASampleCount);
|
||||
|
||||
|
||||
this->updateTitle();
|
||||
this->inval(nullptr);
|
||||
}
|
||||
@ -2027,6 +2065,8 @@ void SampleWindow::updateTitle() {
|
||||
}
|
||||
#endif
|
||||
|
||||
title.appendf(" %s", find_config_name(this->info()));
|
||||
|
||||
this->setTitle(title.c_str());
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,7 @@ public:
|
||||
void draw(SkCanvas*) override;
|
||||
|
||||
void setDeviceType(DeviceType type);
|
||||
void setDeviceColorType(SkColorType, SkColorProfileType);
|
||||
void toggleRendering();
|
||||
void toggleSlideshow();
|
||||
void toggleFPS();
|
||||
|
@ -55,6 +55,8 @@ static bool valid_for_bitmap_device(const SkImageInfo& info,
|
||||
break;
|
||||
case kN32_SkColorType:
|
||||
break;
|
||||
case kRGBA_F16_SkColorType:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -20,13 +20,7 @@
|
||||
#include "SkXfermodeInterpretation.h"
|
||||
|
||||
// define this for testing srgb blits
|
||||
//#define SK_SUPPORT_SRGB_RASTER
|
||||
|
||||
#ifdef SK_SUPPORT_SRGB_RASTER
|
||||
#define ALLOW_SRGB true
|
||||
#else
|
||||
#define ALLOW_SRGB false
|
||||
#endif
|
||||
//#define SK_FORCE_PM4f_FOR_L32_BLITS
|
||||
|
||||
SkBlitter::~SkBlitter() {}
|
||||
|
||||
@ -913,23 +907,32 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
|
||||
break;
|
||||
|
||||
case kN32_SkColorType:
|
||||
if (shader) {
|
||||
if (shaderContext->supports4f() && ALLOW_SRGB) {
|
||||
blitter = allocator->createT<SkARGB32_Shader4f_Blitter>(
|
||||
device, *paint, shaderContext);
|
||||
} else {
|
||||
blitter = allocator->createT<SkARGB32_Shader_Blitter>(
|
||||
device, *paint, shaderContext);
|
||||
}
|
||||
} else if (paint->getColor() == SK_ColorBLACK) {
|
||||
blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
|
||||
} else if (paint->getAlpha() == 0xFF) {
|
||||
blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
|
||||
#ifdef SK_FORCE_PM4f_FOR_L32_BLITS
|
||||
if (true)
|
||||
#else
|
||||
if (device.info().isSRGB())
|
||||
#endif
|
||||
{
|
||||
blitter = SkBlitter_ARGB32_Create(device, *paint, shaderContext, allocator);
|
||||
} else {
|
||||
blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
|
||||
if (shader) {
|
||||
blitter = allocator->createT<SkARGB32_Shader_Blitter>(
|
||||
device, *paint, shaderContext);
|
||||
} else if (paint->getColor() == SK_ColorBLACK) {
|
||||
blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
|
||||
} else if (paint->getAlpha() == 0xFF) {
|
||||
blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
|
||||
} else {
|
||||
blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kRGBA_F16_SkColorType:
|
||||
// kU16_SkColorType:
|
||||
blitter = SkBlitter_ARGB64_Create(device, *paint, shaderContext, allocator);
|
||||
break;
|
||||
|
||||
default:
|
||||
SkDEBUGFAIL("unsupported device config");
|
||||
blitter = allocator->createT<SkNullBlitter>();
|
||||
@ -972,6 +975,7 @@ SkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
|
||||
|
||||
fShader->ref();
|
||||
fShaderFlags = fShaderContext->getFlags();
|
||||
fConstInY = SkToBool(fShaderFlags & SkShader::kConstInY32_Flag);
|
||||
}
|
||||
|
||||
SkShaderBlitter::~SkShaderBlitter() {
|
||||
|
@ -11,149 +11,339 @@
|
||||
#include "SkUtils.h"
|
||||
#include "SkXfermode.h"
|
||||
#include "SkBlitMask.h"
|
||||
#include "SkTemplates.h"
|
||||
|
||||
template <typename State> class SkState_Blitter : public SkRasterBlitter {
|
||||
typedef SkRasterBlitter INHERITED;
|
||||
State fState;
|
||||
|
||||
public:
|
||||
SkState_Blitter(const SkPixmap& device, const SkPaint& paint)
|
||||
: INHERITED(device)
|
||||
, fState(device.info(), paint, nullptr)
|
||||
{}
|
||||
|
||||
void blitH(int x, int y, int width) override {
|
||||
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
|
||||
|
||||
fState.fProc1(fState, State::WritableAddr(fDevice, x, y), fState.fPM4f, width, nullptr);
|
||||
}
|
||||
|
||||
void blitV(int x, int y, int height, SkAlpha alpha) override {
|
||||
SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
size_t deviceRB = fDevice.rowBytes();
|
||||
|
||||
for (int i = 0; i < height; ++i) {
|
||||
fState.fProc1(fState, device, fState.fPM4f, 1, &alpha);
|
||||
device = (typename State::DstType*)((char*)device + deviceRB);
|
||||
}
|
||||
}
|
||||
|
||||
void blitRect(int x, int y, int width, int height) override {
|
||||
SkASSERT(x >= 0 && y >= 0 &&
|
||||
x + width <= fDevice.width() && y + height <= fDevice.height());
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
size_t deviceRB = fDevice.rowBytes();
|
||||
|
||||
do {
|
||||
fState.fProc1(fState, device, fState.fPM4f, width, nullptr);
|
||||
y += 1;
|
||||
device = (typename State::DstType*)((char*)device + deviceRB);
|
||||
} while (--height > 0);
|
||||
}
|
||||
|
||||
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
|
||||
for (;;) {
|
||||
int count = *runs;
|
||||
if (count <= 0) {
|
||||
break;
|
||||
}
|
||||
int aa = *antialias;
|
||||
if (aa) {
|
||||
if (aa == 255) {
|
||||
fState.fProc1(fState, device, fState.fPM4f, count, nullptr);
|
||||
} else {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
fState.fProc1(fState, &device[i], fState.fPM4f, 1, antialias);
|
||||
}
|
||||
}
|
||||
}
|
||||
device += count;
|
||||
runs += count;
|
||||
antialias += count;
|
||||
x += count;
|
||||
}
|
||||
}
|
||||
|
||||
void blitMask(const SkMask& mask, const SkIRect& clip) override {
|
||||
// we only handle kA8
|
||||
if (SkMask::kA8_Format != mask.fFormat) {
|
||||
this->INHERITED::blitMask(mask, clip);
|
||||
return;
|
||||
}
|
||||
|
||||
SkASSERT(mask.fBounds.contains(clip));
|
||||
|
||||
const int x = clip.fLeft;
|
||||
const int width = clip.width();
|
||||
const int y = clip.fTop;
|
||||
const int height = clip.height();
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
const size_t dstRB = fDevice.rowBytes();
|
||||
const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
|
||||
const size_t maskRB = mask.fRowBytes;
|
||||
|
||||
for (int i = 0; i < height; ++i) {
|
||||
fState.fProc1(fState, device, fState.fPM4f, width, maskRow);
|
||||
device = (typename State::DstType*)((char*)device + dstRB);
|
||||
maskRow += maskRB;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename State> class SkState_Shader_Blitter : public SkShaderBlitter {
|
||||
public:
|
||||
SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext)
|
||||
: INHERITED(device, paint, shaderContext)
|
||||
, fState(device.info(), paint, shaderContext)
|
||||
{}
|
||||
|
||||
void blitH(int x, int y, int width) override {
|
||||
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
|
||||
fState.fProcN(fState, device, fState.fBuffer, width, nullptr);
|
||||
}
|
||||
|
||||
void blitV(int x, int y, int height, SkAlpha alpha) override {
|
||||
SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
size_t deviceRB = fDevice.rowBytes();
|
||||
const int bottom = y + height;
|
||||
|
||||
if (fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
|
||||
}
|
||||
for (; y < bottom; ++y) {
|
||||
if (!fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
|
||||
}
|
||||
fState.fProcN(fState, device, fState.fBuffer, 1, &alpha);
|
||||
device = (typename State::DstType*)((char*)device + deviceRB);
|
||||
}
|
||||
}
|
||||
|
||||
void blitRect(int x, int y, int width, int height) override {
|
||||
SkASSERT(x >= 0 && y >= 0 &&
|
||||
x + width <= fDevice.width() && y + height <= fDevice.height());
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
size_t deviceRB = fDevice.rowBytes();
|
||||
const int bottom = y + height;
|
||||
|
||||
if (fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
|
||||
}
|
||||
for (; y < bottom; ++y) {
|
||||
if (!fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
|
||||
}
|
||||
fState.fProcN(fState, device, fState.fBuffer, width, nullptr);
|
||||
device = (typename State::DstType*)((char*)device + deviceRB);
|
||||
}
|
||||
}
|
||||
|
||||
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
|
||||
for (;;) {
|
||||
int count = *runs;
|
||||
if (count <= 0) {
|
||||
break;
|
||||
}
|
||||
int aa = *antialias;
|
||||
if (aa) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count);
|
||||
if (aa == 255) {
|
||||
fState.fProcN(fState, device, fState.fBuffer, count, nullptr);
|
||||
} else {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
fState.fProcN(fState, &device[i], &fState.fBuffer[i], 1, antialias);
|
||||
}
|
||||
}
|
||||
}
|
||||
device += count;
|
||||
runs += count;
|
||||
antialias += count;
|
||||
x += count;
|
||||
}
|
||||
}
|
||||
|
||||
void blitMask(const SkMask& mask, const SkIRect& clip) override {
|
||||
// we only handle kA8
|
||||
if (SkMask::kA8_Format != mask.fFormat) {
|
||||
this->INHERITED::blitMask(mask, clip);
|
||||
return;
|
||||
}
|
||||
|
||||
SkASSERT(mask.fBounds.contains(clip));
|
||||
|
||||
const int x = clip.fLeft;
|
||||
const int width = clip.width();
|
||||
int y = clip.fTop;
|
||||
|
||||
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
|
||||
const size_t deviceRB = fDevice.rowBytes();
|
||||
const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
|
||||
const size_t maskRB = mask.fRowBytes;
|
||||
|
||||
if (fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
|
||||
}
|
||||
for (; y < clip.fBottom; ++y) {
|
||||
if (!fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
|
||||
}
|
||||
fState.fProcN(fState, device, fState.fBuffer, width, maskRow);
|
||||
device = (typename State::DstType*)((char*)device + deviceRB);
|
||||
maskRow += maskRB;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
State fState;
|
||||
|
||||
typedef SkShaderBlitter INHERITED;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkARGB32_Shader4f_Blitter::SkARGB32_Shader4f_Blitter(const SkPixmap& device,
|
||||
const SkPaint& paint, SkShader::Context* shaderContext)
|
||||
: INHERITED(device, paint, shaderContext)
|
||||
{
|
||||
const uint32_t shaderFlags = shaderContext->getFlags();
|
||||
|
||||
SkASSERT(shaderFlags & SkShader::kSupports4f_Flag);
|
||||
|
||||
fBuffer = (SkPM4f*)sk_malloc_throw(device.width() * (sizeof(SkPM4f)));
|
||||
|
||||
fState.fXfer = SkSafeRef(paint.getXfermode());
|
||||
fState.fFlags = 0;
|
||||
if (shaderFlags & SkShader::kOpaqueAlpha_Flag) {
|
||||
fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
|
||||
}
|
||||
if (device.info().isSRGB()) {
|
||||
fState.fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag;
|
||||
}
|
||||
if (fState.fXfer) {
|
||||
fProc1 = fState.fXfer->getPM4fProc1(fState.fFlags);
|
||||
fProcN = fState.fXfer->getPM4fProcN(fState.fFlags);
|
||||
} else {
|
||||
fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fState.fFlags);
|
||||
fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fState.fFlags);
|
||||
}
|
||||
|
||||
fConstInY = SkToBool(shaderFlags & SkShader::kConstInY32_Flag);
|
||||
static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderContext) {
|
||||
return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)
|
||||
: 0xFF == paint.getAlpha();
|
||||
}
|
||||
|
||||
SkARGB32_Shader4f_Blitter::~SkARGB32_Shader4f_Blitter() {
|
||||
SkSafeUnref(fState.fXfer);
|
||||
sk_free(fBuffer);
|
||||
}
|
||||
|
||||
void SkARGB32_Shader4f_Blitter::blitH(int x, int y, int width) {
|
||||
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
|
||||
|
||||
uint32_t* device = fDevice.writable_addr32(x, y);
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
||||
fProcN(fState, device, fBuffer, width, nullptr);
|
||||
}
|
||||
|
||||
void SkARGB32_Shader4f_Blitter::blitRect(int x, int y, int width, int height) {
|
||||
SkASSERT(x >= 0 && y >= 0 &&
|
||||
x + width <= fDevice.width() && y + height <= fDevice.height());
|
||||
|
||||
uint32_t* device = fDevice.writable_addr32(x, y);
|
||||
size_t deviceRB = fDevice.rowBytes();
|
||||
|
||||
if (fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
||||
do {
|
||||
fProcN(fState, device, fBuffer, width, nullptr);
|
||||
y += 1;
|
||||
device = (uint32_t*)((char*)device + deviceRB);
|
||||
} while (--height > 0);
|
||||
} else {
|
||||
do {
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
||||
fProcN(fState, device, fBuffer, width, nullptr);
|
||||
y += 1;
|
||||
device = (uint32_t*)((char*)device + deviceRB);
|
||||
} while (--height > 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SkARGB32_Shader4f_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
|
||||
const int16_t runs[]) {
|
||||
uint32_t* device = fDevice.writable_addr32(x, y);
|
||||
|
||||
for (;;) {
|
||||
int count = *runs;
|
||||
if (count <= 0) {
|
||||
break;
|
||||
struct State32 : SkXfermode::PM4fState {
|
||||
typedef uint32_t DstType;
|
||||
|
||||
SkXfermode::PM4fProc1 fProc1;
|
||||
SkXfermode::PM4fProcN fProcN;
|
||||
SkPM4f fPM4f;
|
||||
SkPM4f* fBuffer;
|
||||
|
||||
State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
|
||||
fXfer = SkSafeRef(paint.getXfermode());
|
||||
fFlags = 0;
|
||||
if (is_opaque(paint, shaderContext)) {
|
||||
fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
|
||||
}
|
||||
int aa = *antialias;
|
||||
if (aa) {
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, count);
|
||||
if (aa == 255) {
|
||||
fProcN(fState, device, fBuffer, count, nullptr);
|
||||
} else {
|
||||
// count is almost always 1
|
||||
for (int i = count - 1; i >= 0; --i) {
|
||||
fProcN(fState, &device[i], &fBuffer[i], 1, antialias);
|
||||
}
|
||||
}
|
||||
if (info.isSRGB()) {
|
||||
fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag;
|
||||
}
|
||||
if (fXfer) {
|
||||
fProc1 = fXfer->getPM4fProc1(fFlags);
|
||||
fProcN = fXfer->getPM4fProcN(fFlags);
|
||||
} else {
|
||||
fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fFlags);
|
||||
fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fFlags);
|
||||
}
|
||||
|
||||
fBuffer = nullptr;
|
||||
if (shaderContext) {
|
||||
fBuffer = new SkPM4f[info.width()];
|
||||
} else {
|
||||
fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
|
||||
}
|
||||
device += count;
|
||||
runs += count;
|
||||
antialias += count;
|
||||
x += count;
|
||||
}
|
||||
}
|
||||
|
||||
void SkARGB32_Shader4f_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
|
||||
// we only handle kA8
|
||||
if (SkMask::kA8_Format != mask.fFormat) {
|
||||
this->INHERITED::blitMask(mask, clip);
|
||||
return;
|
||||
|
||||
~State32() {
|
||||
SkSafeUnref(fXfer);
|
||||
delete[] fBuffer;
|
||||
}
|
||||
|
||||
static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
|
||||
return device.writable_addr32(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
SkASSERT(mask.fBounds.contains(clip));
|
||||
struct State64 : SkXfermode::U64State {
|
||||
typedef uint64_t DstType;
|
||||
|
||||
SkXfermode::U64Proc1 fProc1;
|
||||
SkXfermode::U64ProcN fProcN;
|
||||
SkPM4f fPM4f;
|
||||
SkPM4f* fBuffer;
|
||||
|
||||
State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
|
||||
fXfer = SkSafeRef(paint.getXfermode());
|
||||
fFlags = 0;
|
||||
if (is_opaque(paint, shaderContext)) {
|
||||
fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
|
||||
}
|
||||
if (kRGBA_F16_SkColorType == info.colorType()) {
|
||||
fFlags |= SkXfermode::kDstIsFloat16_U64Flag;
|
||||
}
|
||||
|
||||
SkXfermode::Mode mode;
|
||||
if (SkXfermode::AsMode(fXfer, &mode)) {
|
||||
mode = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
fProc1 = SkXfermode::GetU64Proc1(mode, fFlags);
|
||||
fProcN = SkXfermode::GetU64ProcN(mode, fFlags);
|
||||
|
||||
fBuffer = nullptr;
|
||||
if (shaderContext) {
|
||||
fBuffer = new SkPM4f[info.width()];
|
||||
} else {
|
||||
fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
|
||||
}
|
||||
}
|
||||
|
||||
~State64() {
|
||||
SkSafeUnref(fXfer);
|
||||
delete[] fBuffer;
|
||||
}
|
||||
|
||||
static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
|
||||
return device.writable_addr64(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
const int x = clip.fLeft;
|
||||
const int width = clip.width();
|
||||
int y = clip.fTop;
|
||||
int height = clip.height();
|
||||
|
||||
char* dstRow = (char*)fDevice.writable_addr32(x, y);
|
||||
const size_t dstRB = fDevice.rowBytes();
|
||||
const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
|
||||
const size_t maskRB = mask.fRowBytes;
|
||||
|
||||
do {
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
||||
fProcN(fState, reinterpret_cast<SkPMColor*>(dstRow), fBuffer, width, maskRow);
|
||||
dstRow += dstRB;
|
||||
maskRow += maskRB;
|
||||
y += 1;
|
||||
} while (--height > 0);
|
||||
}
|
||||
|
||||
void SkARGB32_Shader4f_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
|
||||
SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
|
||||
|
||||
uint32_t* device = fDevice.writable_addr32(x, y);
|
||||
size_t deviceRB = fDevice.rowBytes();
|
||||
|
||||
if (fConstInY) {
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
|
||||
do {
|
||||
fProcN(fState, device, fBuffer, 1, &alpha);
|
||||
device = (uint32_t*)((char*)device + deviceRB);
|
||||
} while (--height > 0);
|
||||
template <typename State> SkBlitter* create(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext,
|
||||
SkTBlitterAllocator* allocator) {
|
||||
SkASSERT(allocator != nullptr);
|
||||
|
||||
if (shaderContext) {
|
||||
return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, shaderContext);
|
||||
} else {
|
||||
do {
|
||||
fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
|
||||
fProcN(fState, device, fBuffer, 1, &alpha);
|
||||
y += 1;
|
||||
device = (uint32_t*)((char*)device + deviceRB);
|
||||
} while (--height > 0);
|
||||
SkColor color = paint.getColor();
|
||||
if (0 == SkColorGetA(color)) {
|
||||
return nullptr;
|
||||
}
|
||||
return allocator->createT<SkState_Blitter<State>>(device, paint);
|
||||
}
|
||||
}
|
||||
|
||||
SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext,
|
||||
SkTBlitterAllocator* allocator) {
|
||||
return create<State32>(device, paint, shaderContext, allocator);
|
||||
}
|
||||
|
||||
SkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext,
|
||||
SkTBlitterAllocator* allocator) {
|
||||
return create<State64>(device, paint, shaderContext, allocator);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ protected:
|
||||
uint32_t fShaderFlags;
|
||||
const SkShader* fShader;
|
||||
SkShader::Context* fShaderContext;
|
||||
bool fConstInY;
|
||||
|
||||
private:
|
||||
// illegal
|
||||
@ -177,7 +178,6 @@ private:
|
||||
SkBlitRow::Proc32 fProc32;
|
||||
SkBlitRow::Proc32 fProc32Blend;
|
||||
bool fShadeDirectlyIntoDevice;
|
||||
bool fConstInY;
|
||||
|
||||
// illegal
|
||||
SkARGB32_Shader_Blitter& operator=(const SkARGB32_Shader_Blitter&);
|
||||
@ -185,29 +185,13 @@ private:
|
||||
typedef SkShaderBlitter INHERITED;
|
||||
};
|
||||
|
||||
class SkARGB32_Shader4f_Blitter : public SkARGB32_Shader_Blitter {
|
||||
public:
|
||||
SkARGB32_Shader4f_Blitter(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext);
|
||||
virtual ~SkARGB32_Shader4f_Blitter();
|
||||
void blitH(int x, int y, int width) override;
|
||||
void blitV(int x, int y, int height, SkAlpha alpha) override;
|
||||
void blitRect(int x, int y, int width, int height) override;
|
||||
void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) override;
|
||||
void blitMask(const SkMask&, const SkIRect&) override;
|
||||
|
||||
private:
|
||||
SkXfermode::PM4fState fState;
|
||||
SkXfermode::PM4fProc1 fProc1;
|
||||
SkXfermode::PM4fProcN fProcN;
|
||||
SkPM4f* fBuffer;
|
||||
bool fConstInY;
|
||||
|
||||
// illegal
|
||||
SkARGB32_Shader4f_Blitter& operator=(const SkARGB32_Shader4f_Blitter&);
|
||||
|
||||
typedef SkARGB32_Shader_Blitter INHERITED;
|
||||
};
|
||||
SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext,
|
||||
SkTBlitterAllocator* allocator);
|
||||
|
||||
SkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint,
|
||||
SkShader::Context* shaderContext,
|
||||
SkTBlitterAllocator* allocator);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -117,8 +117,19 @@ SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SkShader::Context::shadeSpan4f(int x, int y, SkPM4f[], int count) {
|
||||
SkASSERT(false && "shadeSpan4f called but not implemented");
|
||||
void SkShader::Context::shadeSpan4f(int x, int y, SkPM4f dst[], int count) {
|
||||
const int N = 128;
|
||||
SkPMColor tmp[N];
|
||||
while (count > 0) {
|
||||
int n = SkTMin(count, N);
|
||||
this->shadeSpan(x, y, tmp, n);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
dst[i] = SkPM4f::FromPMColor(tmp[i]);
|
||||
}
|
||||
dst += n;
|
||||
x += n;
|
||||
count -= n;
|
||||
}
|
||||
}
|
||||
|
||||
#include "SkColorPriv.h"
|
||||
|
@ -57,6 +57,9 @@ bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
|
||||
case kN32_SkColorType:
|
||||
shift = 2;
|
||||
break;
|
||||
case kRGBA_F16_SkColorType:
|
||||
shift = 3;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ SkWindow::SkWindow()
|
||||
fClicks.reset();
|
||||
fWaitingOnInval = false;
|
||||
fMatrix.reset();
|
||||
|
||||
fBitmap.allocN32Pixels(0, 0);
|
||||
}
|
||||
|
||||
SkWindow::~SkWindow() {
|
||||
@ -52,13 +54,21 @@ void SkWindow::postConcat(const SkMatrix& matrix) {
|
||||
this->setMatrix(m);
|
||||
}
|
||||
|
||||
void SkWindow::resize(int width, int height) {
|
||||
if (width != fBitmap.width() || height != fBitmap.height()) {
|
||||
fBitmap.allocPixels(SkImageInfo::Make(width, height, kN32_SkColorType,
|
||||
kPremul_SkAlphaType));
|
||||
void SkWindow::resize(const SkImageInfo& info) {
|
||||
if (fBitmap.info() != info) {
|
||||
fBitmap.allocPixels(info);
|
||||
this->inval(nullptr);
|
||||
}
|
||||
this->setSize(SkIntToScalar(width), SkIntToScalar(height));
|
||||
this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
|
||||
}
|
||||
|
||||
void SkWindow::resize(int width, int height) {
|
||||
this->resize(fBitmap.info().makeWH(width, height));
|
||||
}
|
||||
|
||||
void SkWindow::setColorType(SkColorType ct, SkColorProfileType pt) {
|
||||
const SkImageInfo& info = fBitmap.info();
|
||||
this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, pt));
|
||||
}
|
||||
|
||||
bool SkWindow::handleInval(const SkRect* localR) {
|
||||
|
Loading…
Reference in New Issue
Block a user