diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h index 6db85a421c..850a7e7211 100644 --- a/include/views/SkWindow.h +++ b/include/views/SkWindow.h @@ -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); diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 65e3c17a44..61cd75149f 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -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()); } diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h index 56cf98428b..d4157fa415 100644 --- a/samplecode/SampleApp.h +++ b/samplecode/SampleApp.h @@ -118,6 +118,7 @@ public: void draw(SkCanvas*) override; void setDeviceType(DeviceType type); + void setDeviceColorType(SkColorType, SkColorProfileType); void toggleRendering(); void toggleSlideshow(); void toggleFPS(); diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index a7ca7b7181..8c3c562181 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -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; } diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index eec31525a6..45219c50cb 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -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( - device, *paint, shaderContext); - } else { - blitter = allocator->createT( - device, *paint, shaderContext); - } - } else if (paint->getColor() == SK_ColorBLACK) { - blitter = allocator->createT(device, *paint); - } else if (paint->getAlpha() == 0xFF) { - blitter = allocator->createT(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(device, *paint); + if (shader) { + blitter = allocator->createT( + device, *paint, shaderContext); + } else if (paint->getColor() == SK_ColorBLACK) { + blitter = allocator->createT(device, *paint); + } else if (paint->getAlpha() == 0xFF) { + blitter = allocator->createT(device, *paint); + } else { + blitter = allocator->createT(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(); @@ -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() { diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp index bd8ae493da..01fd704254 100644 --- a/src/core/SkBlitter_PM4f.cpp +++ b/src/core/SkBlitter_PM4f.cpp @@ -11,149 +11,339 @@ #include "SkUtils.h" #include "SkXfermode.h" #include "SkBlitMask.h" +#include "SkTemplates.h" + +template 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 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(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 SkBlitter* create(const SkPixmap& device, const SkPaint& paint, + SkShader::Context* shaderContext, + SkTBlitterAllocator* allocator) { + SkASSERT(allocator != nullptr); + + if (shaderContext) { + return allocator->createT>(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>(device, paint); } } + +SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint, + SkShader::Context* shaderContext, + SkTBlitterAllocator* allocator) { + return create(device, paint, shaderContext, allocator); +} + +SkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint, + SkShader::Context* shaderContext, + SkTBlitterAllocator* allocator) { + return create(device, paint, shaderContext, allocator); +} diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index d2559f565b..06e106dd8e 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -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); /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index 856b659213..4b5dc5dc06 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -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" diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp index 52300c3bde..d9763c0c95 100644 --- a/src/image/SkSurface_Raster.cpp +++ b/src/image/SkSurface_Raster.cpp @@ -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; } diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp index 0e6da0b02d..ebe56b0e95 100644 --- a/src/views/SkWindow.cpp +++ b/src/views/SkWindow.cpp @@ -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) {