| 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 |