Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: src/core/SkLinearBitmapPipeline.cpp

Issue 2134893002: Redo Tiling (Closed) Base URL: https://skia.googlesource.com/skia.git@reduce-LBP-sample
Patch Set: Document bug. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkLinearBitmapPipeline.h ('k') | src/core/SkLinearBitmapPipeline_core.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkLinearBitmapPipeline.h ('k') | src/core/SkLinearBitmapPipeline_core.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698