aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/image/SkImageShader.cpp
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2016-11-17 12:39:09 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-17 18:45:25 +0000
commit06a65e2799eaead18f778792801406aff4aec0d9 (patch)
tree53128b0fa2f92989825516ca04a7bf7188322d8b /src/image/SkImageShader.cpp
parent9fab7e98d711968df3ec4fd2f3fe5c40820b2a0d (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.cpp119
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);
+}