aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@chromium.org>2016-02-15 07:48:35 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-15 07:48:35 -0800
commita34be68a7eff0ae475b194f8a29975460cf3e456 (patch)
tree4cec53acc400eb2788a24c320e551ebac0d27d34
parentbd6366a69ec890211496892e1a76535439ca2b30 (diff)
blitters for sRGB and float16
-rw-r--r--include/views/SkWindow.h3
-rw-r--r--samplecode/SampleApp.cpp46
-rw-r--r--samplecode/SampleApp.h1
-rw-r--r--src/core/SkBitmapDevice.cpp2
-rw-r--r--src/core/SkBlitter.cpp42
-rw-r--r--src/core/SkBlitter_PM4f.cpp422
-rw-r--r--src/core/SkCoreBlitters.h32
-rw-r--r--src/core/SkShader.cpp15
-rw-r--r--src/image/SkSurface_Raster.cpp3
-rw-r--r--src/views/SkWindow.cpp20
10 files changed, 417 insertions, 169 deletions
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);
+
+ 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<SkARGB32_Shader4f_Blitter>(
- device, *paint, shaderContext);
+#ifdef SK_FORCE_PM4f_FOR_L32_BLITS
+ if (true)
+#else
+ if (device.info().isSRGB())
+#endif
+ {
+ blitter = SkBlitter_ARGB32_Create(device, *paint, shaderContext, allocator);
+ } else {
+ 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_Shader_Blitter>(
- device, *paint, shaderContext);
+ blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
}
- } 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() {
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"
-//////////////////////////////////////////////////////////////////////////////////////
-
-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);
+template <typename State> class SkState_Blitter : public SkRasterBlitter {
+ typedef SkRasterBlitter INHERITED;
+ State fState;
- fBuffer = (SkPM4f*)sk_malloc_throw(device.width() * (sizeof(SkPM4f)));
+public:
+ SkState_Blitter(const SkPixmap& device, const SkPaint& paint)
+ : INHERITED(device)
+ , fState(device.info(), paint, nullptr)
+ {}
- fState.fXfer = SkSafeRef(paint.getXfermode());
- fState.fFlags = 0;
- if (shaderFlags & SkShader::kOpaqueAlpha_Flag) {
- fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
+ 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);
}
- 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);
+
+ 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);
+ }
}
- fConstInY = SkToBool(shaderFlags & SkShader::kConstInY32_Flag);
-}
+ 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);
+ }
-SkARGB32_Shader4f_Blitter::~SkARGB32_Shader4f_Blitter() {
- SkSafeUnref(fState.fXfer);
- sk_free(fBuffer);
-}
+ 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 SkARGB32_Shader4f_Blitter::blitH(int x, int y, int width) {
- SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
+ 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;
+ }
+ }
+};
- 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());
+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);
+ }
- uint32_t* device = fDevice.writable_addr32(x, y);
- size_t deviceRB = fDevice.rowBytes();
+ 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);
+ }
+ }
- 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 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 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;
- }
- 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);
+ 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;
}
- 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;
+ 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;
- SkASSERT(mask.fBounds.contains(clip));
-
- const int x = clip.fLeft;
- const int width = clip.width();
- int y = clip.fTop;
- int height = clip.height();
+ typedef SkShaderBlitter INHERITED;
+};
- 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);
+static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderContext) {
+ return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)
+ : 0xFF == paint.getAlpha();
}
-void SkARGB32_Shader4f_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
- SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
+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;
+ }
+ 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);
+ }
- uint32_t* device = fDevice.writable_addr32(x, y);
- size_t deviceRB = fDevice.rowBytes();
+ fBuffer = nullptr;
+ if (shaderContext) {
+ fBuffer = new SkPM4f[info.width()];
+ } else {
+ fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
+ }
+ }
+
+ ~State32() {
+ SkSafeUnref(fXfer);
+ delete[] fBuffer;
+ }
+
+ static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
+ return device.writable_addr32(x, y);
+ }
+};
- if (fConstInY) {
- fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
- do {
- fProcN(fState, device, fBuffer, 1, &alpha);
- device = (uint32_t*)((char*)device + deviceRB);
- } while (--height > 0);
+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);
+ }
+};
+
+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);
+}
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) {