diff options
author | Mike Reed <reed@google.com> | 2017-10-05 16:04:41 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-05 20:25:04 +0000 |
commit | ef8ce2858b7692c9ec9874c43656e603f304c760 (patch) | |
tree | 1b3abd8bd47acfc2e13168df79b58d82878df097 /src/core/SkSpriteBlitter_RGB565.cpp | |
parent | ded7aa82afa9672002fcd2a0eff09db59bfd0010 (diff) |
experiments to speed up drawing 32bit images into 565
New (legacy style) blitters only coded for shaders (and very restricted blendmodes)
Bug: skia:
See https://buganizer.corp.google.com/issues/64884885
Change-Id: Ie2546093bfe1e670a825dfd9542d252d53732c40
Reviewed-on: https://skia-review.googlesource.com/54103
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core/SkSpriteBlitter_RGB565.cpp')
-rw-r--r-- | src/core/SkSpriteBlitter_RGB565.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/core/SkSpriteBlitter_RGB565.cpp b/src/core/SkSpriteBlitter_RGB565.cpp new file mode 100644 index 0000000000..8151347ceb --- /dev/null +++ b/src/core/SkSpriteBlitter_RGB565.cpp @@ -0,0 +1,179 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSpriteBlitter.h" +#include "SkArenaAlloc.h" +#include "SkBlitRow.h" +#include "SkColorFilter.h" +#include "SkColorData.h" +#include "SkTemplates.h" +#include "SkUtils.h" +#include "SkXfermodePriv.h" + +/////////////////////////////////////////////////////////////////////////////// + +static void S32_src(uint16_t dst[], const SkPMColor src[], int count) { + for (int i = 0; i < count; ++i) { + dst[i] = SkPixel32ToPixel16(src[i]); + } +} + +static void S32_srcover(uint16_t dst[], const SkPMColor src[], int count) { + for (int i = 0; i < count; ++i) { + dst[i] = SkSrcOver32To16(src[i], dst[i]); + } +} + +class Sprite_D16_S32 : public SkSpriteBlitter { +public: + Sprite_D16_S32(const SkPixmap& src, SkBlendMode mode) : INHERITED(src) { + SkASSERT(src.colorType() == kN32_SkColorType); + SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver); + + fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque(); + } + + void blitRect(int x, int y, int width, int height) override { + SkASSERT(width > 0 && height > 0); + uint16_t* SK_RESTRICT dst = fDst.writable_addr16(x, y); + const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); + size_t dstRB = fDst.rowBytes(); + size_t srcRB = fSource.rowBytes(); + + do { + if (fUseSrcOver) { + S32_srcover(dst, src, width); + } else { + S32_src(dst, src, width); + } + + dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB); + src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); + } while (--height != 0); + } + +private: + bool fUseSrcOver; + + typedef SkSpriteBlitter INHERITED; +}; + +SkSpriteBlitter* SkSpriteBlitter::ChooseL565(const SkPixmap& source, const SkPaint& paint, + SkArenaAlloc* allocator) { + SkASSERT(allocator != nullptr); + + if (paint.getColorFilter() != nullptr) { + return nullptr; + } + if (paint.getMaskFilter() != nullptr) { + return nullptr; + } + + U8CPU alpha = paint.getAlpha(); + if (alpha != 0xFF) { + return nullptr; + } + + if (source.colorType() == kN32_SkColorType) { + switch (paint.getBlendMode()) { + case SkBlendMode::kSrc: + case SkBlendMode::kSrcOver: + return allocator->make<Sprite_D16_S32>(source, paint.getBlendMode()); + default: + break; + } + } + return nullptr; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +static unsigned div255(unsigned a, unsigned b) { + return (a * b * 257 + 127) >> 16; +} + +static void S32_src_da8(uint8_t dst[], const SkPMColor src[], int count) { + for (int i = 0; i < count; ++i) { + dst[i] = SkGetPackedA32(src[i]); + } +} + +static void S32_srcover_da8(uint8_t dst[], const SkPMColor src[], int count) { + for (int i = 0; i < count; ++i) { + SkPMColor c = src[i]; + if (c) { + unsigned a = SkGetPackedA32(c); + if (a == 0xFF) { + dst[i] = 0xFF; + } else { + dst[i] = a + div255(255 - a, dst[i]); + } + } + } +} + +class Sprite_D8_S32 : public SkSpriteBlitter { +public: + Sprite_D8_S32(const SkPixmap& src, SkBlendMode mode) : INHERITED(src) { + SkASSERT(src.colorType() == kN32_SkColorType); + SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver); + + fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque(); + } + + void blitRect(int x, int y, int width, int height) override { + SkASSERT(width > 0 && height > 0); + uint8_t* SK_RESTRICT dst = fDst.writable_addr8(x, y); + const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); + size_t dstRB = fDst.rowBytes(); + size_t srcRB = fSource.rowBytes(); + + do { + if (fUseSrcOver) { + S32_srcover_da8(dst, src, width); + } else { + S32_src_da8(dst, src, width); + } + + dst = (uint8_t* SK_RESTRICT)((char*)dst + dstRB); + src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); + } while (--height != 0); + } + +private: + bool fUseSrcOver; + + typedef SkSpriteBlitter INHERITED; +}; + +SkSpriteBlitter* SkSpriteBlitter::ChooseLA8(const SkPixmap& source, const SkPaint& paint, + SkArenaAlloc* allocator) { + SkASSERT(allocator != nullptr); + + if (paint.getColorFilter() != nullptr) { + return nullptr; + } + if (paint.getMaskFilter() != nullptr) { + return nullptr; + } + + U8CPU alpha = paint.getAlpha(); + if (alpha != 0xFF) { + return nullptr; + } + + if (source.colorType() == kN32_SkColorType) { + switch (paint.getBlendMode()) { + case SkBlendMode::kSrc: + case SkBlendMode::kSrcOver: + return allocator->make<Sprite_D8_S32>(source, paint.getBlendMode()); + default: + break; + } + } + return nullptr; +} |