Index: src/core/SkRasterPipelineBlitter.cpp |
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp |
index 169bb9f74b83586cb15396841468c896e70a1a0a..9d89b4dcfceeb8cd327c11d8e0b2091cfc0c9993 100644 |
--- a/src/core/SkRasterPipelineBlitter.cpp |
+++ b/src/core/SkRasterPipelineBlitter.cpp |
@@ -9,7 +9,6 @@ |
#include "SkColor.h" |
#include "SkColorFilter.h" |
#include "SkPM4f.h" |
-#include "SkPM4fPriv.h" |
#include "SkRasterPipeline.h" |
#include "SkShader.h" |
#include "SkSRGB.h" |
@@ -57,6 +56,22 @@ SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst, |
return SkRasterPipelineBlitter::Create(dst, paint, alloc); |
} |
+// Clamp colors into [0,1] premul (e.g. just before storing back to memory). |
+static void SK_VECTORCALL clamp_01_premul(SkRasterPipeline::Stage* st, size_t x, |
+ Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
+ Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
+ a = Sk4f::Max(a, 0.0f); |
+ r = Sk4f::Max(r, 0.0f); |
+ g = Sk4f::Max(g, 0.0f); |
+ b = Sk4f::Max(b, 0.0f); |
+ |
+ a = Sk4f::Min(a, 1.0f); |
+ r = Sk4f::Min(r, a); |
+ g = Sk4f::Min(g, a); |
+ b = Sk4f::Min(b, a); |
+ |
+ st->next(x, r,g,b,a, dr,dg,db,da); |
+} |
// The default shader produces a constant color (from the SkPaint). |
static void SK_VECTORCALL constant_color(SkRasterPipeline::Stage* st, size_t x, |
@@ -255,10 +270,10 @@ static void SK_VECTORCALL store_srgb(SkRasterPipeline::Stage* st, size_t x, |
Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
auto dst = st->ctx<uint32_t*>() + x; |
- ( sk_linear_to_srgb(r) << SK_R32_SHIFT |
- | sk_linear_to_srgb(g) << SK_G32_SHIFT |
- | sk_linear_to_srgb(b) << SK_B32_SHIFT |
- | Sk4f_round(255.0f*a) << SK_A32_SHIFT).store(dst); |
+ ( sk_linear_to_srgb_noclamp(r) << SK_R32_SHIFT |
+ | sk_linear_to_srgb_noclamp(g) << SK_G32_SHIFT |
+ | sk_linear_to_srgb_noclamp(b) << SK_B32_SHIFT |
+ | Sk4f_round(255.0f * a) << SK_A32_SHIFT).store(dst); |
} |
// Tail variant of store_srgb() handling 1 pixel at a time. |
@@ -266,7 +281,12 @@ static void SK_VECTORCALL store_srgb_1(SkRasterPipeline::Stage* st, size_t x, |
Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
auto dst = st->ctx<uint32_t*>() + x; |
- *dst = Sk4f_toS32(swizzle_rb_if_bgra({ r[0], g[0], b[0], a[0] })); |
+ Sk4i rgb = sk_linear_to_srgb_noclamp(swizzle_rb_if_bgra({ r[0], g[0], b[0], 0.0f })); |
+ |
+ uint32_t rgba; |
+ SkNx_cast<uint8_t>(rgb).store(&rgba); |
+ rgba |= (uint32_t)(255.0f * a[0] + 0.5f) << 24; |
+ *dst = rgba; |
} |
static bool supported(const SkImageInfo& info) { |
@@ -343,6 +363,7 @@ void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst |
void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const { |
SkASSERT(supported(fDst.info())); |
+ p->append(clamp_01_premul); |
switch (fDst.info().colorType()) { |
case kN32_SkColorType: |
if (fDst.info().gammaCloseToSRGB()) { |