| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBlitter.h" | 8 #include "SkBlitter.h" |
| 9 #include "SkColor.h" | 9 #include "SkColor.h" |
| 10 #include "SkColorFilter.h" | 10 #include "SkColorFilter.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 typedef SkBlitter INHERITED; | 51 typedef SkBlitter INHERITED; |
| 52 }; | 52 }; |
| 53 | 53 |
| 54 SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst, | 54 SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst, |
| 55 const SkPaint& paint, | 55 const SkPaint& paint, |
| 56 SkTBlitterAllocator* alloc) { | 56 SkTBlitterAllocator* alloc) { |
| 57 return SkRasterPipelineBlitter::Create(dst, paint, alloc); | 57 return SkRasterPipelineBlitter::Create(dst, paint, alloc); |
| 58 } | 58 } |
| 59 | 59 |
| 60 // Clamp colors into [0,1] premul (e.g. just before storing back to memory). | 60 // Clamp colors into [0,1] premul (e.g. just before storing back to memory). |
| 61 static void SK_VECTORCALL clamp_01_premul(SkRasterPipeline::Stage* st, size_t x, | 61 SK_RASTER_STAGE(clamp_01_premul) { |
| 62 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | |
| 63 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 64 a = Sk4f::Max(a, 0.0f); | 62 a = Sk4f::Max(a, 0.0f); |
| 65 r = Sk4f::Max(r, 0.0f); | 63 r = Sk4f::Max(r, 0.0f); |
| 66 g = Sk4f::Max(g, 0.0f); | 64 g = Sk4f::Max(g, 0.0f); |
| 67 b = Sk4f::Max(b, 0.0f); | 65 b = Sk4f::Max(b, 0.0f); |
| 68 | 66 |
| 69 a = Sk4f::Min(a, 1.0f); | 67 a = Sk4f::Min(a, 1.0f); |
| 70 r = Sk4f::Min(r, a); | 68 r = Sk4f::Min(r, a); |
| 71 g = Sk4f::Min(g, a); | 69 g = Sk4f::Min(g, a); |
| 72 b = Sk4f::Min(b, a); | 70 b = Sk4f::Min(b, a); |
| 73 | |
| 74 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 75 } | 71 } |
| 76 | 72 |
| 77 // The default shader produces a constant color (from the SkPaint). | 73 // The default shader produces a constant color (from the SkPaint). |
| 78 static void SK_VECTORCALL constant_color(SkRasterPipeline::Stage* st, size_t x, | 74 SK_RASTER_STAGE(constant_color) { |
| 79 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 75 auto color = (const SkPM4f*)ctx; |
| 80 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 81 auto color = st->ctx<const SkPM4f*>(); | |
| 82 r = color->r(); | 76 r = color->r(); |
| 83 g = color->g(); | 77 g = color->g(); |
| 84 b = color->b(); | 78 b = color->b(); |
| 85 a = color->a(); | 79 a = color->a(); |
| 86 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 87 } | 80 } |
| 88 | 81 |
| 89 // The default transfer mode is srcover, s' = s + d*(1-sa). | 82 // The default transfer mode is srcover, s' = s + d*(1-sa). |
| 90 static void SK_VECTORCALL srcover(SkRasterPipeline::Stage* st, size_t x, | 83 SK_RASTER_STAGE(srcover) { |
| 91 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 84 r += dr*(1.0f - a); |
| 92 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | 85 g += dg*(1.0f - a); |
| 93 auto A = 1.0f - a; | 86 b += db*(1.0f - a); |
| 94 r += dr*A; | 87 a += da*(1.0f - a); |
| 95 g += dg*A; | |
| 96 b += db*A; | |
| 97 a += da*A; | |
| 98 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 99 } | 88 } |
| 100 | 89 |
| 101 static Sk4f lerp(const Sk4f& from, const Sk4f& to, const Sk4f& cov) { | 90 static Sk4f lerp(const Sk4f& from, const Sk4f& to, const Sk4f& cov) { |
| 102 return from + (to-from)*cov; | 91 return from + (to-from)*cov; |
| 103 } | 92 } |
| 104 | 93 |
| 105 // s' = d(1-c) + sc, for a constant c. | 94 // s' = d(1-c) + sc, for a constant c. |
| 106 static void SK_VECTORCALL lerp_constant_float(SkRasterPipeline::Stage* st, size_
t x, | 95 SK_RASTER_STAGE(lerp_constant_float) { |
| 107 Sk4f r, Sk4f g, Sk4f b, Sk4f a
, | 96 Sk4f c = *(const float*)ctx; |
| 108 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da
) { | |
| 109 Sk4f c = *st->ctx<const float*>(); | |
| 110 | 97 |
| 111 r = lerp(dr, r, c); | 98 r = lerp(dr, r, c); |
| 112 g = lerp(dg, g, c); | 99 g = lerp(dg, g, c); |
| 113 b = lerp(db, b, c); | 100 b = lerp(db, b, c); |
| 114 a = lerp(da, a, c); | 101 a = lerp(da, a, c); |
| 115 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 116 } | 102 } |
| 117 | 103 |
| 118 // s' = d(1-c) + sc, 4 pixels at a time for 8-bit coverage. | 104 // s' = d(1-c) + sc, 4 pixels at a time for 8-bit coverage. |
| 119 static void SK_VECTORCALL lerp_a8(SkRasterPipeline::Stage* st, size_t x, | 105 SK_RASTER_STAGE(lerp_a8) { |
| 120 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 106 auto ptr = (const uint8_t*)ctx + x; |
| 121 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 122 auto ptr = st->ctx<const uint8_t*>() + x; | |
| 123 Sk4f c = SkNx_cast<float>(Sk4b::Load(ptr)) * (1/255.0f); | 107 Sk4f c = SkNx_cast<float>(Sk4b::Load(ptr)) * (1/255.0f); |
| 124 | 108 |
| 125 r = lerp(dr, r, c); | 109 r = lerp(dr, r, c); |
| 126 g = lerp(dg, g, c); | 110 g = lerp(dg, g, c); |
| 127 b = lerp(db, b, c); | 111 b = lerp(db, b, c); |
| 128 a = lerp(da, a, c); | 112 a = lerp(da, a, c); |
| 129 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 130 } | 113 } |
| 131 | 114 |
| 132 // Tail variant of lerp_a8() handling 1 pixel at a time. | 115 // Tail variant of lerp_a8() handling 1 pixel at a time. |
| 133 static void SK_VECTORCALL lerp_a8_1(SkRasterPipeline::Stage* st, size_t x, | 116 SK_RASTER_STAGE(lerp_a8_1) { |
| 134 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 117 auto ptr = (const uint8_t*)ctx + x; |
| 135 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 136 auto ptr = st->ctx<const uint8_t*>() + x; | |
| 137 Sk4f c = *ptr * (1/255.0f); | 118 Sk4f c = *ptr * (1/255.0f); |
| 138 | 119 |
| 139 r = lerp(dr, r, c); | 120 r = lerp(dr, r, c); |
| 140 g = lerp(dg, g, c); | 121 g = lerp(dg, g, c); |
| 141 b = lerp(db, b, c); | 122 b = lerp(db, b, c); |
| 142 a = lerp(da, a, c); | 123 a = lerp(da, a, c); |
| 143 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 144 } | 124 } |
| 145 | 125 |
| 146 static void from_565(const Sk4h& _565, Sk4f* r, Sk4f* g, Sk4f* b) { | 126 static void from_565(const Sk4h& _565, Sk4f* r, Sk4f* g, Sk4f* b) { |
| 147 Sk4i _32_bit = SkNx_cast<int>(_565); | 127 Sk4i _32_bit = SkNx_cast<int>(_565); |
| 148 | 128 |
| 149 *r = SkNx_cast<float>(_32_bit & SK_R16_MASK_IN_PLACE) * (1.0f / SK_R16_MASK_
IN_PLACE); | 129 *r = SkNx_cast<float>(_32_bit & SK_R16_MASK_IN_PLACE) * (1.0f / SK_R16_MASK_
IN_PLACE); |
| 150 *g = SkNx_cast<float>(_32_bit & SK_G16_MASK_IN_PLACE) * (1.0f / SK_G16_MASK_
IN_PLACE); | 130 *g = SkNx_cast<float>(_32_bit & SK_G16_MASK_IN_PLACE) * (1.0f / SK_G16_MASK_
IN_PLACE); |
| 151 *b = SkNx_cast<float>(_32_bit & SK_B16_MASK_IN_PLACE) * (1.0f / SK_B16_MASK_
IN_PLACE); | 131 *b = SkNx_cast<float>(_32_bit & SK_B16_MASK_IN_PLACE) * (1.0f / SK_B16_MASK_
IN_PLACE); |
| 152 } | 132 } |
| 153 | 133 |
| 154 static Sk4h to_565(const Sk4f& r, const Sk4f& g, const Sk4f& b) { | 134 static Sk4h to_565(const Sk4f& r, const Sk4f& g, const Sk4f& b) { |
| 155 return SkNx_cast<uint16_t>( Sk4f_round(r * SK_R16_MASK) << SK_R16_SHIFT | 135 return SkNx_cast<uint16_t>( Sk4f_round(r * SK_R16_MASK) << SK_R16_SHIFT |
| 156 | Sk4f_round(g * SK_G16_MASK) << SK_G16_SHIFT | 136 | Sk4f_round(g * SK_G16_MASK) << SK_G16_SHIFT |
| 157 | Sk4f_round(b * SK_B16_MASK) << SK_B16_SHIFT); | 137 | Sk4f_round(b * SK_B16_MASK) << SK_B16_SHIFT); |
| 158 } | 138 } |
| 159 | 139 |
| 160 // s' = d(1-c) + sc, 4 pixels at a time for 565 coverage. | 140 // s' = d(1-c) + sc, 4 pixels at a time for 565 coverage. |
| 161 static void SK_VECTORCALL lerp_lcd16(SkRasterPipeline::Stage* st, size_t x, | 141 SK_RASTER_STAGE(lerp_lcd16) { |
| 162 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 142 auto ptr = (const uint16_t*)ctx + x; |
| 163 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 164 auto ptr = st->ctx<const uint16_t*>() + x; | |
| 165 Sk4f cr, cg, cb; | 143 Sk4f cr, cg, cb; |
| 166 from_565(Sk4h::Load(ptr), &cr, &cg, &cb); | 144 from_565(Sk4h::Load(ptr), &cr, &cg, &cb); |
| 167 | 145 |
| 168 r = lerp(dr, r, cr); | 146 r = lerp(dr, r, cr); |
| 169 g = lerp(dg, g, cg); | 147 g = lerp(dg, g, cg); |
| 170 b = lerp(db, b, cb); | 148 b = lerp(db, b, cb); |
| 171 a = 1.0f; | 149 a = 1.0f; |
| 172 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 173 } | 150 } |
| 174 | 151 |
| 175 // Tail variant of lerp_lcd16() handling 1 pixel at a time. | 152 // Tail variant of lerp_lcd16() handling 1 pixel at a time. |
| 176 static void SK_VECTORCALL lerp_lcd16_1(SkRasterPipeline::Stage* st, size_t x, | 153 SK_RASTER_STAGE(lerp_lcd16_1) { |
| 177 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 154 auto ptr = (const uint16_t*)ctx + x; |
| 178 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 179 auto ptr = st->ctx<const uint16_t*>() + x; | |
| 180 Sk4f cr, cg, cb; | 155 Sk4f cr, cg, cb; |
| 181 from_565({*ptr,0,0,0}, &cr, &cg, &cb); | 156 from_565({*ptr,0,0,0}, &cr, &cg, &cb); |
| 182 | 157 |
| 183 r = lerp(dr, r, cr); | 158 r = lerp(dr, r, cr); |
| 184 g = lerp(dg, g, cg); | 159 g = lerp(dg, g, cg); |
| 185 b = lerp(db, b, cb); | 160 b = lerp(db, b, cb); |
| 186 a = 1.0f; | 161 a = 1.0f; |
| 187 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 188 } | 162 } |
| 189 | 163 |
| 190 // Load 4 565 dst pixels. | 164 // Load 4 565 dst pixels. |
| 191 static void SK_VECTORCALL load_d_565(SkRasterPipeline::Stage* st, size_t x, | 165 SK_RASTER_STAGE(load_d_565) { |
| 192 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 166 auto ptr = (const uint16_t*)ctx + x; |
| 193 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 194 auto ptr = st->ctx<const uint16_t*>() + x; | |
| 195 | 167 |
| 196 from_565(Sk4h::Load(ptr), &dr,&dg,&db); | 168 from_565(Sk4h::Load(ptr), &dr,&dg,&db); |
| 197 da = 1.0f; | 169 da = 1.0f; |
| 198 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 199 } | 170 } |
| 200 | 171 |
| 201 // Load 1 565 dst pixel. | 172 // Load 1 565 dst pixel. |
| 202 static void SK_VECTORCALL load_d_565_1(SkRasterPipeline::Stage* st, size_t x, | 173 SK_RASTER_STAGE(load_d_565_1) { |
| 203 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 174 auto ptr = (const uint16_t*)ctx + x; |
| 204 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 205 auto ptr = st->ctx<const uint16_t*>() + x; | |
| 206 | 175 |
| 207 from_565({*ptr,0,0,0}, &dr,&dg,&db); | 176 from_565({*ptr,0,0,0}, &dr,&dg,&db); |
| 208 da = 1.0f; | 177 da = 1.0f; |
| 209 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 210 } | 178 } |
| 211 | 179 |
| 212 // Store 4 565 pixels. | 180 // Store 4 565 pixels. |
| 213 static void SK_VECTORCALL store_565(SkRasterPipeline::Stage* st, size_t x, | 181 SK_RASTER_STAGE(store_565) { |
| 214 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 182 auto ptr = (uint16_t*)ctx + x; |
| 215 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 216 auto ptr = st->ctx<uint16_t*>() + x; | |
| 217 to_565(r,g,b).store(ptr); | 183 to_565(r,g,b).store(ptr); |
| 218 } | 184 } |
| 219 | 185 |
| 220 // Store 1 565 pixel. | 186 // Store 1 565 pixel. |
| 221 static void SK_VECTORCALL store_565_1(SkRasterPipeline::Stage* st, size_t x, | 187 SK_RASTER_STAGE(store_565_1) { |
| 222 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 188 auto ptr = (uint16_t*)ctx + x; |
| 223 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 224 auto ptr = st->ctx<uint16_t*>() + x; | |
| 225 *ptr = to_565(r,g,b)[0]; | 189 *ptr = to_565(r,g,b)[0]; |
| 226 } | 190 } |
| 227 | 191 |
| 228 // Load 4 F16 pixels. | 192 // Load 4 F16 pixels. |
| 229 static void SK_VECTORCALL load_d_f16(SkRasterPipeline::Stage* st, size_t x, | 193 SK_RASTER_STAGE(load_d_f16) { |
| 230 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 194 auto ptr = (const uint64_t*)ctx + x; |
| 231 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 232 auto ptr = st->ctx<const uint64_t*>() + x; | |
| 233 | 195 |
| 234 Sk4h rh, gh, bh, ah; | 196 Sk4h rh, gh, bh, ah; |
| 235 Sk4h_load4(ptr, &rh, &gh, &bh, &ah); | 197 Sk4h_load4(ptr, &rh, &gh, &bh, &ah); |
| 236 | 198 |
| 237 dr = SkHalfToFloat_finite(rh); | 199 dr = SkHalfToFloat_finite(rh); |
| 238 dg = SkHalfToFloat_finite(gh); | 200 dg = SkHalfToFloat_finite(gh); |
| 239 db = SkHalfToFloat_finite(bh); | 201 db = SkHalfToFloat_finite(bh); |
| 240 da = SkHalfToFloat_finite(ah); | 202 da = SkHalfToFloat_finite(ah); |
| 241 | |
| 242 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 243 } | 203 } |
| 244 | 204 |
| 245 // Load 1 F16 pixel. | 205 // Load 1 F16 pixel. |
| 246 static void SK_VECTORCALL load_d_f16_1(SkRasterPipeline::Stage* st, size_t x, | 206 SK_RASTER_STAGE(load_d_f16_1) { |
| 247 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 207 auto ptr = (const uint64_t*)ctx + x; |
| 248 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 249 auto ptr = st->ctx<const uint64_t*>() + x; | |
| 250 | 208 |
| 251 auto p0 = SkHalfToFloat_finite(ptr[0]); | 209 auto p0 = SkHalfToFloat_finite(ptr[0]); |
| 252 dr = { p0[0],0,0,0 }; | 210 dr = { p0[0],0,0,0 }; |
| 253 dg = { p0[1],0,0,0 }; | 211 dg = { p0[1],0,0,0 }; |
| 254 db = { p0[2],0,0,0 }; | 212 db = { p0[2],0,0,0 }; |
| 255 da = { p0[3],0,0,0 }; | 213 da = { p0[3],0,0,0 }; |
| 256 | |
| 257 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 258 } | 214 } |
| 259 | 215 |
| 260 // Store 4 F16 pixels. | 216 // Store 4 F16 pixels. |
| 261 static void SK_VECTORCALL store_f16(SkRasterPipeline::Stage* st, size_t x, | 217 SK_RASTER_STAGE(store_f16) { |
| 262 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 218 auto ptr = (uint64_t*)ctx + x; |
| 263 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 264 auto ptr = st->ctx<uint64_t*>() + x; | |
| 265 | 219 |
| 266 Sk4h_store4(ptr, SkFloatToHalf_finite(r), SkFloatToHalf_finite(g), | 220 Sk4h_store4(ptr, SkFloatToHalf_finite(r), SkFloatToHalf_finite(g), |
| 267 SkFloatToHalf_finite(b), SkFloatToHalf_finite(a)); | 221 SkFloatToHalf_finite(b), SkFloatToHalf_finite(a)); |
| 268 } | 222 } |
| 269 | 223 |
| 270 // Store 1 F16 pixel. | 224 // Store 1 F16 pixel. |
| 271 static void SK_VECTORCALL store_f16_1(SkRasterPipeline::Stage* st, size_t x, | 225 SK_RASTER_STAGE(store_f16_1) { |
| 272 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 226 auto ptr = (uint64_t*)ctx + x; |
| 273 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 274 auto ptr = st->ctx<uint64_t*>() + x; | |
| 275 | 227 |
| 276 SkFloatToHalf_finite({r[0], g[0], b[0], a[0]}).store(ptr); | 228 SkFloatToHalf_finite({r[0], g[0], b[0], a[0]}).store(ptr); |
| 277 } | 229 } |
| 278 | 230 |
| 279 // Load 4 8-bit sRGB pixels from SkPMColor order to RGBA. | 231 // Load 4 8-bit sRGB pixels from SkPMColor order to RGBA. |
| 280 static void SK_VECTORCALL load_d_srgb(SkRasterPipeline::Stage* st, size_t x, | 232 SK_RASTER_STAGE(load_d_srgb) { |
| 281 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 233 auto ptr = (const uint32_t*)ctx + x; |
| 282 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 283 auto ptr = st->ctx<const uint32_t*>() + x; | |
| 284 | 234 |
| 285 dr = { sk_linear_from_srgb[(ptr[0] >> SK_R32_SHIFT) & 0xff], | 235 dr = { sk_linear_from_srgb[(ptr[0] >> SK_R32_SHIFT) & 0xff], |
| 286 sk_linear_from_srgb[(ptr[1] >> SK_R32_SHIFT) & 0xff], | 236 sk_linear_from_srgb[(ptr[1] >> SK_R32_SHIFT) & 0xff], |
| 287 sk_linear_from_srgb[(ptr[2] >> SK_R32_SHIFT) & 0xff], | 237 sk_linear_from_srgb[(ptr[2] >> SK_R32_SHIFT) & 0xff], |
| 288 sk_linear_from_srgb[(ptr[3] >> SK_R32_SHIFT) & 0xff] }; | 238 sk_linear_from_srgb[(ptr[3] >> SK_R32_SHIFT) & 0xff] }; |
| 289 | 239 |
| 290 dg = { sk_linear_from_srgb[(ptr[0] >> SK_G32_SHIFT) & 0xff], | 240 dg = { sk_linear_from_srgb[(ptr[0] >> SK_G32_SHIFT) & 0xff], |
| 291 sk_linear_from_srgb[(ptr[1] >> SK_G32_SHIFT) & 0xff], | 241 sk_linear_from_srgb[(ptr[1] >> SK_G32_SHIFT) & 0xff], |
| 292 sk_linear_from_srgb[(ptr[2] >> SK_G32_SHIFT) & 0xff], | 242 sk_linear_from_srgb[(ptr[2] >> SK_G32_SHIFT) & 0xff], |
| 293 sk_linear_from_srgb[(ptr[3] >> SK_G32_SHIFT) & 0xff] }; | 243 sk_linear_from_srgb[(ptr[3] >> SK_G32_SHIFT) & 0xff] }; |
| 294 | 244 |
| 295 db = { sk_linear_from_srgb[(ptr[0] >> SK_B32_SHIFT) & 0xff], | 245 db = { sk_linear_from_srgb[(ptr[0] >> SK_B32_SHIFT) & 0xff], |
| 296 sk_linear_from_srgb[(ptr[1] >> SK_B32_SHIFT) & 0xff], | 246 sk_linear_from_srgb[(ptr[1] >> SK_B32_SHIFT) & 0xff], |
| 297 sk_linear_from_srgb[(ptr[2] >> SK_B32_SHIFT) & 0xff], | 247 sk_linear_from_srgb[(ptr[2] >> SK_B32_SHIFT) & 0xff], |
| 298 sk_linear_from_srgb[(ptr[3] >> SK_B32_SHIFT) & 0xff] }; | 248 sk_linear_from_srgb[(ptr[3] >> SK_B32_SHIFT) & 0xff] }; |
| 299 | 249 |
| 300 da = SkNx_cast<float>(Sk4u::Load(ptr) >> SK_A32_SHIFT) * (1/255.0f); | 250 da = SkNx_cast<float>(Sk4u::Load(ptr) >> SK_A32_SHIFT) * (1/255.0f); |
| 301 | |
| 302 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 303 } | 251 } |
| 304 | 252 |
| 305 // Tail variant of load_d_srgb() handling 1 pixel at a time. | 253 // Tail variant of load_d_srgb() handling 1 pixel at a time. |
| 306 static void SK_VECTORCALL load_d_srgb_1(SkRasterPipeline::Stage* st, size_t x, | 254 SK_RASTER_STAGE(load_d_srgb_1) { |
| 307 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 255 auto ptr = (const uint32_t*)ctx + x; |
| 308 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 309 auto ptr = st->ctx<const uint32_t*>() + x; | |
| 310 | 256 |
| 311 dr = { sk_linear_from_srgb[(*ptr >> SK_R32_SHIFT) & 0xff], 0,0,0 }; | 257 dr = { sk_linear_from_srgb[(*ptr >> SK_R32_SHIFT) & 0xff], 0,0,0 }; |
| 312 dg = { sk_linear_from_srgb[(*ptr >> SK_G32_SHIFT) & 0xff], 0,0,0 }; | 258 dg = { sk_linear_from_srgb[(*ptr >> SK_G32_SHIFT) & 0xff], 0,0,0 }; |
| 313 db = { sk_linear_from_srgb[(*ptr >> SK_B32_SHIFT) & 0xff], 0,0,0 }; | 259 db = { sk_linear_from_srgb[(*ptr >> SK_B32_SHIFT) & 0xff], 0,0,0 }; |
| 314 da = { (1/255.0f) * (*ptr >> SK_A32_SHIFT) , 0,0,0 }; | 260 da = { (1/255.0f) * (*ptr >> SK_A32_SHIFT) , 0,0,0 }; |
| 315 | |
| 316 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 317 } | 261 } |
| 318 | 262 |
| 319 // Write out 4 pixels as 8-bit SkPMColor-order sRGB. | 263 // Write out 4 pixels as 8-bit SkPMColor-order sRGB. |
| 320 static void SK_VECTORCALL store_srgb(SkRasterPipeline::Stage* st, size_t x, | 264 SK_RASTER_STAGE(store_srgb) { |
| 321 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 265 auto ptr = (uint32_t*)ctx + x; |
| 322 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 323 auto dst = st->ctx<uint32_t*>() + x; | |
| 324 ( sk_linear_to_srgb_noclamp(r) << SK_R32_SHIFT | 266 ( sk_linear_to_srgb_noclamp(r) << SK_R32_SHIFT |
| 325 | sk_linear_to_srgb_noclamp(g) << SK_G32_SHIFT | 267 | sk_linear_to_srgb_noclamp(g) << SK_G32_SHIFT |
| 326 | sk_linear_to_srgb_noclamp(b) << SK_B32_SHIFT | 268 | sk_linear_to_srgb_noclamp(b) << SK_B32_SHIFT |
| 327 | Sk4f_round(255.0f * a) << SK_A32_SHIFT).store(dst); | 269 | Sk4f_round(255.0f * a) << SK_A32_SHIFT).store(ptr); |
| 328 } | 270 } |
| 329 | 271 |
| 330 // Tail variant of store_srgb() handling 1 pixel at a time. | 272 // Tail variant of store_srgb() handling 1 pixel at a time. |
| 331 static void SK_VECTORCALL store_srgb_1(SkRasterPipeline::Stage* st, size_t x, | 273 SK_RASTER_STAGE(store_srgb_1) { |
| 332 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 274 auto ptr = (uint32_t*)ctx + x; |
| 333 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 334 auto dst = st->ctx<uint32_t*>() + x; | |
| 335 Sk4i rgb = sk_linear_to_srgb_noclamp(swizzle_rb_if_bgra({ r[0], g[0], b[0],
0.0f })); | 275 Sk4i rgb = sk_linear_to_srgb_noclamp(swizzle_rb_if_bgra({ r[0], g[0], b[0],
0.0f })); |
| 336 | 276 |
| 337 uint32_t rgba; | 277 uint32_t rgba; |
| 338 SkNx_cast<uint8_t>(rgb).store(&rgba); | 278 SkNx_cast<uint8_t>(rgb).store(&rgba); |
| 339 rgba |= (uint32_t)(255.0f * a[0] + 0.5f) << 24; | 279 rgba |= (uint32_t)(255.0f * a[0] + 0.5f) << 24; |
| 340 *dst = rgba; | 280 *ptr = rgba; |
| 341 } | 281 } |
| 342 | 282 |
| 343 static bool supported(const SkImageInfo& info) { | 283 static bool supported(const SkImageInfo& info) { |
| 344 switch (info.colorType()) { | 284 switch (info.colorType()) { |
| 345 case kN32_SkColorType: return info.gammaCloseToSRGB(); | 285 case kN32_SkColorType: return info.gammaCloseToSRGB(); |
| 346 case kRGBA_F16_SkColorType: return true; | 286 case kRGBA_F16_SkColorType: return true; |
| 347 case kRGB_565_SkColorType: return true; | 287 case kRGB_565_SkColorType: return true; |
| 348 default: return false; | 288 default: return false; |
| 349 } | 289 } |
| 350 } | 290 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 379 } else { | 319 } else { |
| 380 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store
(&color); | 320 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store
(&color); |
| 381 } | 321 } |
| 382 | 322 |
| 383 auto blitter = alloc->createT<SkRasterPipelineBlitter>( | 323 auto blitter = alloc->createT<SkRasterPipelineBlitter>( |
| 384 dst, | 324 dst, |
| 385 shader, colorFilter, xfermode, | 325 shader, colorFilter, xfermode, |
| 386 color.premul()); | 326 color.premul()); |
| 387 | 327 |
| 388 if (!paint.getShader()) { | 328 if (!paint.getShader()) { |
| 389 blitter->fShader.append(constant_color, &blitter->fPaintColor); | 329 blitter->fShader.append<constant_color>(&blitter->fPaintColor); |
| 390 } | 330 } |
| 391 if (!paint.getXfermode()) { | 331 if (!paint.getXfermode()) { |
| 392 blitter->fXfermode.append(srcover); | 332 blitter->fXfermode.append<srcover>(); |
| 393 } | 333 } |
| 394 | 334 |
| 395 return blitter; | 335 return blitter; |
| 396 } | 336 } |
| 397 | 337 |
| 398 void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst
) const { | 338 void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst
) const { |
| 399 SkASSERT(supported(fDst.info())); | 339 SkASSERT(supported(fDst.info())); |
| 400 | 340 |
| 401 switch (fDst.info().colorType()) { | 341 switch (fDst.info().colorType()) { |
| 402 case kN32_SkColorType: | 342 case kN32_SkColorType: |
| 403 if (fDst.info().gammaCloseToSRGB()) { | 343 if (fDst.info().gammaCloseToSRGB()) { |
| 404 p->append(load_d_srgb, load_d_srgb_1, dst); | 344 p->append<load_d_srgb, load_d_srgb_1>(dst); |
| 405 } | 345 } |
| 406 break; | 346 break; |
| 407 case kRGBA_F16_SkColorType: | 347 case kRGBA_F16_SkColorType: |
| 408 p->append(load_d_f16, load_d_f16_1, dst); | 348 p->append<load_d_f16, load_d_f16_1>(dst); |
| 409 break; | 349 break; |
| 410 case kRGB_565_SkColorType: | 350 case kRGB_565_SkColorType: |
| 411 p->append(load_d_565, load_d_565_1, dst); | 351 p->append<load_d_565, load_d_565_1>(dst); |
| 412 break; | 352 break; |
| 413 default: break; | 353 default: break; |
| 414 } | 354 } |
| 415 } | 355 } |
| 416 | 356 |
| 417 void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const
{ | 357 void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const
{ |
| 418 SkASSERT(supported(fDst.info())); | 358 SkASSERT(supported(fDst.info())); |
| 419 | 359 |
| 420 p->append(clamp_01_premul); | 360 p->append<clamp_01_premul>(); |
| 421 switch (fDst.info().colorType()) { | 361 switch (fDst.info().colorType()) { |
| 422 case kN32_SkColorType: | 362 case kN32_SkColorType: |
| 423 if (fDst.info().gammaCloseToSRGB()) { | 363 if (fDst.info().gammaCloseToSRGB()) { |
| 424 p->append(store_srgb, store_srgb_1, dst); | 364 p->append<store_srgb, store_srgb_1>(dst); |
| 425 } | 365 } |
| 426 break; | 366 break; |
| 427 case kRGBA_F16_SkColorType: | 367 case kRGBA_F16_SkColorType: |
| 428 p->append(store_f16, store_f16_1, dst); | 368 p->append<store_f16, store_f16_1>(dst); |
| 429 break; | 369 break; |
| 430 case kRGB_565_SkColorType: | 370 case kRGB_565_SkColorType: |
| 431 p->append(store_565, store_565_1, dst); | 371 p->append<store_565, store_565_1>(dst); |
| 432 break; | 372 break; |
| 433 default: break; | 373 default: break; |
| 434 } | 374 } |
| 435 } | 375 } |
| 436 | 376 |
| 437 void SkRasterPipelineBlitter::blitH(int x, int y, int w) { | 377 void SkRasterPipelineBlitter::blitH(int x, int y, int w) { |
| 438 auto dst = fDst.writable_addr(0,y); | 378 auto dst = fDst.writable_addr(0,y); |
| 439 | 379 |
| 440 SkRasterPipeline p; | 380 SkRasterPipeline p; |
| 441 p.extend(fShader); | 381 p.extend(fShader); |
| 442 p.extend(fColorFilter); | 382 p.extend(fColorFilter); |
| 443 this->append_load_d(&p, dst); | 383 this->append_load_d(&p, dst); |
| 444 p.extend(fXfermode); | 384 p.extend(fXfermode); |
| 445 this->append_store(&p, dst); | 385 this->append_store(&p, dst); |
| 446 | 386 |
| 447 p.run(x, w); | 387 p.run(x, w); |
| 448 } | 388 } |
| 449 | 389 |
| 450 void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const
int16_t runs[]) { | 390 void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const
int16_t runs[]) { |
| 451 auto dst = fDst.writable_addr(0,y); | 391 auto dst = fDst.writable_addr(0,y); |
| 452 float coverage; | 392 float coverage; |
| 453 | 393 |
| 454 SkRasterPipeline p; | 394 SkRasterPipeline p; |
| 455 p.extend(fShader); | 395 p.extend(fShader); |
| 456 p.extend(fColorFilter); | 396 p.extend(fColorFilter); |
| 457 this->append_load_d(&p, dst); | 397 this->append_load_d(&p, dst); |
| 458 p.extend(fXfermode); | 398 p.extend(fXfermode); |
| 459 p.append(lerp_constant_float, &coverage); | 399 p.append<lerp_constant_float>(&coverage); |
| 460 this->append_store(&p, dst); | 400 this->append_store(&p, dst); |
| 461 | 401 |
| 462 for (int16_t run = *runs; run > 0; run = *runs) { | 402 for (int16_t run = *runs; run > 0; run = *runs) { |
| 463 coverage = *aa * (1/255.0f); | 403 coverage = *aa * (1/255.0f); |
| 464 p.run(x, run); | 404 p.run(x, run); |
| 465 | 405 |
| 466 x += run; | 406 x += run; |
| 467 runs += run; | 407 runs += run; |
| 468 aa += run; | 408 aa += run; |
| 469 } | 409 } |
| 470 } | 410 } |
| 471 | 411 |
| 472 void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
{ | 412 void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
{ |
| 473 if (mask.fFormat == SkMask::kBW_Format) { | 413 if (mask.fFormat == SkMask::kBW_Format) { |
| 474 // TODO: native BW masks? | 414 // TODO: native BW masks? |
| 475 return INHERITED::blitMask(mask, clip); | 415 return INHERITED::blitMask(mask, clip); |
| 476 } | 416 } |
| 477 | 417 |
| 478 int x = clip.left(); | 418 int x = clip.left(); |
| 479 for (int y = clip.top(); y < clip.bottom(); y++) { | 419 for (int y = clip.top(); y < clip.bottom(); y++) { |
| 480 auto dst = fDst.writable_addr(0,y); | 420 auto dst = fDst.writable_addr(0,y); |
| 481 | 421 |
| 482 SkRasterPipeline p; | 422 SkRasterPipeline p; |
| 483 p.extend(fShader); | 423 p.extend(fShader); |
| 484 p.extend(fColorFilter); | 424 p.extend(fColorFilter); |
| 485 this->append_load_d(&p, dst); | 425 this->append_load_d(&p, dst); |
| 486 p.extend(fXfermode); | 426 p.extend(fXfermode); |
| 487 switch (mask.fFormat) { | 427 switch (mask.fFormat) { |
| 488 case SkMask::kA8_Format: | 428 case SkMask::kA8_Format: |
| 489 p.append(lerp_a8, lerp_a8_1, mask.getAddr8(x,y)-x); | 429 p.append<lerp_a8, lerp_a8_1>(mask.getAddr8(x,y)-x); |
| 490 break; | 430 break; |
| 491 case SkMask::kLCD16_Format: | 431 case SkMask::kLCD16_Format: |
| 492 p.append(lerp_lcd16, lerp_lcd16_1, mask.getAddrLCD16(x,y)-x); | 432 p.append<lerp_lcd16, lerp_lcd16_1>(mask.getAddrLCD16(x,y)-x); |
| 493 break; | 433 break; |
| 494 default: break; | 434 default: break; |
| 495 } | 435 } |
| 496 this->append_store(&p, dst); | 436 this->append_store(&p, dst); |
| 497 | 437 |
| 498 p.run(x, clip.width()); | 438 p.run(x, clip.width()); |
| 499 } | 439 } |
| 500 } | 440 } |
| OLD | NEW |