Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Unified Diff: src/core/SkBlitter_PM4f.cpp

Issue 1697863002: blitters for sRGB and float16 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkBlitter.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkBlitter_PM4f.cpp
diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp
index bd8ae493dab9f2bca50d98eb07f3c02163a66d25..01fd70425423967cc835f4e93d3226af9fa4793e 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);
+}
« no previous file with comments | « src/core/SkBlitter.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698