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 #ifndef SkLinearBitmapPipeline_sampler_DEFINED | 8 #ifndef SkLinearBitmapPipeline_sampler_DEFINED |
9 #define SkLinearBitmapPipeline_sampler_DEFINED | 9 #define SkLinearBitmapPipeline_sampler_DEFINED |
10 | 10 |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 } | 259 } |
260 | 260 |
261 const void* row(int y) const { return fSrc + y * fWidth[0]; } | 261 const void* row(int y) const { return fSrc + y * fWidth[0]; } |
262 | 262 |
263 private: | 263 private: |
264 const Element* const fSrc; | 264 const Element* const fSrc; |
265 const Sk4i fWidth; | 265 const Sk4i fWidth; |
266 PixelGetter<colorType, colorProfile> fGetter; | 266 PixelGetter<colorType, colorProfile> fGetter; |
267 }; | 267 }; |
268 | 268 |
269 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 269 // We're moving through source space at a rate of 1 source pixel per 1 dst pixel
. |
270 // GeneralSampler handles all the different sampling scenarios. It makes runtime
decisions to | 270 // We'll never re-use pixels, but we can at least load contiguous pixels. |
271 // choose the fastest strategy given a particular job. It ultimately uses PixelG
etters to access | 271 template <typename Next, typename Strategy> |
272 // the pixels. | 272 static void src_strategy_blend(Span span, Next* next, Strategy* strategy) { |
| 273 SkPoint start; |
| 274 SkScalar length; |
| 275 int count; |
| 276 std::tie(start, length, count) = span; |
| 277 int ix = SkScalarFloorToInt(X(start)); |
| 278 const void* row = strategy->row((int)std::floor(Y(start))); |
| 279 if (length > 0) { |
| 280 while (count >= 4) { |
| 281 Sk4f px0, px1, px2, px3; |
| 282 strategy->get4Pixels(row, ix, &px0, &px1, &px2, &px3); |
| 283 next->blend4Pixels(px0, px1, px2, px3); |
| 284 ix += 4; |
| 285 count -= 4; |
| 286 } |
| 287 |
| 288 while (count > 0) { |
| 289 next->blendPixel(strategy->getPixelFromRow(row, ix)); |
| 290 ix += 1; |
| 291 count -= 1; |
| 292 } |
| 293 } else { |
| 294 while (count >= 4) { |
| 295 Sk4f px0, px1, px2, px3; |
| 296 strategy->get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0); |
| 297 next->blend4Pixels(px0, px1, px2, px3); |
| 298 ix -= 4; |
| 299 count -= 4; |
| 300 } |
| 301 |
| 302 while (count > 0) { |
| 303 next->blendPixel(strategy->getPixelFromRow(row, ix)); |
| 304 ix -= 1; |
| 305 count -= 1; |
| 306 } |
| 307 } |
| 308 } |
| 309 |
| 310 // NearestNeighborSampler - use nearest neighbor filtering to create runs of des
tination pixels. |
273 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> | 311 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> |
274 class GeneralSampler { | 312 class NearestNeighborSampler : public SkLinearBitmapPipeline::SampleProcessorInt
erface { |
275 public: | 313 public: |
276 template<typename... Args> | 314 template<typename... Args> |
277 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) | 315 NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next
, Args&& ... args) |
278 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } | 316 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } |
279 | 317 |
280 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, | 318 NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next
, |
281 const GeneralSampler& sampler) | 319 const NearestNeighborSampler& sampler) |
282 : fNext{next}, fStrategy{sampler.fStrategy} { } | 320 : fNext{next}, fStrategy{sampler.fStrategy} { } |
283 | 321 |
284 void VECTORCALL nearestListFew(int n, Sk4s xs, Sk4s ys) { | 322 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
285 SkASSERT(0 < n && n < 4); | 323 SkASSERT(0 < n && n < 4); |
286 Sk4f px0, px1, px2; | 324 Sk4f px0, px1, px2; |
287 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); | 325 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); |
288 if (n >= 1) fNext->blendPixel(px0); | 326 if (n >= 1) fNext->blendPixel(px0); |
289 if (n >= 2) fNext->blendPixel(px1); | 327 if (n >= 2) fNext->blendPixel(px1); |
290 if (n >= 3) fNext->blendPixel(px2); | 328 if (n >= 3) fNext->blendPixel(px2); |
291 } | 329 } |
292 | 330 |
293 void VECTORCALL nearestList4(Sk4s xs, Sk4s ys) { | 331 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
294 Sk4f px0, px1, px2, px3; | 332 Sk4f px0, px1, px2, px3; |
295 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); | 333 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); |
296 fNext->blend4Pixels(px0, px1, px2, px3); | 334 fNext->blend4Pixels(px0, px1, px2, px3); |
297 } | 335 } |
298 | 336 |
299 void nearestSpan(Span span) { | 337 void pointSpan(Span span) override { |
300 SkASSERT(!span.isEmpty()); | 338 SkASSERT(!span.isEmpty()); |
301 SkPoint start; | 339 SkPoint start; |
302 SkScalar length; | 340 SkScalar length; |
303 int count; | 341 int count; |
304 std::tie(start, length, count) = span; | 342 std::tie(start, length, count) = span; |
305 SkScalar absLength = SkScalarAbs(length); | 343 SkScalar absLength = SkScalarAbs(length); |
306 if (absLength < (count - 1)) { | 344 if (absLength < (count - 1)) { |
307 this->nearestSpanSlowRate(span); | 345 this->spanSlowRate(span); |
308 } else if (absLength == (count - 1)) { | 346 } else if (absLength == (count - 1)) { |
309 this->nearestSpanUnitRate(span); | 347 src_strategy_blend(span, fNext, &fStrategy); |
310 } else { | 348 } else { |
311 this->nearestSpanFastRate(span); | 349 this->spanFastRate(span); |
312 } | 350 } |
313 } | 351 } |
314 | 352 |
315 Sk4f bilerpNonEdgePixel(SkScalar x, SkScalar y) { | 353 void repeatSpan(Span span, int32_t repeatCount) override { |
316 Sk4f px00, px10, px01, px11; | 354 while (repeatCount > 0) { |
317 // bilerp4() expects xs, ys are the top-lefts of the 2x2 kernel. | 355 this->pointSpan(span); |
318 Sk4f xs = Sk4f{x} - 0.5f; | 356 repeatCount--; |
319 Sk4f ys = Sk4f{y} - 0.5f; | 357 } |
320 Sk4f sampleXs = xs + Sk4f{0.0f, 1.0f, 0.0f, 1.0f}; | |
321 Sk4f sampleYs = ys + Sk4f{0.0f, 0.0f, 1.0f, 1.0f}; | |
322 fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11); | |
323 return bilerp4(xs, ys, px00, px10, px01, px11); | |
324 } | 358 } |
325 | 359 |
326 void VECTORCALL bilerpListFew(int n, Sk4s xs, Sk4s ys) { | 360 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { |
327 SkASSERT(0 < n && n < 4); | 361 SkFAIL("Using nearest neighbor sampler, but calling a bilerpEdge."); |
328 auto bilerpPixel = [&](int index) { | |
329 return this->bilerpNonEdgePixel(xs[index], ys[index]); | |
330 }; | |
331 | |
332 if (n >= 1) fNext->blendPixel(bilerpPixel(0)); | |
333 if (n >= 2) fNext->blendPixel(bilerpPixel(1)); | |
334 if (n >= 3) fNext->blendPixel(bilerpPixel(2)); | |
335 } | 362 } |
336 | 363 |
337 void VECTORCALL bilerpList4(Sk4s xs, Sk4s ys) { | 364 void bilerpSpan(Span span, SkScalar y) override { |
338 auto bilerpPixel = [&](int index) { | 365 SkFAIL("Using nearest neighbor sampler, but calling a bilerpSpan."); |
339 return this->bilerpNonEdgePixel(xs[index], ys[index]); | |
340 }; | |
341 fNext->blend4Pixels(bilerpPixel(0), bilerpPixel(1), bilerpPixel(2), bile
rpPixel(3)); | |
342 } | |
343 | |
344 void VECTORCALL bilerpEdge(Sk4s sampleXs, Sk4s sampleYs) { | |
345 Sk4f px00, px10, px01, px11; | |
346 Sk4f xs = Sk4f{sampleXs[0]}; | |
347 Sk4f ys = Sk4f{sampleYs[0]}; | |
348 fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11); | |
349 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); | |
350 fNext->blendPixel(pixel); | |
351 } | |
352 | |
353 void bilerpSpan(Span span) { | |
354 this->bilerpSpanWithY(span, span.startY()); | |
355 } | |
356 | |
357 void bilerpSpanWithY(Span span, SkScalar y) { | |
358 SkASSERT(!span.isEmpty()); | |
359 SkPoint start; | |
360 SkScalar length; | |
361 int count; | |
362 std::tie(start, length, count) = span; | |
363 SkScalar absLength = SkScalarAbs(length); | |
364 if (absLength == 0.0f) { | |
365 this->bilerpSpanZeroRate(span, y); | |
366 } else if (absLength < (count - 1)) { | |
367 this->bilerpSpanSlowRate(span, y); | |
368 } else if (absLength == (count - 1)) { | |
369 if (std::fmod(span.startX() - 0.5f, 1.0f) == 0.0f) { | |
370 if (std::fmod(span.startY() - 0.5f, 1.0f) == 0.0f) { | |
371 this->nearestSpanUnitRate(span); | |
372 } else { | |
373 this->bilerpSpanUnitRateAlignedX(span, y); | |
374 } | |
375 } else { | |
376 this->bilerpSpanUnitRate(span, y); | |
377 } | |
378 } else { | |
379 this->bilerpSpanFastRate(span, y); | |
380 } | |
381 } | 366 } |
382 | 367 |
383 private: | 368 private: |
384 // When moving through source space more slowly than dst space (zoomed in), | 369 // When moving through source space more slowly than dst space (zoomed in), |
385 // we'll be sampling from the same source pixel more than once. | 370 // we'll be sampling from the same source pixel more than once. |
386 void nearestSpanSlowRate(Span span) { | 371 void spanSlowRate(Span span) { |
387 SkPoint start; | 372 SkPoint start; |
388 SkScalar length; | 373 SkScalar length; |
389 int count; | 374 int count; |
390 std::tie(start, length, count) = span; | 375 std::tie(start, length, count) = span; |
391 SkScalar x = X(start); | 376 SkScalar x = X(start); |
392 SkFixed fx = SkScalarToFixed(x); | 377 SkFixed fx = SkScalarToFixed(x); |
393 SkScalar dx = length / (count - 1); | 378 SkScalar dx = length / (count - 1); |
394 SkFixed fdx = SkScalarToFixed(dx); | 379 SkFixed fdx = SkScalarToFixed(dx); |
395 | 380 |
396 const void* row = fStrategy.row((int)std::floor(Y(start))); | 381 const void* row = fStrategy.row((int)std::floor(Y(start))); |
(...skipping 25 matching lines...) Expand all Loading... |
422 count -= 4; | 407 count -= 4; |
423 } | 408 } |
424 while (count > 0) { | 409 while (count > 0) { |
425 next->blendPixel(getNextPixel()); | 410 next->blendPixel(getNextPixel()); |
426 count -= 1; | 411 count -= 1; |
427 } | 412 } |
428 } | 413 } |
429 | 414 |
430 // We're moving through source space at a rate of 1 source pixel per 1 dst p
ixel. | 415 // We're moving through source space at a rate of 1 source pixel per 1 dst p
ixel. |
431 // We'll never re-use pixels, but we can at least load contiguous pixels. | 416 // We'll never re-use pixels, but we can at least load contiguous pixels. |
432 void nearestSpanUnitRate(Span span) { | 417 void spanUnitRate(Span span) { |
| 418 src_strategy_blend(span, fNext, &fStrategy); |
| 419 } |
| 420 |
| 421 // We're moving through source space faster than dst (zoomed out), |
| 422 // so we'll never reuse a source pixel or be able to do contiguous loads. |
| 423 void spanFastRate(Span span) { |
| 424 span_fallback(span, this); |
| 425 } |
| 426 |
| 427 Next* const fNext; |
| 428 PixelAccessor<colorType, colorProfile> fStrategy; |
| 429 }; |
| 430 |
| 431 // BilerpSampler - use a bilerp filter to create runs of destination pixels. |
| 432 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> |
| 433 class BilerpSampler : public SkLinearBitmapPipeline::SampleProcessorInterface { |
| 434 public: |
| 435 template<typename... Args> |
| 436 BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) |
| 437 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } |
| 438 |
| 439 BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, |
| 440 const BilerpSampler& sampler) |
| 441 : fNext{next}, fStrategy{sampler.fStrategy} { } |
| 442 |
| 443 Sk4f bilerpNonEdgePixel(SkScalar x, SkScalar y) { |
| 444 Sk4f px00, px10, px01, px11; |
| 445 |
| 446 // bilerp4() expects xs, ys are the top-lefts of the 2x2 kernel. |
| 447 Sk4f xs = Sk4f{x} - 0.5f; |
| 448 Sk4f ys = Sk4f{y} - 0.5f; |
| 449 Sk4f sampleXs = xs + Sk4f{0.0f, 1.0f, 0.0f, 1.0f}; |
| 450 Sk4f sampleYs = ys + Sk4f{0.0f, 0.0f, 1.0f, 1.0f}; |
| 451 fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11); |
| 452 return bilerp4(xs, ys, px00, px10, px01, px11); |
| 453 } |
| 454 |
| 455 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
| 456 SkASSERT(0 < n && n < 4); |
| 457 auto bilerpPixel = [&](int index) { |
| 458 return this->bilerpNonEdgePixel(xs[index], ys[index]); |
| 459 }; |
| 460 |
| 461 if (n >= 1) fNext->blendPixel(bilerpPixel(0)); |
| 462 if (n >= 2) fNext->blendPixel(bilerpPixel(1)); |
| 463 if (n >= 3) fNext->blendPixel(bilerpPixel(2)); |
| 464 } |
| 465 |
| 466 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
| 467 auto bilerpPixel = [&](int index) { |
| 468 return this->bilerpNonEdgePixel(xs[index], ys[index]); |
| 469 }; |
| 470 fNext->blend4Pixels(bilerpPixel(0), bilerpPixel(1), bilerpPixel(2), bile
rpPixel(3)); |
| 471 } |
| 472 |
| 473 void pointSpan(Span span) override { |
| 474 this->bilerpSpan(span, span.startY()); |
| 475 } |
| 476 |
| 477 void repeatSpan(Span span, int32_t repeatCount) override { |
| 478 while (repeatCount > 0) { |
| 479 this->pointSpan(span); |
| 480 repeatCount--; |
| 481 } |
| 482 } |
| 483 |
| 484 void VECTORCALL bilerpEdge(Sk4s sampleXs, Sk4s sampleYs) override { |
| 485 Sk4f px00, px10, px01, px11; |
| 486 Sk4f xs = Sk4f{sampleXs[0]}; |
| 487 Sk4f ys = Sk4f{sampleYs[0]}; |
| 488 fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11); |
| 489 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); |
| 490 fNext->blendPixel(pixel); |
| 491 } |
| 492 |
| 493 void bilerpSpan(Span span, SkScalar y) override { |
| 494 SkASSERT(!span.isEmpty()); |
433 SkPoint start; | 495 SkPoint start; |
434 SkScalar length; | 496 SkScalar length; |
435 int count; | 497 int count; |
436 std::tie(start, length, count) = span; | 498 std::tie(start, length, count) = span; |
437 int ix = SkScalarFloorToInt(X(start)); | 499 SkScalar absLength = SkScalarAbs(length); |
438 const void* row = fStrategy.row((int)std::floor(Y(start))); | 500 if (absLength == 0.0f) { |
439 Next* next = fNext; | 501 this->spanZeroRate(span, y); |
440 if (length > 0) { | 502 } else if (absLength < (count - 1)) { |
441 while (count >= 4) { | 503 this->spanSlowRate(span, y); |
442 Sk4f px0, px1, px2, px3; | 504 } else if (absLength == (count - 1)) { |
443 fStrategy.get4Pixels(row, ix, &px0, &px1, &px2, &px3); | 505 if (std::fmod(span.startX() - 0.5f, 1.0f) == 0.0f) { |
444 next->blend4Pixels(px0, px1, px2, px3); | 506 if (std::fmod(span.startY() - 0.5f, 1.0f) == 0.0f) { |
445 ix += 4; | 507 src_strategy_blend(span, fNext, &fStrategy); |
446 count -= 4; | 508 } else { |
447 } | 509 this->spanUnitRateAlignedX(span, y); |
448 | 510 } |
449 while (count > 0) { | 511 } else { |
450 next->blendPixel(fStrategy.getPixelFromRow(row, ix)); | 512 this->spanUnitRate(span, y); |
451 ix += 1; | |
452 count -= 1; | |
453 } | 513 } |
454 } else { | 514 } else { |
455 while (count >= 4) { | 515 this->spanFastRate(span, y); |
456 Sk4f px0, px1, px2, px3; | |
457 fStrategy.get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0); | |
458 next->blend4Pixels(px0, px1, px2, px3); | |
459 ix -= 4; | |
460 count -= 4; | |
461 } | |
462 | |
463 while (count > 0) { | |
464 next->blendPixel(fStrategy.getPixelFromRow(row, ix)); | |
465 ix -= 1; | |
466 count -= 1; | |
467 } | |
468 } | 516 } |
469 } | 517 } |
470 | 518 |
471 // We're moving through source space faster than dst (zoomed out), | 519 private: |
472 // so we'll never reuse a source pixel or be able to do contiguous loads. | 520 void spanZeroRate(Span span, SkScalar y1) { |
473 void nearestSpanFastRate(Span span) { | |
474 struct NearestWrapper { | |
475 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) { | |
476 fSampler.nearestListFew(n, xs, ys); | |
477 } | |
478 | |
479 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) { | |
480 fSampler.nearestList4(xs, ys); | |
481 } | |
482 | |
483 GeneralSampler& fSampler; | |
484 }; | |
485 NearestWrapper wrapper{*this}; | |
486 span_fallback(span, &wrapper); | |
487 } | |
488 | |
489 void bilerpSpanZeroRate(Span span, SkScalar y1) { | |
490 SkScalar y0 = span.startY() - 0.5f; | 521 SkScalar y0 = span.startY() - 0.5f; |
491 y1 += 0.5f; | 522 y1 += 0.5f; |
492 int iy0 = SkScalarFloorToInt(y0); | 523 int iy0 = SkScalarFloorToInt(y0); |
493 SkScalar filterY1 = y0 - iy0; | 524 SkScalar filterY1 = y0 - iy0; |
494 SkScalar filterY0 = 1.0f - filterY1; | 525 SkScalar filterY0 = 1.0f - filterY1; |
495 int iy1 = SkScalarFloorToInt(y1); | 526 int iy1 = SkScalarFloorToInt(y1); |
496 int ix = SkScalarFloorToInt(span.startX()); | 527 int ix = SkScalarFloorToInt(span.startX()); |
497 Sk4f pixelY0 = fStrategy.getPixelFromRow(fStrategy.row(iy0), ix); | 528 Sk4f pixelY0 = fStrategy.getPixelFromRow(fStrategy.row(iy0), ix); |
498 Sk4f pixelY1 = fStrategy.getPixelFromRow(fStrategy.row(iy1), ix); | 529 Sk4f pixelY1 = fStrategy.getPixelFromRow(fStrategy.row(iy1), ix); |
499 Sk4f filterPixel = pixelY0 * filterY0 + pixelY1 * filterY1; | 530 Sk4f filterPixel = pixelY0 * filterY0 + pixelY1 * filterY1; |
500 int count = span.count(); | 531 int count = span.count(); |
501 while (count >= 4) { | 532 while (count >= 4) { |
502 fNext->blend4Pixels(filterPixel, filterPixel, filterPixel, filterPix
el); | 533 fNext->blend4Pixels(filterPixel, filterPixel, filterPixel, filterPix
el); |
503 count -= 4; | 534 count -= 4; |
504 } | 535 } |
505 while (count > 0) { | 536 while (count > 0) { |
506 fNext->blendPixel(filterPixel); | 537 fNext->blendPixel(filterPixel); |
507 count -= 1; | 538 count -= 1; |
508 } | 539 } |
509 } | 540 } |
510 | 541 |
511 // When moving through source space more slowly than dst space (zoomed in), | 542 // When moving through source space more slowly than dst space (zoomed in), |
512 // we'll be sampling from the same source pixel more than once. | 543 // we'll be sampling from the same source pixel more than once. |
513 void bilerpSpanSlowRate(Span span, SkScalar ry1) { | 544 void spanSlowRate(Span span, SkScalar ry1) { |
514 SkPoint start; | 545 SkPoint start; |
515 SkScalar length; | 546 SkScalar length; |
516 int count; | 547 int count; |
517 std::tie(start, length, count) = span; | 548 std::tie(start, length, count) = span; |
518 SkFixed fx = SkScalarToFixed(X(start)-0.5f); | 549 SkFixed fx = SkScalarToFixed(X(start)-0.5f); |
519 | 550 |
520 SkFixed fdx = SkScalarToFixed(length / (count - 1)); | 551 SkFixed fdx = SkScalarToFixed(length / (count - 1)); |
521 | 552 |
522 Sk4f xAdjust; | 553 Sk4f xAdjust; |
523 if (fdx >= 0) { | 554 if (fdx >= 0) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 | 603 |
573 while (count > 0) { | 604 while (count > 0) { |
574 fNext->blendPixel(getNextPixel()); | 605 fNext->blendPixel(getNextPixel()); |
575 | 606 |
576 count -= 1; | 607 count -= 1; |
577 } | 608 } |
578 } | 609 } |
579 | 610 |
580 // We're moving through source space at a rate of 1 source pixel per 1 dst p
ixel. | 611 // We're moving through source space at a rate of 1 source pixel per 1 dst p
ixel. |
581 // We'll never re-use pixels, but we can at least load contiguous pixels. | 612 // We'll never re-use pixels, but we can at least load contiguous pixels. |
582 void bilerpSpanUnitRate(Span span, SkScalar y1) { | 613 void spanUnitRate(Span span, SkScalar y1) { |
583 y1 += 0.5f; | 614 y1 += 0.5f; |
584 SkScalar y0 = span.startY() - 0.5f; | 615 SkScalar y0 = span.startY() - 0.5f; |
585 int iy0 = SkScalarFloorToInt(y0); | 616 int iy0 = SkScalarFloorToInt(y0); |
586 SkScalar filterY1 = y0 - iy0; | 617 SkScalar filterY1 = y0 - iy0; |
587 SkScalar filterY0 = 1.0f - filterY1; | 618 SkScalar filterY0 = 1.0f - filterY1; |
588 int iy1 = SkScalarFloorToInt(y1); | 619 int iy1 = SkScalarFloorToInt(y1); |
589 const void* rowY0 = fStrategy.row(iy0); | 620 const void* rowY0 = fStrategy.row(iy0); |
590 const void* rowY1 = fStrategy.row(iy1); | 621 const void* rowY1 = fStrategy.row(iy1); |
591 SkScalar x0 = span.startX() - 0.5f; | 622 SkScalar x0 = span.startX() - 0.5f; |
592 int ix0 = SkScalarFloorToInt(x0); | 623 int ix0 = SkScalarFloorToInt(x0); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 Sk4f pixelY0 = fStrategy.getPixelFromRow(rowY0, ix0); | 708 Sk4f pixelY0 = fStrategy.getPixelFromRow(rowY0, ix0); |
678 Sk4f pixelY1 = fStrategy.getPixelFromRow(rowY1, ix0); | 709 Sk4f pixelY1 = fStrategy.getPixelFromRow(rowY1, ix0); |
679 | 710 |
680 fNext->blendPixel(lerp(pixelY0, pixelY1)); | 711 fNext->blendPixel(lerp(pixelY0, pixelY1)); |
681 ix0 -= 1; | 712 ix0 -= 1; |
682 count -= 1; | 713 count -= 1; |
683 } | 714 } |
684 } | 715 } |
685 } | 716 } |
686 | 717 |
687 void bilerpSpanUnitRateAlignedX(Span span, SkScalar y1) { | 718 void spanUnitRateAlignedX(Span span, SkScalar y1) { |
688 SkScalar y0 = span.startY() - 0.5f; | 719 SkScalar y0 = span.startY() - 0.5f; |
689 y1 += 0.5f; | 720 y1 += 0.5f; |
690 int iy0 = SkScalarFloorToInt(y0); | 721 int iy0 = SkScalarFloorToInt(y0); |
691 SkScalar filterY1 = y0 - iy0; | 722 SkScalar filterY1 = y0 - iy0; |
692 SkScalar filterY0 = 1.0f - filterY1; | 723 SkScalar filterY0 = 1.0f - filterY1; |
693 int iy1 = SkScalarFloorToInt(y1); | 724 int iy1 = SkScalarFloorToInt(y1); |
694 int ix = SkScalarFloorToInt(span.startX()); | 725 int ix = SkScalarFloorToInt(span.startX()); |
695 const void* rowY0 = fStrategy.row(iy0); | 726 const void* rowY0 = fStrategy.row(iy0); |
696 const void* rowY1 = fStrategy.row(iy1); | 727 const void* rowY1 = fStrategy.row(iy1); |
697 auto lerp = [&](Sk4f* pixelY0, Sk4f* pixelY1) { | 728 auto lerp = [&](Sk4f* pixelY0, Sk4f* pixelY1) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 | 767 |
737 fNext->blendPixel(lerp(&pixelY0, &pixelY1)); | 768 fNext->blendPixel(lerp(&pixelY0, &pixelY1)); |
738 ix -= 1; | 769 ix -= 1; |
739 count -= 1; | 770 count -= 1; |
740 } | 771 } |
741 } | 772 } |
742 } | 773 } |
743 | 774 |
744 // We're moving through source space faster than dst (zoomed out), | 775 // We're moving through source space faster than dst (zoomed out), |
745 // so we'll never reuse a source pixel or be able to do contiguous loads. | 776 // so we'll never reuse a source pixel or be able to do contiguous loads. |
746 void bilerpSpanFastRate(Span span, SkScalar y1) { | 777 void spanFastRate(Span span, SkScalar y1) { |
747 SkPoint start; | 778 SkPoint start; |
748 SkScalar length; | 779 SkScalar length; |
749 int count; | 780 int count; |
750 std::tie(start, length, count) = span; | 781 std::tie(start, length, count) = span; |
751 SkScalar x = X(start); | 782 SkScalar x = X(start); |
752 SkScalar y = Y(start); | 783 SkScalar y = Y(start); |
| 784 |
753 // In this sampler, it is assumed that if span.StartY() and y1 are the s
ame then both | 785 // In this sampler, it is assumed that if span.StartY() and y1 are the s
ame then both |
754 // y-lines are on the same tile. | 786 // y-lines are on the same tile. |
755 if (y == y1) { | 787 if (y == y1) { |
756 // Both y-lines are on the same tile. | 788 // Both y-lines are on the same tile. |
757 struct BilerpWrapper { | 789 span_fallback(span, this); |
758 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) { | |
759 fSampler.bilerpListFew(n, xs, ys); | |
760 } | |
761 | |
762 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) { | |
763 fSampler.bilerpList4(xs, ys); | |
764 } | |
765 | |
766 GeneralSampler& fSampler; | |
767 }; | |
768 BilerpWrapper wrapper{*this}; | |
769 span_fallback(span, &wrapper); | |
770 } else { | 790 } else { |
771 // The y-lines are on different tiles. | 791 // The y-lines are on different tiles. |
772 SkScalar dx = length / (count - 1); | 792 SkScalar dx = length / (count - 1); |
773 Sk4f ys = {y - 0.5f, y - 0.5f, y1 + 0.5f, y1 + 0.5f}; | 793 Sk4f ys = {y - 0.5f, y - 0.5f, y1 + 0.5f, y1 + 0.5f}; |
774 while (count > 0) { | 794 while (count > 0) { |
775 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; | 795 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; |
776 this->bilerpEdge(xs, ys); | 796 this->bilerpEdge(xs, ys); |
777 x += dx; | 797 x += dx; |
778 count -= 1; | 798 count -= 1; |
779 } | 799 } |
780 } | 800 } |
781 } | 801 } |
782 | 802 |
783 Next* const fNext; | 803 Next* const fNext; |
784 PixelAccessor<colorType, colorProfile> fStrategy; | 804 PixelAccessor<colorType, colorProfile> fStrategy; |
785 }; | 805 }; |
786 | 806 |
787 } // namespace | 807 } // namespace |
788 | 808 |
789 #endif // SkLinearBitmapPipeline_sampler_DEFINED | 809 #endif // SkLinearBitmapPipeline_sampler_DEFINED |
OLD | NEW |