aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-05-31 14:18:07 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-01 15:02:08 +0000
commit5cc9da6bbc6a599ab5e83a365fa20456e710c52c (patch)
tree3668d3905268daa7beceb4b6173cb880dab6d8bb
parentc6912f712f3423b2a09a6e96c999b65a1fd86062 (diff)
raster pipeline sprite blitter
The color in the unit test turned out to be right on the edge of not round tripping well, and I guess rounding pushed it over the edge, so I've tweaked it to a new one that seems better. Change-Id: I46095fafc9d6b68fd417ff9dc32003f42929c5a5 Reviewed-on: https://skia-review.googlesource.com/18238 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
-rw-r--r--src/core/SkBlitter_Sprite.cpp97
-rw-r--r--tests/CachedDecodingPixelRefTest.cpp2
2 files changed, 88 insertions, 11 deletions
diff --git a/src/core/SkBlitter_Sprite.cpp b/src/core/SkBlitter_Sprite.cpp
index fd147a1cbc..d82f3dba78 100644
--- a/src/core/SkBlitter_Sprite.cpp
+++ b/src/core/SkBlitter_Sprite.cpp
@@ -6,8 +6,11 @@
*/
#include "SkArenaAlloc.h"
-#include "SkColorSpace_Base.h"
+#include "SkColorSpace.h"
+#include "SkCoreBlitters.h"
#include "SkOpts.h"
+#include "SkPM4fPriv.h"
+#include "SkRasterPipeline.h"
#include "SkSpriteBlitter.h"
SkSpriteBlitter::SkSpriteBlitter(const SkPixmap& source)
@@ -92,6 +95,82 @@ private:
typedef SkSpriteBlitter INHERITED;
};
+class SkRasterPipelineSpriteBlitter : public SkSpriteBlitter {
+public:
+ SkRasterPipelineSpriteBlitter(const SkPixmap& src, SkArenaAlloc* alloc)
+ : INHERITED(src)
+ , fAlloc(alloc)
+ , fBlitter(nullptr)
+ , fSrcPtr(nullptr)
+ {}
+
+ static bool Supports(const SkPixmap& src) {
+ // We'd need to add a load_i8 stage.
+ return src.colorType() != kIndex_8_SkColorType;
+ }
+
+ void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
+ fDst = dst;
+ fLeft = left;
+ fTop = top;
+
+ fPaintColor = SkColor4f_from_SkColor(paint.getColor(), fDst.colorSpace());
+
+ SkRasterPipeline p(fAlloc);
+ switch (fSource.colorType()) {
+ case kAlpha_8_SkColorType: p.append(SkRasterPipeline::load_a8, &fSrcPtr); break;
+ case kGray_8_SkColorType: p.append(SkRasterPipeline::load_g8, &fSrcPtr); break;
+ case kRGB_565_SkColorType: p.append(SkRasterPipeline::load_565, &fSrcPtr); break;
+ case kARGB_4444_SkColorType: p.append(SkRasterPipeline::load_4444, &fSrcPtr); break;
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType: p.append(SkRasterPipeline::load_8888, &fSrcPtr); break;
+ case kRGBA_F16_SkColorType: p.append(SkRasterPipeline::load_f16, &fSrcPtr); break;
+ default: SkASSERT(false);
+ }
+ if (fDst.colorSpace() &&
+ (!fSource.colorSpace() || fSource.colorSpace()->gammaCloseToSRGB())) {
+ p.append_from_srgb(fSource.alphaType());
+ }
+ if (fSource.colorType() == kBGRA_8888_SkColorType) {
+ p.append(SkRasterPipeline::swap_rb);
+ }
+ if (fSource.colorType() == kAlpha_8_SkColorType) {
+ p.append(SkRasterPipeline::set_rgb, &fPaintColor);
+ p.append(SkRasterPipeline::premul);
+ }
+ append_gamut_transform(&p, fAlloc,
+ fSource.colorSpace(), fDst.colorSpace(), kPremul_SkAlphaType);
+ if (fPaintColor.fA != 1.0f) {
+ p.append(SkRasterPipeline::scale_1_float, &fPaintColor.fA);
+ }
+
+ bool is_opaque = fSource.isOpaque() && fPaintColor.fA == 1.0f,
+ wants_dither = paint.isDither();
+ fBlitter = SkCreateRasterPipelineBlitter(fDst, paint, p, is_opaque, wants_dither, fAlloc);
+ }
+
+ void blitRect(int x, int y, int width, int height) override {
+ fSrcPtr = (const char*)fSource.addr(x-fLeft,y-fTop);
+
+ // Our pipeline will load from fSrcPtr+x, fSrcPtr+x+1, etc.,
+ // so we back up an extra x pixels to start at 0.
+ fSrcPtr -= fSource.info().bytesPerPixel() * x;
+
+ while (height --> 0) {
+ fBlitter->blitH(x,y++, width);
+ fSrcPtr += fSource.rowBytes();
+ }
+ }
+
+private:
+ SkArenaAlloc* fAlloc;
+ SkBlitter* fBlitter;
+ const char* fSrcPtr;
+ SkColor4f fPaintColor;
+
+ typedef SkSpriteBlitter INHERITED;
+};
+
// returning null means the caller will call SkBlitter::Choose() and
// have wrapped the source bitmap inside a shader
SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint,
@@ -113,16 +192,14 @@ SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint,
SkSpriteBlitter* blitter = nullptr;
- if (SkSpriteBlitter_Memcpy::Supports(dst, source, paint)) {
+ if (!blitter && SkSpriteBlitter_Memcpy::Supports(dst, source, paint)) {
blitter = allocator->make<SkSpriteBlitter_Memcpy>(source);
- } else if (!dst.colorSpace()) {
- switch (dst.colorType()) {
- case kN32_SkColorType:
- blitter = SkSpriteBlitter::ChooseL32(source, paint, allocator);
- break;
- default:
- break;
- }
+ }
+ if (!blitter && !dst.colorSpace() && dst.colorType() == kN32_SkColorType) {
+ blitter = SkSpriteBlitter::ChooseL32(source, paint, allocator);
+ }
+ if (!blitter && SkRasterPipelineSpriteBlitter::Supports(source)) {
+ blitter = allocator->make<SkRasterPipelineSpriteBlitter>(source, allocator);
}
if (blitter) {
diff --git a/tests/CachedDecodingPixelRefTest.cpp b/tests/CachedDecodingPixelRefTest.cpp
index 8878d6dd2e..0eecdbb55a 100644
--- a/tests/CachedDecodingPixelRefTest.cpp
+++ b/tests/CachedDecodingPixelRefTest.cpp
@@ -29,7 +29,7 @@ public:
static int Width() { return 10; }
static int Height() { return 10; }
// value choosen so that there is no loss when converting to to RGB565 and back
- static SkColor Color() { return 0xff10345a; }
+ static SkColor Color() { return 0xff10355a; }
static SkPMColor PMColor() { return SkPreMultiplyColor(Color()); }
TestImageGenerator(TestType type, skiatest::Reporter* reporter,