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 "SkLinearBitmapPipeline.h" | 8 #include "SkLinearBitmapPipeline.h" |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 } else { | 158 } else { |
159 return next; | 159 return next; |
160 } | 160 } |
161 return matrixProc->get(); | 161 return matrixProc->get(); |
162 } | 162 } |
163 | 163 |
164 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 164 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
165 // Tile Stage | 165 // Tile Stage |
166 | 166 |
167 template<typename XStrategy, typename YStrategy, typename Next> | 167 template<typename XStrategy, typename YStrategy, typename Next> |
168 class NearestTileStage final : public SkLinearBitmapPipeline::PointProcessorInte
rface { | 168 class CombinedTileStage final : public SkLinearBitmapPipeline::PointProcessorInt
erface { |
169 public: | 169 public: |
170 template <typename... Args> | 170 CombinedTileStage(Next* next, SkISize dimensions) |
171 NearestTileStage(Next* next, SkISize dimensions) | |
172 : fNext{next} | 171 : fNext{next} |
173 , fXStrategy{dimensions.width()} | 172 , fXStrategy{dimensions.width()} |
174 , fYStrategy{dimensions.height()}{ } | 173 , fYStrategy{dimensions.height()}{ } |
175 | 174 |
176 NearestTileStage(Next* next, const NearestTileStage& stage) | 175 CombinedTileStage(Next* next, const CombinedTileStage& stage) |
177 : fNext{next} | 176 : fNext{next} |
178 , fXStrategy{stage.fXStrategy} | 177 , fXStrategy{stage.fXStrategy} |
179 , fYStrategy{stage.fYStrategy} { } | 178 , fYStrategy{stage.fYStrategy} { } |
180 | 179 |
181 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 180 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
182 fXStrategy.tileXPoints(&xs); | 181 fXStrategy.tileXPoints(&xs); |
183 fYStrategy.tileYPoints(&ys); | 182 fYStrategy.tileYPoints(&ys); |
184 fNext->pointListFew(n, xs, ys); | 183 fNext->pointListFew(n, xs, ys); |
185 } | 184 } |
186 | 185 |
187 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | 186 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
188 fXStrategy.tileXPoints(&xs); | 187 fXStrategy.tileXPoints(&xs); |
189 fYStrategy.tileYPoints(&ys); | 188 fYStrategy.tileYPoints(&ys); |
190 fNext->pointList4(xs, ys); | 189 fNext->pointList4(xs, ys); |
191 } | 190 } |
192 | 191 |
193 // The span you pass must not be empty. | 192 // The span you pass must not be empty. |
194 void pointSpan(Span span) override { | 193 void pointSpan(Span span) override { |
195 SkASSERT(!span.isEmpty()); | 194 SkASSERT(!span.isEmpty()); |
196 SkPoint start; SkScalar length; int count; | 195 SkPoint start; SkScalar length; int count; |
197 std::tie(start, length, count) = span; | 196 std::tie(start, length, count) = span; |
| 197 |
| 198 if (span.count() == 1) { |
| 199 // DANGER: |
| 200 // The explicit casts from float to Sk4f are not usually necessary,
but are here to |
| 201 // work around an MSVC 2015u2 c++ code generation bug. This is track
ed using skia bug |
| 202 // 5566. |
| 203 this->pointListFew(1, Sk4f{span.startX()}, Sk4f{span.startY()}); |
| 204 return; |
| 205 } |
| 206 |
198 SkScalar x = X(start); | 207 SkScalar x = X(start); |
199 SkScalar y = fYStrategy.tileY(Y(start)); | 208 SkScalar y = fYStrategy.tileY(Y(start)); |
200 Span yAdjustedSpan{{x, y}, length, count}; | 209 Span yAdjustedSpan{{x, y}, length, count}; |
| 210 |
201 if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) { | 211 if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) { |
202 span_fallback(span, this); | 212 span_fallback(span, this); |
203 } | 213 } |
204 } | 214 } |
205 | 215 |
206 private: | 216 private: |
207 Next* const fNext; | 217 Next* const fNext; |
208 XStrategy fXStrategy; | 218 XStrategy fXStrategy; |
209 YStrategy fYStrategy; | 219 YStrategy fYStrategy; |
210 }; | 220 }; |
211 | 221 |
212 template<typename XStrategy, typename YStrategy, typename Next> | 222 template <typename XStrategy, typename Next> |
213 class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInter
face { | |
214 public: | |
215 template <typename... Args> | |
216 BilerpTileStage(Next* next, SkISize dimensions) | |
217 : fNext{next} | |
218 , fXMax(dimensions.width()) | |
219 , fYMax(dimensions.height()) | |
220 , fXStrategy{dimensions.width()} | |
221 , fYStrategy{dimensions.height()} { } | |
222 | |
223 BilerpTileStage(Next* next, const BilerpTileStage& stage) | |
224 : fNext{next} | |
225 , fXMax{stage.fXMax} | |
226 , fYMax{stage.fYMax} | |
227 , fXStrategy{stage.fXStrategy} | |
228 , fYStrategy{stage.fYStrategy} { } | |
229 | |
230 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | |
231 fXStrategy.tileXPoints(&xs); | |
232 fYStrategy.tileYPoints(&ys); | |
233 // TODO: check to see if xs and ys are in range then just call pointList
Few on next. | |
234 if (n >= 1) this->bilerpPoint(xs[0], ys[0]); | |
235 if (n >= 2) this->bilerpPoint(xs[1], ys[1]); | |
236 if (n >= 3) this->bilerpPoint(xs[2], ys[2]); | |
237 } | |
238 | |
239 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | |
240 fXStrategy.tileXPoints(&xs); | |
241 fYStrategy.tileYPoints(&ys); | |
242 // TODO: check to see if xs and ys are in range then just call pointList
4 on next. | |
243 this->bilerpPoint(xs[0], ys[0]); | |
244 this->bilerpPoint(xs[1], ys[1]); | |
245 this->bilerpPoint(xs[2], ys[2]); | |
246 this->bilerpPoint(xs[3], ys[3]); | |
247 } | |
248 | |
249 struct Wrapper { | |
250 void pointSpan(Span span) { | |
251 processor->breakIntoEdges(span); | |
252 } | |
253 | |
254 void repeatSpan(Span span, int32_t repeatCount) { | |
255 while (repeatCount --> 0) { | |
256 processor->pointSpan(span); | |
257 } | |
258 } | |
259 | |
260 BilerpTileStage* processor; | |
261 }; | |
262 | |
263 // The span you pass must not be empty. | |
264 void pointSpan(Span span) override { | |
265 SkASSERT(!span.isEmpty()); | |
266 | |
267 Wrapper wrapper = {this}; | |
268 if (!fXStrategy.maybeProcessSpan(span, &wrapper)) { | |
269 span_fallback(span, this); | |
270 } | |
271 } | |
272 | |
273 private: | |
274 void bilerpPoint(SkScalar x, SkScalar y) { | |
275 Sk4f txs = Sk4f{x} + Sk4f{-0.5f, 0.5f, -0.5f, 0.5f}; | |
276 Sk4f tys = Sk4f{y} + Sk4f{-0.5f, -0.5f, 0.5f, 0.5f}; | |
277 fXStrategy.tileXPoints(&txs); | |
278 fYStrategy.tileYPoints(&tys); | |
279 fNext->bilerpEdge(txs, tys); | |
280 } | |
281 | |
282 void handleEdges(Span span, SkScalar dx) { | |
283 SkPoint start; SkScalar length; int count; | |
284 std::tie(start, length, count) = span; | |
285 SkScalar x = X(start); | |
286 SkScalar y = Y(start); | |
287 SkScalar tiledY = fYStrategy.tileY(y); | |
288 while (count > 0) { | |
289 this->bilerpPoint(x, tiledY); | |
290 x += dx; | |
291 count -= 1; | |
292 } | |
293 } | |
294 | |
295 void yProcessSpan(Span span) { | |
296 SkScalar tiledY = fYStrategy.tileY(span.startY()); | |
297 if (0.5f <= tiledY && tiledY < fYMax - 0.5f ) { | |
298 Span tiledSpan{{span.startX(), tiledY}, span.length(), span.count()}
; | |
299 fNext->pointSpan(tiledSpan); | |
300 } else { | |
301 // Convert to the Y0 bilerp sample set by shifting by -0.5f. Then ti
le that new y | |
302 // value and shift it back resulting in the working Y0. Do the same
thing with Y1 but | |
303 // in the opposite direction. | |
304 SkScalar y0 = fYStrategy.tileY(span.startY() - 0.5f) + 0.5f; | |
305 SkScalar y1 = fYStrategy.tileY(span.startY() + 0.5f) - 0.5f; | |
306 Span newSpan{{span.startX(), y0}, span.length(), span.count()}; | |
307 fNext->bilerpSpan(newSpan, y1); | |
308 } | |
309 } | |
310 void breakIntoEdges(Span span) { | |
311 if (span.count() == 1) { | |
312 this->bilerpPoint(span.startX(), span.startY()); | |
313 } else if (span.length() == 0) { | |
314 yProcessSpan(span); | |
315 } else { | |
316 SkScalar dx = span.length() / (span.count() - 1); | |
317 if (span.length() > 0) { | |
318 Span leftBorder = span.breakAt(0.5f, dx); | |
319 if (!leftBorder.isEmpty()) { | |
320 this->handleEdges(leftBorder, dx); | |
321 } | |
322 Span center = span.breakAt(fXMax - 0.5f, dx); | |
323 if (!center.isEmpty()) { | |
324 this->yProcessSpan(center); | |
325 } | |
326 | |
327 if (!span.isEmpty()) { | |
328 this->handleEdges(span, dx); | |
329 } | |
330 } else { | |
331 Span center = span.breakAt(fXMax + 0.5f, dx); | |
332 if (!span.isEmpty()) { | |
333 this->handleEdges(span, dx); | |
334 } | |
335 Span leftEdge = center.breakAt(0.5f, dx); | |
336 if (!center.isEmpty()) { | |
337 this->yProcessSpan(center); | |
338 } | |
339 if (!leftEdge.isEmpty()) { | |
340 this->handleEdges(leftEdge, dx); | |
341 } | |
342 | |
343 } | |
344 } | |
345 } | |
346 | |
347 Next* const fNext; | |
348 SkScalar fXMax; | |
349 SkScalar fYMax; | |
350 XStrategy fXStrategy; | |
351 YStrategy fYStrategy; | |
352 }; | |
353 | |
354 template <typename XStrategy, typename YStrategy, typename Next> | |
355 void make_tile_stage( | |
356 SkFilterQuality filterQuality, SkISize dimensions, | |
357 Next* next, SkLinearBitmapPipeline::TileStage* tileStage) { | |
358 if (filterQuality == kNone_SkFilterQuality) { | |
359 tileStage->initStage<NearestTileStage<XStrategy, YStrategy, Next>>(next,
dimensions); | |
360 } else { | |
361 tileStage->initStage<BilerpTileStage<XStrategy, YStrategy, Next>>(next,
dimensions); | |
362 } | |
363 } | |
364 template <typename XStrategy> | |
365 void choose_tiler_ymode( | 223 void choose_tiler_ymode( |
366 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, | 224 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, |
367 SkLinearBitmapPipeline::SampleProcessorInterface* next, | 225 Next* next, |
368 SkLinearBitmapPipeline::TileStage* tileStage) { | 226 SkLinearBitmapPipeline::TileStage* tileStage) { |
369 switch (yMode) { | 227 switch (yMode) { |
370 case SkShader::kClamp_TileMode: | 228 case SkShader::kClamp_TileMode: { |
371 make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions
, next, tileStage); | 229 using Tiler = CombinedTileStage<XStrategy, YClampStrategy, Next>; |
| 230 tileStage->initStage<Tiler>(next, dimensions); |
372 break; | 231 break; |
373 case SkShader::kRepeat_TileMode: | 232 } |
374 make_tile_stage<XStrategy, YRepeatStrategy>(filterQuality, dimension
s, next, tileStage); | 233 case SkShader::kRepeat_TileMode: { |
| 234 using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, Next>; |
| 235 tileStage->initStage<Tiler>(next, dimensions); |
375 break; | 236 break; |
376 case SkShader::kMirror_TileMode: | 237 } |
377 make_tile_stage<XStrategy, YMirrorStrategy>(filterQuality, dimension
s, next, tileStage); | 238 case SkShader::kMirror_TileMode: { |
| 239 using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, Next>; |
| 240 tileStage->initStage<Tiler>(next, dimensions); |
378 break; | 241 break; |
| 242 } |
379 } | 243 } |
380 }; | 244 }; |
381 | 245 |
382 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( | 246 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( |
383 SkLinearBitmapPipeline::SampleProcessorInterface* next, | 247 SkLinearBitmapPipeline::SampleProcessorInterface* next, |
384 SkISize dimensions, | 248 SkISize dimensions, |
385 SkShader::TileMode xMode, | 249 SkShader::TileMode xMode, |
386 SkShader::TileMode yMode, | 250 SkShader::TileMode yMode, |
387 SkFilterQuality filterQuality, | 251 SkFilterQuality filterQuality, |
388 SkScalar dx, | 252 SkScalar dx, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 int32_t y = SkScalarTruncToInt(span.startY()); | 324 int32_t y = SkScalarTruncToInt(span.startY()); |
461 const uint32_t* src = this->pixelAddress(x, y); | 325 const uint32_t* src = this->pixelAddress(x, y); |
462 uint32_t* dest = fDest; | 326 uint32_t* dest = fDest; |
463 while (repeatCount --> 0) { | 327 while (repeatCount --> 0) { |
464 memmove(dest, src, span.count() * sizeof(uint32_t)); | 328 memmove(dest, src, span.count() * sizeof(uint32_t)); |
465 dest += span.count(); | 329 dest += span.count(); |
466 } | 330 } |
467 fDest = dest; | 331 fDest = dest; |
468 } | 332 } |
469 | 333 |
470 void SK_VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Imple
mented"); } | |
471 | |
472 void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented");
} | |
473 | |
474 void setDestination(void* dst, int count) override { | 334 void setDestination(void* dst, int count) override { |
475 fDest = static_cast<uint32_t*>(dst); | 335 fDest = static_cast<uint32_t*>(dst); |
476 fEnd = fDest + count; | 336 fEnd = fDest + count; |
477 } | 337 } |
478 | 338 |
479 private: | 339 private: |
480 const uint32_t* pixelAddress(int32_t x, int32_t y) { | 340 const uint32_t* pixelAddress(int32_t x, int32_t y) { |
481 return &fSrc[fWidth * y + x]; | 341 return &fSrc[fWidth * y + x]; |
482 } | 342 } |
483 const uint32_t* const fSrc; | 343 const uint32_t* const fSrc; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 int32_t y = (int32_t)span.startY(); | 391 int32_t y = (int32_t)span.startY(); |
532 const uint32_t* beginSpan = this->pixelAddress(x, y); | 392 const uint32_t* beginSpan = this->pixelAddress(x, y); |
533 | 393 |
534 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount,
span.count()); | 394 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount,
span.count()); |
535 | 395 |
536 fDest += span.count() * repeatCount; | 396 fDest += span.count() * repeatCount; |
537 | 397 |
538 SkASSERT(fDest <= fEnd); | 398 SkASSERT(fDest <= fEnd); |
539 } | 399 } |
540 | 400 |
541 void SK_VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Imple
mented"); } | |
542 | |
543 void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented");
} | |
544 | |
545 void setDestination(void* dst, int count) override { | 401 void setDestination(void* dst, int count) override { |
546 SkASSERT(count > 0); | 402 SkASSERT(count > 0); |
547 fDest = static_cast<uint32_t*>(dst); | 403 fDest = static_cast<uint32_t*>(dst); |
548 fEnd = fDest + count; | 404 fEnd = fDest + count; |
549 } | 405 } |
550 | 406 |
551 private: | 407 private: |
552 const uint32_t* pixelAddress(int32_t x, int32_t y) { | 408 const uint32_t* pixelAddress(int32_t x, int32_t y) { |
553 return &fSrc[fWidth * y + x]; | 409 return &fSrc[fWidth * y + x]; |
554 } | 410 } |
(...skipping 20 matching lines...) Expand all Loading... |
575 using PA = PixelAccessor<colorType, kSRGB_SkGammaType>; | 431 using PA = PixelAccessor<colorType, kSRGB_SkGammaType>; |
576 accessor->init<PA>(srcPixmap); | 432 accessor->init<PA>(srcPixmap); |
577 return accessor->get(); | 433 return accessor->get(); |
578 } else { | 434 } else { |
579 using PA = PixelAccessor<colorType, kLinear_SkGammaType>; | 435 using PA = PixelAccessor<colorType, kLinear_SkGammaType>; |
580 accessor->init<PA>(srcPixmap); | 436 accessor->init<PA>(srcPixmap); |
581 return accessor->get(); | 437 return accessor->get(); |
582 } | 438 } |
583 } | 439 } |
584 | 440 |
585 template<template <typename, typename> class Sampler> | 441 static SkLinearBitmapPipeline::PixelAccessorInterface* choose_pixel_accessor( |
586 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba
se( | |
587 Blender* next, | |
588 const SkPixmap& srcPixmap, | 442 const SkPixmap& srcPixmap, |
589 const SkColor A8TintColor, | 443 const SkColor A8TintColor, |
590 SkLinearBitmapPipeline::SampleStage* sampleStage, | |
591 SkLinearBitmapPipeline::Accessor* accessor) | 444 SkLinearBitmapPipeline::Accessor* accessor) |
592 { | 445 { |
593 const SkImageInfo& imageInfo = srcPixmap.info(); | 446 const SkImageInfo& imageInfo = srcPixmap.info(); |
594 | 447 |
595 SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr; | 448 SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr; |
596 switch (imageInfo.colorType()) { | 449 switch (imageInfo.colorType()) { |
597 case kAlpha_8_SkColorType: { | 450 case kAlpha_8_SkColorType: { |
598 using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaTy
pe>; | 451 using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaTy
pe>; |
599 accessor->init<PA>(srcPixmap, A8TintColor); | 452 accessor->init<PA>(srcPixmap, A8TintColor); |
600 pixelAccessor = accessor->get(); | 453 pixelAccessor = accessor->get(); |
(...skipping 21 matching lines...) Expand all Loading... |
622 using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaT
ype>; | 475 using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaT
ype>; |
623 accessor->init<PA>(srcPixmap); | 476 accessor->init<PA>(srcPixmap); |
624 pixelAccessor = accessor->get(); | 477 pixelAccessor = accessor->get(); |
625 } | 478 } |
626 break; | 479 break; |
627 default: | 480 default: |
628 SkFAIL("Not implemented. Unsupported src"); | 481 SkFAIL("Not implemented. Unsupported src"); |
629 break; | 482 break; |
630 } | 483 } |
631 | 484 |
632 using S = Sampler<PixelAccessorShim, Blender>; | 485 return pixelAccessor; |
633 sampleStage->initStage<S>(next, pixelAccessor); | |
634 return sampleStage->get(); | |
635 } | 486 } |
636 | 487 |
637 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( | 488 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( |
638 Blender* next, | 489 Blender* next, |
639 SkFilterQuality filterQuality, | 490 SkFilterQuality filterQuality, |
| 491 SkShader::TileMode xTile, SkShader::TileMode yTile, |
640 const SkPixmap& srcPixmap, | 492 const SkPixmap& srcPixmap, |
641 const SkColor A8TintColor, | 493 const SkColor A8TintColor, |
642 SkLinearBitmapPipeline::SampleStage* sampleStage, | 494 SkLinearBitmapPipeline::SampleStage* sampleStage, |
643 SkLinearBitmapPipeline::Accessor* accessor) { | 495 SkLinearBitmapPipeline::Accessor* accessor) { |
644 const SkImageInfo& imageInfo = srcPixmap.info(); | 496 const SkImageInfo& imageInfo = srcPixmap.info(); |
| 497 SkISize dimensions = imageInfo.dimensions(); |
645 | 498 |
646 // Special case samplers with fully expanded templates | 499 // Special case samplers with fully expanded templates |
647 if (imageInfo.gammaCloseToSRGB()) { | 500 if (imageInfo.gammaCloseToSRGB()) { |
648 if (filterQuality == kNone_SkFilterQuality) { | 501 if (filterQuality == kNone_SkFilterQuality) { |
649 switch (imageInfo.colorType()) { | 502 switch (imageInfo.colorType()) { |
650 case kN32_SkColorType: { | 503 case kN32_SkColorType: { |
651 using S = | 504 using S = |
652 NearestNeighborSampler< | 505 NearestNeighborSampler< |
653 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; | 506 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; |
654 sampleStage->initStage<S>(next, srcPixmap); | 507 sampleStage->initStage<S>(next, srcPixmap); |
655 return sampleStage->get(); | 508 return sampleStage->get(); |
656 } | 509 } |
657 case kIndex_8_SkColorType: { | 510 case kIndex_8_SkColorType: { |
658 using S = | 511 using S = |
659 NearestNeighborSampler< | 512 NearestNeighborSampler< |
660 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; | 513 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; |
661 sampleStage->initStage<S>(next, srcPixmap); | 514 sampleStage->initStage<S>(next, srcPixmap); |
662 return sampleStage->get(); | 515 return sampleStage->get(); |
663 } | 516 } |
664 default: | 517 default: |
665 break; | 518 break; |
666 } | 519 } |
667 } else { | 520 } else { |
668 switch (imageInfo.colorType()) { | 521 switch (imageInfo.colorType()) { |
669 case kN32_SkColorType: { | 522 case kN32_SkColorType: { |
670 using S = | 523 using S = |
671 BilerpSampler< | 524 BilerpSampler< |
672 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; | 525 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; |
673 sampleStage->initStage<S>(next, srcPixmap); | 526 sampleStage->initStage<S>(next, dimensions, xTile, yTile, sr
cPixmap); |
674 return sampleStage->get(); | 527 return sampleStage->get(); |
675 } | 528 } |
676 case kIndex_8_SkColorType: { | 529 case kIndex_8_SkColorType: { |
677 using S = | 530 using S = |
678 BilerpSampler< | 531 BilerpSampler< |
679 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; | 532 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; |
680 sampleStage->initStage<S>(next, srcPixmap); | 533 sampleStage->initStage<S>(next, dimensions, xTile, yTile, sr
cPixmap); |
681 return sampleStage->get(); | 534 return sampleStage->get(); |
682 } | 535 } |
683 default: | 536 default: |
684 break; | 537 break; |
685 } | 538 } |
686 } | 539 } |
687 } | 540 } |
688 | 541 |
| 542 auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor)
; |
689 // General cases. | 543 // General cases. |
690 if (filterQuality == kNone_SkFilterQuality) { | 544 if (filterQuality == kNone_SkFilterQuality) { |
691 return choose_pixel_sampler_base<NearestNeighborSampler>( | 545 using S = NearestNeighborSampler<PixelAccessorShim, Blender>; |
692 next, srcPixmap, A8TintColor, sampleStage, accessor); | 546 sampleStage->initStage<S>(next, pixelAccessor); |
693 } else { | 547 } else { |
694 return choose_pixel_sampler_base<BilerpSampler>( | 548 using S = BilerpSampler<PixelAccessorShim, Blender>; |
695 next, srcPixmap, A8TintColor, sampleStage, accessor); | 549 sampleStage->initStage<S>(next, dimensions, xTile, yTile, pixelAccessor)
; |
696 } | 550 } |
| 551 return sampleStage->get(); |
697 } | 552 } |
698 | 553 |
699 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 554 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
700 // Pixel Blender Stage | 555 // Pixel Blender Stage |
701 template <SkAlphaType alphaType> | 556 template <SkAlphaType alphaType> |
702 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface
{ | 557 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface
{ |
703 public: | 558 public: |
704 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } | 559 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } |
705 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} | 560 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} |
706 void SK_VECTORCALL blendPixel(Sk4f pixel) override { | 561 void SK_VECTORCALL blendPixel(Sk4f pixel) override { |
707 SkASSERT(fDst + 1 <= fEnd ); | 562 SkASSERT(fDst + 1 <= fEnd ); |
708 SrcPixel(fDst, pixel, 0); | 563 this->srcPixel(fDst, pixel, 0); |
709 fDst += 1; | 564 fDst += 1; |
710 } | 565 } |
711 | 566 |
712 void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override
{ | 567 void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override
{ |
713 SkASSERT(fDst + 4 <= fEnd); | 568 SkASSERT(fDst + 4 <= fEnd); |
714 SkPM4f* dst = fDst; | 569 SkPM4f* dst = fDst; |
715 SrcPixel(dst, p0, 0); | 570 this->srcPixel(dst, p0, 0); |
716 SrcPixel(dst, p1, 1); | 571 this->srcPixel(dst, p1, 1); |
717 SrcPixel(dst, p2, 2); | 572 this->srcPixel(dst, p2, 2); |
718 SrcPixel(dst, p3, 3); | 573 this->srcPixel(dst, p3, 3); |
719 fDst += 4; | 574 fDst += 4; |
720 } | 575 } |
721 | 576 |
722 void setDestination(void* dst, int count) override { | 577 void setDestination(void* dst, int count) override { |
723 fDst = static_cast<SkPM4f*>(dst); | 578 fDst = static_cast<SkPM4f*>(dst); |
724 fEnd = fDst + count; | 579 fEnd = fDst + count; |
725 } | 580 } |
726 | 581 |
727 private: | 582 private: |
728 void SK_VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) { | 583 void SK_VECTORCALL srcPixel(SkPM4f* dst, Sk4f pixel, int index) { |
| 584 check_pixel(pixel); |
| 585 |
729 Sk4f newPixel = pixel; | 586 Sk4f newPixel = pixel; |
730 if (alphaType == kUnpremul_SkAlphaType) { | 587 if (alphaType == kUnpremul_SkAlphaType) { |
731 newPixel = Premultiply(pixel); | 588 newPixel = Premultiply(pixel); |
732 } | 589 } |
733 newPixel = newPixel * fPostAlpha; | 590 newPixel = newPixel * fPostAlpha; |
734 newPixel.store(dst + index); | 591 newPixel.store(dst + index); |
735 } | 592 } |
736 static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) { | 593 static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) { |
737 float alpha = pixel[3]; | 594 float alpha = pixel[3]; |
738 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; | 595 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 SkAlphaType alphaType = srcImageInfo.alphaType(); | 647 SkAlphaType alphaType = srcImageInfo.alphaType(); |
791 if (srcPixmap.colorType() == kIndex_8_SkColorType) { | 648 if (srcPixmap.colorType() == kIndex_8_SkColorType) { |
792 alphaType = kUnpremul_SkAlphaType; | 649 alphaType = kUnpremul_SkAlphaType; |
793 } | 650 } |
794 | 651 |
795 float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f); | 652 float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f); |
796 // As the stages are built, the chooser function may skip a stage. For examp
le, with the | 653 // As the stages are built, the chooser function may skip a stage. For examp
le, with the |
797 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. | 654 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. |
798 auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlend
erStage); | 655 auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlend
erStage); |
799 auto samplerStage = choose_pixel_sampler( | 656 auto samplerStage = choose_pixel_sampler( |
800 blenderStage, filterQuality, srcPixmap, paintColor, &fSampleStage, &fAcc
essor); | 657 blenderStage, filterQuality, xTile, yTile, |
| 658 srcPixmap, paintColor, &fSampleStage, &fAccessor); |
801 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, | 659 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, |
802 filterQuality, dx, &fTileStage); | 660 filterQuality, dx, &fTileStage); |
803 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage
); | 661 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage
); |
804 fLastStage = blenderStage; | 662 fLastStage = blenderStage; |
805 } | 663 } |
806 | 664 |
807 bool SkLinearBitmapPipeline::ClonePipelineForBlitting( | 665 bool SkLinearBitmapPipeline::ClonePipelineForBlitting( |
808 SkEmbeddableLinearPipeline* pipelineStorage, | 666 SkEmbeddableLinearPipeline* pipelineStorage, |
809 const SkLinearBitmapPipeline& pipeline, | 667 const SkLinearBitmapPipeline& pipeline, |
810 SkMatrix::TypeMask matrixMask, | 668 SkMatrix::TypeMask matrixMask, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { | 734 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { |
877 SkASSERT(count > 0); | 735 SkASSERT(count > 0); |
878 fLastStage->setDestination(dst, count); | 736 fLastStage->setDestination(dst, count); |
879 | 737 |
880 // The count and length arguments start out in a precise relation in order t
o keep the | 738 // The count and length arguments start out in a precise relation in order t
o keep the |
881 // math correct through the different stages. Count is the number of pixel t
o produce. | 739 // math correct through the different stages. Count is the number of pixel t
o produce. |
882 // Since the code samples at pixel centers, length is the distance from the
center of the | 740 // Since the code samples at pixel centers, length is the distance from the
center of the |
883 // first pixel to the center of the last pixel. This implies that length is
count-1. | 741 // first pixel to the center of the last pixel. This implies that length is
count-1. |
884 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); | 742 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); |
885 } | 743 } |
OLD | NEW |