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 CombinedTileStage final : public SkLinearBitmapPipeline::PointProcessorInt
erface { | 168 class NearestTileStage final : public SkLinearBitmapPipeline::PointProcessorInte
rface { |
169 public: | 169 public: |
170 CombinedTileStage(Next* next, SkISize dimensions) | 170 template <typename... Args> |
| 171 NearestTileStage(Next* next, SkISize dimensions) |
171 : fNext{next} | 172 : fNext{next} |
172 , fXStrategy{dimensions.width()} | 173 , fXStrategy{dimensions.width()} |
173 , fYStrategy{dimensions.height()}{ } | 174 , fYStrategy{dimensions.height()}{ } |
174 | 175 |
175 CombinedTileStage(Next* next, const CombinedTileStage& stage) | 176 NearestTileStage(Next* next, const NearestTileStage& stage) |
176 : fNext{next} | 177 : fNext{next} |
177 , fXStrategy{stage.fXStrategy} | 178 , fXStrategy{stage.fXStrategy} |
178 , fYStrategy{stage.fYStrategy} { } | 179 , fYStrategy{stage.fYStrategy} { } |
179 | 180 |
180 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 181 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
181 fXStrategy.tileXPoints(&xs); | 182 fXStrategy.tileXPoints(&xs); |
182 fYStrategy.tileYPoints(&ys); | 183 fYStrategy.tileYPoints(&ys); |
183 fNext->pointListFew(n, xs, ys); | 184 fNext->pointListFew(n, xs, ys); |
184 } | 185 } |
185 | 186 |
186 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | 187 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
187 fXStrategy.tileXPoints(&xs); | 188 fXStrategy.tileXPoints(&xs); |
188 fYStrategy.tileYPoints(&ys); | 189 fYStrategy.tileYPoints(&ys); |
189 fNext->pointList4(xs, ys); | 190 fNext->pointList4(xs, ys); |
190 } | 191 } |
191 | 192 |
192 // The span you pass must not be empty. | 193 // The span you pass must not be empty. |
193 void pointSpan(Span span) override { | 194 void pointSpan(Span span) override { |
194 SkASSERT(!span.isEmpty()); | 195 SkASSERT(!span.isEmpty()); |
195 SkPoint start; SkScalar length; int count; | 196 SkPoint start; SkScalar length; int count; |
196 std::tie(start, length, count) = span; | 197 std::tie(start, length, count) = span; |
197 | |
198 if (span.count() == 1) { | |
199 this->pointListFew(1, span.startX(), span.startY()); | |
200 return; | |
201 } | |
202 | |
203 SkScalar x = X(start); | 198 SkScalar x = X(start); |
204 SkScalar y = fYStrategy.tileY(Y(start)); | 199 SkScalar y = fYStrategy.tileY(Y(start)); |
205 Span yAdjustedSpan{{x, y}, length, count}; | 200 Span yAdjustedSpan{{x, y}, length, count}; |
206 | |
207 if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) { | 201 if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) { |
208 span_fallback(span, this); | 202 span_fallback(span, this); |
209 } | 203 } |
210 } | 204 } |
211 | 205 |
212 private: | 206 private: |
213 Next* const fNext; | 207 Next* const fNext; |
214 XStrategy fXStrategy; | 208 XStrategy fXStrategy; |
215 YStrategy fYStrategy; | 209 YStrategy fYStrategy; |
216 }; | 210 }; |
217 | 211 |
218 template <typename XStrategy, typename Next> | 212 template<typename XStrategy, typename YStrategy, 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> |
219 void choose_tiler_ymode( | 365 void choose_tiler_ymode( |
220 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, | 366 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, |
221 Next* next, | 367 SkLinearBitmapPipeline::SampleProcessorInterface* next, |
222 SkLinearBitmapPipeline::TileStage* tileStage) { | 368 SkLinearBitmapPipeline::TileStage* tileStage) { |
223 switch (yMode) { | 369 switch (yMode) { |
224 case SkShader::kClamp_TileMode: { | 370 case SkShader::kClamp_TileMode: |
225 using Tiler = CombinedTileStage<XStrategy, YClampStrategy, Next>; | 371 make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions
, next, tileStage); |
226 tileStage->initStage<Tiler>(next, dimensions); | |
227 break; | 372 break; |
228 } | 373 case SkShader::kRepeat_TileMode: |
229 case SkShader::kRepeat_TileMode: { | 374 make_tile_stage<XStrategy, YRepeatStrategy>(filterQuality, dimension
s, next, tileStage); |
230 using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, Next>; | |
231 tileStage->initStage<Tiler>(next, dimensions); | |
232 break; | 375 break; |
233 } | 376 case SkShader::kMirror_TileMode: |
234 case SkShader::kMirror_TileMode: { | 377 make_tile_stage<XStrategy, YMirrorStrategy>(filterQuality, dimension
s, next, tileStage); |
235 using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, Next>; | |
236 tileStage->initStage<Tiler>(next, dimensions); | |
237 break; | 378 break; |
238 } | |
239 } | 379 } |
240 }; | 380 }; |
241 | 381 |
242 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( | 382 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( |
243 SkLinearBitmapPipeline::SampleProcessorInterface* next, | 383 SkLinearBitmapPipeline::SampleProcessorInterface* next, |
244 SkISize dimensions, | 384 SkISize dimensions, |
245 SkShader::TileMode xMode, | 385 SkShader::TileMode xMode, |
246 SkShader::TileMode yMode, | 386 SkShader::TileMode yMode, |
247 SkFilterQuality filterQuality, | 387 SkFilterQuality filterQuality, |
248 SkScalar dx, | 388 SkScalar dx, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 int32_t y = SkScalarTruncToInt(span.startY()); | 460 int32_t y = SkScalarTruncToInt(span.startY()); |
321 const uint32_t* src = this->pixelAddress(x, y); | 461 const uint32_t* src = this->pixelAddress(x, y); |
322 uint32_t* dest = fDest; | 462 uint32_t* dest = fDest; |
323 while (repeatCount --> 0) { | 463 while (repeatCount --> 0) { |
324 memmove(dest, src, span.count() * sizeof(uint32_t)); | 464 memmove(dest, src, span.count() * sizeof(uint32_t)); |
325 dest += span.count(); | 465 dest += span.count(); |
326 } | 466 } |
327 fDest = dest; | 467 fDest = dest; |
328 } | 468 } |
329 | 469 |
| 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 |
330 void setDestination(void* dst, int count) override { | 474 void setDestination(void* dst, int count) override { |
331 fDest = static_cast<uint32_t*>(dst); | 475 fDest = static_cast<uint32_t*>(dst); |
332 fEnd = fDest + count; | 476 fEnd = fDest + count; |
333 } | 477 } |
334 | 478 |
335 private: | 479 private: |
336 const uint32_t* pixelAddress(int32_t x, int32_t y) { | 480 const uint32_t* pixelAddress(int32_t x, int32_t y) { |
337 return &fSrc[fWidth * y + x]; | 481 return &fSrc[fWidth * y + x]; |
338 } | 482 } |
339 const uint32_t* const fSrc; | 483 const uint32_t* const fSrc; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 int32_t y = (int32_t)span.startY(); | 531 int32_t y = (int32_t)span.startY(); |
388 const uint32_t* beginSpan = this->pixelAddress(x, y); | 532 const uint32_t* beginSpan = this->pixelAddress(x, y); |
389 | 533 |
390 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount,
span.count()); | 534 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount,
span.count()); |
391 | 535 |
392 fDest += span.count() * repeatCount; | 536 fDest += span.count() * repeatCount; |
393 | 537 |
394 SkASSERT(fDest <= fEnd); | 538 SkASSERT(fDest <= fEnd); |
395 } | 539 } |
396 | 540 |
| 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 |
397 void setDestination(void* dst, int count) override { | 545 void setDestination(void* dst, int count) override { |
398 SkASSERT(count > 0); | 546 SkASSERT(count > 0); |
399 fDest = static_cast<uint32_t*>(dst); | 547 fDest = static_cast<uint32_t*>(dst); |
400 fEnd = fDest + count; | 548 fEnd = fDest + count; |
401 } | 549 } |
402 | 550 |
403 private: | 551 private: |
404 const uint32_t* pixelAddress(int32_t x, int32_t y) { | 552 const uint32_t* pixelAddress(int32_t x, int32_t y) { |
405 return &fSrc[fWidth * y + x]; | 553 return &fSrc[fWidth * y + x]; |
406 } | 554 } |
(...skipping 20 matching lines...) Expand all Loading... |
427 using PA = PixelAccessor<colorType, kSRGB_SkGammaType>; | 575 using PA = PixelAccessor<colorType, kSRGB_SkGammaType>; |
428 accessor->init<PA>(srcPixmap); | 576 accessor->init<PA>(srcPixmap); |
429 return accessor->get(); | 577 return accessor->get(); |
430 } else { | 578 } else { |
431 using PA = PixelAccessor<colorType, kLinear_SkGammaType>; | 579 using PA = PixelAccessor<colorType, kLinear_SkGammaType>; |
432 accessor->init<PA>(srcPixmap); | 580 accessor->init<PA>(srcPixmap); |
433 return accessor->get(); | 581 return accessor->get(); |
434 } | 582 } |
435 } | 583 } |
436 | 584 |
437 static SkLinearBitmapPipeline::PixelAccessorInterface* choose_pixel_accessor( | 585 template<template <typename, typename> class Sampler> |
| 586 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba
se( |
| 587 Blender* next, |
438 const SkPixmap& srcPixmap, | 588 const SkPixmap& srcPixmap, |
439 const SkColor A8TintColor, | 589 const SkColor A8TintColor, |
| 590 SkLinearBitmapPipeline::SampleStage* sampleStage, |
440 SkLinearBitmapPipeline::Accessor* accessor) | 591 SkLinearBitmapPipeline::Accessor* accessor) |
441 { | 592 { |
442 const SkImageInfo& imageInfo = srcPixmap.info(); | 593 const SkImageInfo& imageInfo = srcPixmap.info(); |
443 | 594 |
444 SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr; | 595 SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr; |
445 switch (imageInfo.colorType()) { | 596 switch (imageInfo.colorType()) { |
446 case kAlpha_8_SkColorType: { | 597 case kAlpha_8_SkColorType: { |
447 using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaTy
pe>; | 598 using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaTy
pe>; |
448 accessor->init<PA>(srcPixmap, A8TintColor); | 599 accessor->init<PA>(srcPixmap, A8TintColor); |
449 pixelAccessor = accessor->get(); | 600 pixelAccessor = accessor->get(); |
(...skipping 21 matching lines...) Expand all Loading... |
471 using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaT
ype>; | 622 using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaT
ype>; |
472 accessor->init<PA>(srcPixmap); | 623 accessor->init<PA>(srcPixmap); |
473 pixelAccessor = accessor->get(); | 624 pixelAccessor = accessor->get(); |
474 } | 625 } |
475 break; | 626 break; |
476 default: | 627 default: |
477 SkFAIL("Not implemented. Unsupported src"); | 628 SkFAIL("Not implemented. Unsupported src"); |
478 break; | 629 break; |
479 } | 630 } |
480 | 631 |
481 return pixelAccessor; | 632 using S = Sampler<PixelAccessorShim, Blender>; |
| 633 sampleStage->initStage<S>(next, pixelAccessor); |
| 634 return sampleStage->get(); |
482 } | 635 } |
483 | 636 |
484 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( | 637 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( |
485 Blender* next, | 638 Blender* next, |
486 SkFilterQuality filterQuality, | 639 SkFilterQuality filterQuality, |
487 SkShader::TileMode xTile, SkShader::TileMode yTile, | |
488 const SkPixmap& srcPixmap, | 640 const SkPixmap& srcPixmap, |
489 const SkColor A8TintColor, | 641 const SkColor A8TintColor, |
490 SkLinearBitmapPipeline::SampleStage* sampleStage, | 642 SkLinearBitmapPipeline::SampleStage* sampleStage, |
491 SkLinearBitmapPipeline::Accessor* accessor) { | 643 SkLinearBitmapPipeline::Accessor* accessor) { |
492 const SkImageInfo& imageInfo = srcPixmap.info(); | 644 const SkImageInfo& imageInfo = srcPixmap.info(); |
493 SkISize dimensions = imageInfo.dimensions(); | |
494 | 645 |
495 // Special case samplers with fully expanded templates | 646 // Special case samplers with fully expanded templates |
496 if (imageInfo.gammaCloseToSRGB()) { | 647 if (imageInfo.gammaCloseToSRGB()) { |
497 if (filterQuality == kNone_SkFilterQuality) { | 648 if (filterQuality == kNone_SkFilterQuality) { |
498 switch (imageInfo.colorType()) { | 649 switch (imageInfo.colorType()) { |
499 case kN32_SkColorType: { | 650 case kN32_SkColorType: { |
500 using S = | 651 using S = |
501 NearestNeighborSampler< | 652 NearestNeighborSampler< |
502 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; | 653 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; |
503 sampleStage->initStage<S>(next, srcPixmap); | 654 sampleStage->initStage<S>(next, srcPixmap); |
504 return sampleStage->get(); | 655 return sampleStage->get(); |
505 } | 656 } |
506 case kIndex_8_SkColorType: { | 657 case kIndex_8_SkColorType: { |
507 using S = | 658 using S = |
508 NearestNeighborSampler< | 659 NearestNeighborSampler< |
509 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; | 660 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; |
510 sampleStage->initStage<S>(next, srcPixmap); | 661 sampleStage->initStage<S>(next, srcPixmap); |
511 return sampleStage->get(); | 662 return sampleStage->get(); |
512 } | 663 } |
513 default: | 664 default: |
514 break; | 665 break; |
515 } | 666 } |
516 } else { | 667 } else { |
517 switch (imageInfo.colorType()) { | 668 switch (imageInfo.colorType()) { |
518 case kN32_SkColorType: { | 669 case kN32_SkColorType: { |
519 using S = | 670 using S = |
520 BilerpSampler< | 671 BilerpSampler< |
521 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; | 672 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen
der>; |
522 sampleStage->initStage<S>(next, dimensions, xTile, yTile, sr
cPixmap); | 673 sampleStage->initStage<S>(next, srcPixmap); |
523 return sampleStage->get(); | 674 return sampleStage->get(); |
524 } | 675 } |
525 case kIndex_8_SkColorType: { | 676 case kIndex_8_SkColorType: { |
526 using S = | 677 using S = |
527 BilerpSampler< | 678 BilerpSampler< |
528 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; | 679 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>,
Blender>; |
529 sampleStage->initStage<S>(next, dimensions, xTile, yTile, sr
cPixmap); | 680 sampleStage->initStage<S>(next, srcPixmap); |
530 return sampleStage->get(); | 681 return sampleStage->get(); |
531 } | 682 } |
532 default: | 683 default: |
533 break; | 684 break; |
534 } | 685 } |
535 } | 686 } |
536 } | 687 } |
537 | 688 |
538 auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor)
; | |
539 // General cases. | 689 // General cases. |
540 if (filterQuality == kNone_SkFilterQuality) { | 690 if (filterQuality == kNone_SkFilterQuality) { |
541 using S = NearestNeighborSampler<PixelAccessorShim, Blender>; | 691 return choose_pixel_sampler_base<NearestNeighborSampler>( |
542 sampleStage->initStage<S>(next, pixelAccessor); | 692 next, srcPixmap, A8TintColor, sampleStage, accessor); |
543 } else { | 693 } else { |
544 using S = BilerpSampler<PixelAccessorShim, Blender>; | 694 return choose_pixel_sampler_base<BilerpSampler>( |
545 sampleStage->initStage<S>(next, dimensions, xTile, yTile, pixelAccessor)
; | 695 next, srcPixmap, A8TintColor, sampleStage, accessor); |
546 } | 696 } |
547 return sampleStage->get(); | |
548 } | 697 } |
549 | 698 |
550 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 699 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
551 // Pixel Blender Stage | 700 // Pixel Blender Stage |
552 template <SkAlphaType alphaType> | 701 template <SkAlphaType alphaType> |
553 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface
{ | 702 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface
{ |
554 public: | 703 public: |
555 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } | 704 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } |
556 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} | 705 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} |
557 void SK_VECTORCALL blendPixel(Sk4f pixel) override { | 706 void SK_VECTORCALL blendPixel(Sk4f pixel) override { |
558 SkASSERT(fDst + 1 <= fEnd ); | 707 SkASSERT(fDst + 1 <= fEnd ); |
559 this->srcPixel(fDst, pixel, 0); | 708 SrcPixel(fDst, pixel, 0); |
560 fDst += 1; | 709 fDst += 1; |
561 } | 710 } |
562 | 711 |
563 void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override
{ | 712 void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override
{ |
564 SkASSERT(fDst + 4 <= fEnd); | 713 SkASSERT(fDst + 4 <= fEnd); |
565 SkPM4f* dst = fDst; | 714 SkPM4f* dst = fDst; |
566 this->srcPixel(dst, p0, 0); | 715 SrcPixel(dst, p0, 0); |
567 this->srcPixel(dst, p1, 1); | 716 SrcPixel(dst, p1, 1); |
568 this->srcPixel(dst, p2, 2); | 717 SrcPixel(dst, p2, 2); |
569 this->srcPixel(dst, p3, 3); | 718 SrcPixel(dst, p3, 3); |
570 fDst += 4; | 719 fDst += 4; |
571 } | 720 } |
572 | 721 |
573 void setDestination(void* dst, int count) override { | 722 void setDestination(void* dst, int count) override { |
574 fDst = static_cast<SkPM4f*>(dst); | 723 fDst = static_cast<SkPM4f*>(dst); |
575 fEnd = fDst + count; | 724 fEnd = fDst + count; |
576 } | 725 } |
577 | 726 |
578 private: | 727 private: |
579 void SK_VECTORCALL srcPixel(SkPM4f* dst, Sk4f pixel, int index) { | 728 void SK_VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) { |
580 check_pixel(pixel); | |
581 | |
582 Sk4f newPixel = pixel; | 729 Sk4f newPixel = pixel; |
583 if (alphaType == kUnpremul_SkAlphaType) { | 730 if (alphaType == kUnpremul_SkAlphaType) { |
584 newPixel = Premultiply(pixel); | 731 newPixel = Premultiply(pixel); |
585 } | 732 } |
586 newPixel = newPixel * fPostAlpha; | 733 newPixel = newPixel * fPostAlpha; |
587 newPixel.store(dst + index); | 734 newPixel.store(dst + index); |
588 } | 735 } |
589 static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) { | 736 static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) { |
590 float alpha = pixel[3]; | 737 float alpha = pixel[3]; |
591 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; | 738 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 SkAlphaType alphaType = srcImageInfo.alphaType(); | 790 SkAlphaType alphaType = srcImageInfo.alphaType(); |
644 if (srcPixmap.colorType() == kIndex_8_SkColorType) { | 791 if (srcPixmap.colorType() == kIndex_8_SkColorType) { |
645 alphaType = kUnpremul_SkAlphaType; | 792 alphaType = kUnpremul_SkAlphaType; |
646 } | 793 } |
647 | 794 |
648 float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f); | 795 float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f); |
649 // As the stages are built, the chooser function may skip a stage. For examp
le, with the | 796 // As the stages are built, the chooser function may skip a stage. For examp
le, with the |
650 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. | 797 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. |
651 auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlend
erStage); | 798 auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlend
erStage); |
652 auto samplerStage = choose_pixel_sampler( | 799 auto samplerStage = choose_pixel_sampler( |
653 blenderStage, filterQuality, xTile, yTile, | 800 blenderStage, filterQuality, srcPixmap, paintColor, &fSampleStage, &fAcc
essor); |
654 srcPixmap, paintColor, &fSampleStage, &fAccessor); | |
655 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, | 801 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, |
656 filterQuality, dx, &fTileStage); | 802 filterQuality, dx, &fTileStage); |
657 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage
); | 803 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage
); |
658 fLastStage = blenderStage; | 804 fLastStage = blenderStage; |
659 } | 805 } |
660 | 806 |
661 bool SkLinearBitmapPipeline::ClonePipelineForBlitting( | 807 bool SkLinearBitmapPipeline::ClonePipelineForBlitting( |
662 SkEmbeddableLinearPipeline* pipelineStorage, | 808 SkEmbeddableLinearPipeline* pipelineStorage, |
663 const SkLinearBitmapPipeline& pipeline, | 809 const SkLinearBitmapPipeline& pipeline, |
664 SkMatrix::TypeMask matrixMask, | 810 SkMatrix::TypeMask matrixMask, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { | 876 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { |
731 SkASSERT(count > 0); | 877 SkASSERT(count > 0); |
732 fLastStage->setDestination(dst, count); | 878 fLastStage->setDestination(dst, count); |
733 | 879 |
734 // The count and length arguments start out in a precise relation in order t
o keep the | 880 // The count and length arguments start out in a precise relation in order t
o keep the |
735 // math correct through the different stages. Count is the number of pixel t
o produce. | 881 // math correct through the different stages. Count is the number of pixel t
o produce. |
736 // Since the code samples at pixel centers, length is the distance from the
center of the | 882 // Since the code samples at pixel centers, length is the distance from the
center of the |
737 // first pixel to the center of the last pixel. This implies that length is
count-1. | 883 // first pixel to the center of the last pixel. This implies that length is
count-1. |
738 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); | 884 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); |
739 } | 885 } |
OLD | NEW |