diff options
author | 2016-11-17 12:39:09 -0500 | |
---|---|---|
committer | 2016-11-17 18:45:25 +0000 | |
commit | 06a65e2799eaead18f778792801406aff4aec0d9 (patch) | |
tree | 53128b0fa2f92989825516ca04a7bf7188322d8b /src/image/SkImageShader.cpp | |
parent | 9fab7e98d711968df3ec4fd2f3fe5c40820b2a0d (diff) |
Support SkImageShader in SkRasterPipeline blitter
First of many CLs, I'm sure.
This handles 8888 or sRGB sources with an affine matrix, clamp/clamp tiling, and nearest-neighbor sampling only.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4906
CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot
Change-Id: I99f7508852b3d44b6f52f7a0bee29a793af35c48
Reviewed-on: https://skia-review.googlesource.com/4906
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/image/SkImageShader.cpp')
-rw-r--r-- | src/image/SkImageShader.cpp | 119 |
1 files changed, 115 insertions, 4 deletions
diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp index 8f8f6a32ba..152007d6e8 100644 --- a/src/image/SkImageShader.cpp +++ b/src/image/SkImageShader.cpp @@ -10,8 +10,10 @@ #include "SkColorShader.h" #include "SkColorTable.h" #include "SkEmptyShader.h" +#include "SkFixedAlloc.h" #include "SkImage_Base.h" #include "SkImageShader.h" +#include "SkPM4fPriv.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -92,7 +94,7 @@ static bool bitmap_is_too_big(int w, int h) { // widen that, we have to reject bitmaps that are larger. // static const int kMaxSize = 65535; - + return w > kMaxSize || h > kMaxSize; } @@ -103,16 +105,16 @@ static bool can_use_color_shader(const SkImage* image, SkColor* color) { // HWUI does not support color shaders (see b/22390304) return false; #endif - + if (1 != image->width() || 1 != image->height()) { return false; } - + SkPixmap pmap; if (!image->peekPixels(&pmap)) { return false; } - + switch (pmap.colorType()) { case kN32_SkColorType: *color = SkUnPreMultiply::PMColorToColor(*pmap.addr32(0, 0)); @@ -263,3 +265,112 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageShader) SkFlattenable::Register("SkBitmapProcShader", SkBitmapProcShader_CreateProc, kSkShader_Type); SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END + +bool SkImageShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* dst, SkFallbackAlloc* scratch, + const SkMatrix& ctm, SkFilterQuality quality) const { + SkPixmap pm; + if (!fImage->peekPixels(&pm)) { + return false; + } + auto info = pm.info(); + + + auto matrix = SkMatrix::Concat(ctm, this->getLocalMatrix()); + if (!matrix.invert(&matrix)) { + return false; + } + + // TODO: perspective + if (!matrix.asAffine(nullptr)) { + return false; + } + + // TODO: all formats + switch (info.colorType()) { + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: +// case kRGB_565_SkColorType: +// case kRGBA_F16_SkColorType: + break; + default: return false; + } + + // TODO: all tile modes + if (fTileModeX != kClamp_TileMode || fTileModeY != kClamp_TileMode) { + return false; + } + + // TODO: bilerp + if (quality != kNone_SkFilterQuality) { + return false; + } + + // TODO: mtklein doesn't understand why we do this. + if (quality == kNone_SkFilterQuality) { + if (matrix.getScaleX() >= 0) { + matrix.setTranslateX(nextafterf(matrix.getTranslateX(), + floorf(matrix.getTranslateX()))); + } + if (matrix.getScaleY() >= 0) { + matrix.setTranslateY(nextafterf(matrix.getTranslateY(), + floorf(matrix.getTranslateY()))); + } + } + + struct context { + const void* pixels; + int stride; + int width; + int height; + float matrix[6]; + }; + auto ctx = scratch->make<context>(); + + ctx->pixels = pm.addr(); + ctx->stride = pm.rowBytesAsPixels(); + ctx->width = pm.width(); + ctx->height = pm.height(); + SkAssertResult(matrix.asAffine(ctx->matrix)); + + p->append(SkRasterPipeline::matrix_2x3, &ctx->matrix); + + switch (fTileModeX) { + case kClamp_TileMode: p->append(SkRasterPipeline::clamp_x, &ctx->width); break; + case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, &ctx->width); break; + case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, &ctx->width); break; + } + switch (fTileModeY) { + case kClamp_TileMode: p->append(SkRasterPipeline::clamp_y, &ctx->height); break; + case kMirror_TileMode: p->append(SkRasterPipeline::mirror_y, &ctx->height); break; + case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_y, &ctx->height); break; + } + + switch(info.colorType()) { + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: + if (info.gammaCloseToSRGB() && dst) { + p->append(SkRasterPipeline::nearest_srgb, ctx); + } else { + p->append(SkRasterPipeline::nearest_8888, ctx); + } + break; + case kRGBA_F16_SkColorType: + p->append(SkRasterPipeline::nearest_f16, ctx); + break; + case kRGB_565_SkColorType: + p->append(SkRasterPipeline::nearest_565, ctx); + break; + + default: + SkASSERT(false); + break; + } + + if (info.colorType() == kBGRA_8888_SkColorType) { + p->append(SkRasterPipeline::swap_rb); + } + if (info.alphaType() == kUnpremul_SkAlphaType) { + p->append(SkRasterPipeline::premul); + } + return append_gamut_transform(p, scratch, info.colorSpace(), dst); +} |