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:
reed 2016-02-15 07:48:35 -08:00 committed by Commit bot
parent bd6366a69e
commit a34be68a7e
10 changed files with 435 additions and 187 deletions

View File

@ -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);

View File

@ -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());
}

View File

@ -118,6 +118,7 @@ public:
void draw(SkCanvas*) override;
void setDeviceType(DeviceType type);
void setDeviceColorType(SkColorType, SkColorProfileType);
void toggleRendering();
void toggleSlideshow();
void toggleFPS();

View File

@ -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;
}

View File

@ -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() {

View File

@ -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);
}

View File

@ -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);
///////////////////////////////////////////////////////////////////////////////

View File

@ -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"

View File

@ -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;
}

View File

@ -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) {