| 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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 SkScalar x = X(start); | 169 SkScalar x = X(start); |
| 170 SkFixed fx = SkScalarToFixed(x); | 170 SkFixed fx = SkScalarToFixed(x); |
| 171 SkScalar dx = length / (count - 1); | 171 SkScalar dx = length / (count - 1); |
| 172 SkFixed fdx = SkScalarToFixed(dx); | 172 SkFixed fdx = SkScalarToFixed(dx); |
| 173 | 173 |
| 174 const void* row = fStrategy.row((int)std::floor(Y(start))); | 174 const void* row = fStrategy.row((int)std::floor(Y(start))); |
| 175 Next* next = fNext; | 175 Next* next = fNext; |
| 176 | 176 |
| 177 int ix = SkFixedFloorToInt(fx); | 177 int ix = SkFixedFloorToInt(fx); |
| 178 int prevIX = ix; | 178 int prevIX = ix; |
| 179 Sk4f fpixel = fStrategy.getPixelAt(row, ix); | 179 Sk4f fpixel = fStrategy.getPixelFromRow(row, ix); |
| 180 | 180 |
| 181 // When dx is less than one, each pixel is used more than once. Using th
e fixed point fx | 181 // When dx is less than one, each pixel is used more than once. Using th
e fixed point fx |
| 182 // allows the code to quickly check that the same pixel is being used. T
he code uses this | 182 // allows the code to quickly check that the same pixel is being used. T
he code uses this |
| 183 // same pixel check to do the sRGB and normalization only once. | 183 // same pixel check to do the sRGB and normalization only once. |
| 184 auto getNextPixel = [&]() { | 184 auto getNextPixel = [&]() { |
| 185 if (ix != prevIX) { | 185 if (ix != prevIX) { |
| 186 fpixel = fStrategy.getPixelAt(row, ix); | 186 fpixel = fStrategy.getPixelFromRow(row, ix); |
| 187 prevIX = ix; | 187 prevIX = ix; |
| 188 } | 188 } |
| 189 fx += fdx; | 189 fx += fdx; |
| 190 ix = SkFixedFloorToInt(fx); | 190 ix = SkFixedFloorToInt(fx); |
| 191 return fpixel; | 191 return fpixel; |
| 192 }; | 192 }; |
| 193 | 193 |
| 194 while (count >= 4) { | 194 while (count >= 4) { |
| 195 Sk4f px0 = getNextPixel(); | 195 Sk4f px0 = getNextPixel(); |
| 196 Sk4f px1 = getNextPixel(); | 196 Sk4f px1 = getNextPixel(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 218 if (length > 0) { | 218 if (length > 0) { |
| 219 while (count >= 4) { | 219 while (count >= 4) { |
| 220 Sk4f px0, px1, px2, px3; | 220 Sk4f px0, px1, px2, px3; |
| 221 fStrategy.get4Pixels(row, ix, &px0, &px1, &px2, &px3); | 221 fStrategy.get4Pixels(row, ix, &px0, &px1, &px2, &px3); |
| 222 next->blend4Pixels(px0, px1, px2, px3); | 222 next->blend4Pixels(px0, px1, px2, px3); |
| 223 ix += 4; | 223 ix += 4; |
| 224 count -= 4; | 224 count -= 4; |
| 225 } | 225 } |
| 226 | 226 |
| 227 while (count > 0) { | 227 while (count > 0) { |
| 228 next->blendPixel(fStrategy.getPixelAt(row, ix)); | 228 next->blendPixel(fStrategy.getPixelFromRow(row, ix)); |
| 229 ix += 1; | 229 ix += 1; |
| 230 count -= 1; | 230 count -= 1; |
| 231 } | 231 } |
| 232 } else { | 232 } else { |
| 233 while (count >= 4) { | 233 while (count >= 4) { |
| 234 Sk4f px0, px1, px2, px3; | 234 Sk4f px0, px1, px2, px3; |
| 235 fStrategy.get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0); | 235 fStrategy.get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0); |
| 236 next->blend4Pixels(px0, px1, px2, px3); | 236 next->blend4Pixels(px0, px1, px2, px3); |
| 237 ix -= 4; | 237 ix -= 4; |
| 238 count -= 4; | 238 count -= 4; |
| 239 } | 239 } |
| 240 | 240 |
| 241 while (count > 0) { | 241 while (count > 0) { |
| 242 next->blendPixel(fStrategy.getPixelAt(row, ix)); | 242 next->blendPixel(fStrategy.getPixelFromRow(row, ix)); |
| 243 ix -= 1; | 243 ix -= 1; |
| 244 count -= 1; | 244 count -= 1; |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 } | 247 } |
| 248 | 248 |
| 249 // We're moving through source space faster than dst (zoomed out), | 249 // We're moving through source space faster than dst (zoomed out), |
| 250 // so we'll never reuse a source pixel or be able to do contiguous loads. | 250 // so we'll never reuse a source pixel or be able to do contiguous loads. |
| 251 void nearestSpanFastRate(Span span) { | 251 void nearestSpanFastRate(Span span) { |
| 252 struct NearestWrapper { | 252 struct NearestWrapper { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 265 } | 265 } |
| 266 | 266 |
| 267 void bilerpSpanZeroRate(Span span, SkScalar y1) { | 267 void bilerpSpanZeroRate(Span span, SkScalar y1) { |
| 268 SkScalar y0 = span.startY() - 0.5f; | 268 SkScalar y0 = span.startY() - 0.5f; |
| 269 y1 += 0.5f; | 269 y1 += 0.5f; |
| 270 int iy0 = SkScalarFloorToInt(y0); | 270 int iy0 = SkScalarFloorToInt(y0); |
| 271 SkScalar filterY1 = y0 - iy0; | 271 SkScalar filterY1 = y0 - iy0; |
| 272 SkScalar filterY0 = 1.0f - filterY1; | 272 SkScalar filterY0 = 1.0f - filterY1; |
| 273 int iy1 = SkScalarFloorToInt(y1); | 273 int iy1 = SkScalarFloorToInt(y1); |
| 274 int ix = SkScalarFloorToInt(span.startX()); | 274 int ix = SkScalarFloorToInt(span.startX()); |
| 275 Sk4f pixelY0 = fStrategy.getPixelAt(fStrategy.row(iy0), ix); | 275 Sk4f pixelY0 = fStrategy.getPixelFromRow(fStrategy.row(iy0), ix); |
| 276 Sk4f pixelY1 = fStrategy.getPixelAt(fStrategy.row(iy1), ix); | 276 Sk4f pixelY1 = fStrategy.getPixelFromRow(fStrategy.row(iy1), ix); |
| 277 Sk4f filterPixel = pixelY0 * filterY0 + pixelY1 * filterY1; | 277 Sk4f filterPixel = pixelY0 * filterY0 + pixelY1 * filterY1; |
| 278 int count = span.count(); | 278 int count = span.count(); |
| 279 while (count >= 4) { | 279 while (count >= 4) { |
| 280 fNext->blend4Pixels(filterPixel, filterPixel, filterPixel, filterPix
el); | 280 fNext->blend4Pixels(filterPixel, filterPixel, filterPixel, filterPix
el); |
| 281 count -= 4; | 281 count -= 4; |
| 282 } | 282 } |
| 283 while (count > 0) { | 283 while (count > 0) { |
| 284 fNext->blendPixel(filterPixel); | 284 fNext->blendPixel(filterPixel); |
| 285 count -= 1; | 285 count -= 1; |
| 286 } | 286 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 309 int ioldx = ix; | 309 int ioldx = ix; |
| 310 Sk4f x{SkFixedToScalar(fx) - ix}; | 310 Sk4f x{SkFixedToScalar(fx) - ix}; |
| 311 Sk4f dx{SkFixedToScalar(fdx)}; | 311 Sk4f dx{SkFixedToScalar(fdx)}; |
| 312 SkScalar ry0 = Y(start) - 0.5f; | 312 SkScalar ry0 = Y(start) - 0.5f; |
| 313 ry1 += 0.5f; | 313 ry1 += 0.5f; |
| 314 SkScalar yFloor = std::floor(ry0); | 314 SkScalar yFloor = std::floor(ry0); |
| 315 Sk4f y1 = Sk4f{ry0 - yFloor}; | 315 Sk4f y1 = Sk4f{ry0 - yFloor}; |
| 316 Sk4f y0 = Sk4f{1.0f} - y1; | 316 Sk4f y0 = Sk4f{1.0f} - y1; |
| 317 const void* const row0 = fStrategy.row(SkScalarFloorToInt(ry0)); | 317 const void* const row0 = fStrategy.row(SkScalarFloorToInt(ry0)); |
| 318 const void* const row1 = fStrategy.row(SkScalarFloorToInt(ry1)); | 318 const void* const row1 = fStrategy.row(SkScalarFloorToInt(ry1)); |
| 319 Sk4f fpixel00 = y0 * fStrategy.getPixelAt(row0, ix); | 319 Sk4f fpixel00 = y0 * fStrategy.getPixelFromRow(row0, ix); |
| 320 Sk4f fpixel01 = y1 * fStrategy.getPixelAt(row1, ix); | 320 Sk4f fpixel01 = y1 * fStrategy.getPixelFromRow(row1, ix); |
| 321 Sk4f fpixel10 = y0 * fStrategy.getPixelAt(row0, ix + 1); | 321 Sk4f fpixel10 = y0 * fStrategy.getPixelFromRow(row0, ix + 1); |
| 322 Sk4f fpixel11 = y1 * fStrategy.getPixelAt(row1, ix + 1); | 322 Sk4f fpixel11 = y1 * fStrategy.getPixelFromRow(row1, ix + 1); |
| 323 auto getNextPixel = [&]() { | 323 auto getNextPixel = [&]() { |
| 324 if (ix != ioldx) { | 324 if (ix != ioldx) { |
| 325 fpixel00 = fpixel10; | 325 fpixel00 = fpixel10; |
| 326 fpixel01 = fpixel11; | 326 fpixel01 = fpixel11; |
| 327 fpixel10 = y0 * fStrategy.getPixelAt(row0, ix + 1); | 327 fpixel10 = y0 * fStrategy.getPixelFromRow(row0, ix + 1); |
| 328 fpixel11 = y1 * fStrategy.getPixelAt(row1, ix + 1); | 328 fpixel11 = y1 * fStrategy.getPixelFromRow(row1, ix + 1); |
| 329 ioldx = ix; | 329 ioldx = ix; |
| 330 x = x + xAdjust; | 330 x = x + xAdjust; |
| 331 } | 331 } |
| 332 | 332 |
| 333 Sk4f x0, x1; | 333 Sk4f x0, x1; |
| 334 x0 = Sk4f{1.0f} - x; | 334 x0 = Sk4f{1.0f} - x; |
| 335 x1 = x; | 335 x1 = x; |
| 336 Sk4f fpixel = x0 * (fpixel00 + fpixel01) + x1 * (fpixel10 + fpixel11
); | 336 Sk4f fpixel = x0 * (fpixel00 + fpixel01) + x1 * (fpixel10 + fpixel11
); |
| 337 fx += fdx; | 337 fx += fdx; |
| 338 ix = SkFixedFloorToInt(fx); | 338 ix = SkFixedFloorToInt(fx); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 367 SkScalar filterY0 = 1.0f - filterY1; | 367 SkScalar filterY0 = 1.0f - filterY1; |
| 368 int iy1 = SkScalarFloorToInt(y1); | 368 int iy1 = SkScalarFloorToInt(y1); |
| 369 const void* rowY0 = fStrategy.row(iy0); | 369 const void* rowY0 = fStrategy.row(iy0); |
| 370 const void* rowY1 = fStrategy.row(iy1); | 370 const void* rowY1 = fStrategy.row(iy1); |
| 371 SkScalar x0 = span.startX() - 0.5f; | 371 SkScalar x0 = span.startX() - 0.5f; |
| 372 int ix0 = SkScalarFloorToInt(x0); | 372 int ix0 = SkScalarFloorToInt(x0); |
| 373 SkScalar filterX1 = x0 - ix0; | 373 SkScalar filterX1 = x0 - ix0; |
| 374 SkScalar filterX0 = 1.0f - filterX1; | 374 SkScalar filterX0 = 1.0f - filterX1; |
| 375 | 375 |
| 376 auto getPixelY0 = [&]() { | 376 auto getPixelY0 = [&]() { |
| 377 Sk4f px = fStrategy.getPixelAt(rowY0, ix0); | 377 Sk4f px = fStrategy.getPixelFromRow(rowY0, ix0); |
| 378 return px * filterY0; | 378 return px * filterY0; |
| 379 }; | 379 }; |
| 380 | 380 |
| 381 auto getPixelY1 = [&]() { | 381 auto getPixelY1 = [&]() { |
| 382 Sk4f px = fStrategy.getPixelAt(rowY1, ix0); | 382 Sk4f px = fStrategy.getPixelFromRow(rowY1, ix0); |
| 383 return px * filterY1; | 383 return px * filterY1; |
| 384 }; | 384 }; |
| 385 | 385 |
| 386 auto get4PixelsY0 = [&](int ix, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* p
x3) { | 386 auto get4PixelsY0 = [&](int ix, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* p
x3) { |
| 387 fStrategy.get4Pixels(rowY0, ix, px0, px1, px2, px3); | 387 fStrategy.get4Pixels(rowY0, ix, px0, px1, px2, px3); |
| 388 *px0 = *px0 * filterY0; | 388 *px0 = *px0 * filterY0; |
| 389 *px1 = *px1 * filterY0; | 389 *px1 = *px1 * filterY0; |
| 390 *px2 = *px2 * filterY0; | 390 *px2 = *px2 * filterY0; |
| 391 *px3 = *px3 * filterY0; | 391 *px3 = *px3 * filterY0; |
| 392 }; | 392 }; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 419 Sk4f pxS2 = px20 + px21; | 419 Sk4f pxS2 = px20 + px21; |
| 420 Sk4f px2 = lerp(pxS1, pxS2); | 420 Sk4f px2 = lerp(pxS1, pxS2); |
| 421 Sk4f pxS3 = px30 + px31; | 421 Sk4f pxS3 = px30 + px31; |
| 422 Sk4f px3 = lerp(pxS2, pxS3); | 422 Sk4f px3 = lerp(pxS2, pxS3); |
| 423 pxB = pxS3; | 423 pxB = pxS3; |
| 424 fNext->blend4Pixels(px0, px1, px2, px3); | 424 fNext->blend4Pixels(px0, px1, px2, px3); |
| 425 ix0 += 4; | 425 ix0 += 4; |
| 426 count -= 4; | 426 count -= 4; |
| 427 } | 427 } |
| 428 while (count > 0) { | 428 while (count > 0) { |
| 429 Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix0); | 429 Sk4f pixelY0 = fStrategy.getPixelFromRow(rowY0, ix0); |
| 430 Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix0); | 430 Sk4f pixelY1 = fStrategy.getPixelFromRow(rowY1, ix0); |
| 431 | 431 |
| 432 fNext->blendPixel(lerp(pixelY0, pixelY1)); | 432 fNext->blendPixel(lerp(pixelY0, pixelY1)); |
| 433 ix0 += 1; | 433 ix0 += 1; |
| 434 count -= 1; | 434 count -= 1; |
| 435 } | 435 } |
| 436 } else { | 436 } else { |
| 437 int count = span.count(); | 437 int count = span.count(); |
| 438 while (count >= 4) { | 438 while (count >= 4) { |
| 439 Sk4f px00, px10, px20, px30; | 439 Sk4f px00, px10, px20, px30; |
| 440 get4PixelsY0(ix0 - 3, &px00, &px10, &px20, &px30); | 440 get4PixelsY0(ix0 - 3, &px00, &px10, &px20, &px30); |
| 441 Sk4f px01, px11, px21, px31; | 441 Sk4f px01, px11, px21, px31; |
| 442 get4PixelsY1(ix0 - 3, &px01, &px11, &px21, &px31); | 442 get4PixelsY1(ix0 - 3, &px01, &px11, &px21, &px31); |
| 443 Sk4f pxS3 = px30 + px31; | 443 Sk4f pxS3 = px30 + px31; |
| 444 Sk4f px0 = lerp(pxS3, pxB); | 444 Sk4f px0 = lerp(pxS3, pxB); |
| 445 Sk4f pxS2 = px20 + px21; | 445 Sk4f pxS2 = px20 + px21; |
| 446 Sk4f px1 = lerp(pxS2, pxS3); | 446 Sk4f px1 = lerp(pxS2, pxS3); |
| 447 Sk4f pxS1 = px10 + px11; | 447 Sk4f pxS1 = px10 + px11; |
| 448 Sk4f px2 = lerp(pxS1, pxS2); | 448 Sk4f px2 = lerp(pxS1, pxS2); |
| 449 Sk4f pxS0 = px00 + px01; | 449 Sk4f pxS0 = px00 + px01; |
| 450 Sk4f px3 = lerp(pxS0, pxS1); | 450 Sk4f px3 = lerp(pxS0, pxS1); |
| 451 pxB = pxS0; | 451 pxB = pxS0; |
| 452 fNext->blend4Pixels(px0, px1, px2, px3); | 452 fNext->blend4Pixels(px0, px1, px2, px3); |
| 453 ix0 -= 4; | 453 ix0 -= 4; |
| 454 count -= 4; | 454 count -= 4; |
| 455 } | 455 } |
| 456 while (count > 0) { | 456 while (count > 0) { |
| 457 Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix0); | 457 Sk4f pixelY0 = fStrategy.getPixelFromRow(rowY0, ix0); |
| 458 Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix0); | 458 Sk4f pixelY1 = fStrategy.getPixelFromRow(rowY1, ix0); |
| 459 | 459 |
| 460 fNext->blendPixel(lerp(pixelY0, pixelY1)); | 460 fNext->blendPixel(lerp(pixelY0, pixelY1)); |
| 461 ix0 -= 1; | 461 ix0 -= 1; |
| 462 count -= 1; | 462 count -= 1; |
| 463 } | 463 } |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 void bilerpSpanUnitRateAlignedX(Span span, SkScalar y1) { | 467 void bilerpSpanUnitRateAlignedX(Span span, SkScalar y1) { |
| 468 SkScalar y0 = span.startY() - 0.5f; | 468 SkScalar y0 = span.startY() - 0.5f; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 484 Sk4f px00, px10, px20, px30; | 484 Sk4f px00, px10, px20, px30; |
| 485 fStrategy.get4Pixels(rowY0, ix, &px00, &px10, &px20, &px30); | 485 fStrategy.get4Pixels(rowY0, ix, &px00, &px10, &px20, &px30); |
| 486 Sk4f px01, px11, px21, px31; | 486 Sk4f px01, px11, px21, px31; |
| 487 fStrategy.get4Pixels(rowY1, ix, &px01, &px11, &px21, &px31); | 487 fStrategy.get4Pixels(rowY1, ix, &px01, &px11, &px21, &px31); |
| 488 fNext->blend4Pixels( | 488 fNext->blend4Pixels( |
| 489 lerp(&px00, &px01), lerp(&px10, &px11), lerp(&px20, &px21),
lerp(&px30, &px31)); | 489 lerp(&px00, &px01), lerp(&px10, &px11), lerp(&px20, &px21),
lerp(&px30, &px31)); |
| 490 ix += 4; | 490 ix += 4; |
| 491 count -= 4; | 491 count -= 4; |
| 492 } | 492 } |
| 493 while (count > 0) { | 493 while (count > 0) { |
| 494 Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix); | 494 Sk4f pixelY0 = fStrategy.getPixelFromRow(rowY0, ix); |
| 495 Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix); | 495 Sk4f pixelY1 = fStrategy.getPixelFromRow(rowY1, ix); |
| 496 | 496 |
| 497 fNext->blendPixel(lerp(&pixelY0, &pixelY1)); | 497 fNext->blendPixel(lerp(&pixelY0, &pixelY1)); |
| 498 ix += 1; | 498 ix += 1; |
| 499 count -= 1; | 499 count -= 1; |
| 500 } | 500 } |
| 501 } else { | 501 } else { |
| 502 int count = span.count(); | 502 int count = span.count(); |
| 503 while (count >= 4) { | 503 while (count >= 4) { |
| 504 Sk4f px00, px10, px20, px30; | 504 Sk4f px00, px10, px20, px30; |
| 505 fStrategy.get4Pixels(rowY0, ix - 3, &px30, &px20, &px10, &px00); | 505 fStrategy.get4Pixels(rowY0, ix - 3, &px30, &px20, &px10, &px00); |
| 506 Sk4f px01, px11, px21, px31; | 506 Sk4f px01, px11, px21, px31; |
| 507 fStrategy.get4Pixels(rowY1, ix - 3, &px31, &px21, &px11, &px01); | 507 fStrategy.get4Pixels(rowY1, ix - 3, &px31, &px21, &px11, &px01); |
| 508 fNext->blend4Pixels( | 508 fNext->blend4Pixels( |
| 509 lerp(&px00, &px01), lerp(&px10, &px11), lerp(&px20, &px21),
lerp(&px30, &px31)); | 509 lerp(&px00, &px01), lerp(&px10, &px11), lerp(&px20, &px21),
lerp(&px30, &px31)); |
| 510 ix -= 4; | 510 ix -= 4; |
| 511 count -= 4; | 511 count -= 4; |
| 512 } | 512 } |
| 513 while (count > 0) { | 513 while (count > 0) { |
| 514 Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix); | 514 Sk4f pixelY0 = fStrategy.getPixelFromRow(rowY0, ix); |
| 515 Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix); | 515 Sk4f pixelY1 = fStrategy.getPixelFromRow(rowY1, ix); |
| 516 | 516 |
| 517 fNext->blendPixel(lerp(&pixelY0, &pixelY1)); | 517 fNext->blendPixel(lerp(&pixelY0, &pixelY1)); |
| 518 ix -= 1; | 518 ix -= 1; |
| 519 count -= 1; | 519 count -= 1; |
| 520 } | 520 } |
| 521 } | 521 } |
| 522 } | 522 } |
| 523 | 523 |
| 524 // We're moving through source space faster than dst (zoomed out), | 524 // We're moving through source space faster than dst (zoomed out), |
| 525 // so we'll never reuse a source pixel or be able to do contiguous loads. | 525 // so we'll never reuse a source pixel or be able to do contiguous loads. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 }; | 561 }; |
| 562 | 562 |
| 563 class sRGBFast { | 563 class sRGBFast { |
| 564 public: | 564 public: |
| 565 static Sk4s VECTORCALL sRGBToLinear(Sk4s pixel) { | 565 static Sk4s VECTORCALL sRGBToLinear(Sk4s pixel) { |
| 566 Sk4s l = pixel * pixel; | 566 Sk4s l = pixel * pixel; |
| 567 return Sk4s{l[0], l[1], l[2], pixel[3]}; | 567 return Sk4s{l[0], l[1], l[2], pixel[3]}; |
| 568 } | 568 } |
| 569 }; | 569 }; |
| 570 | 570 |
| 571 enum class ColorOrder { | 571 template <typename PixelGetter> |
| 572 kRGBA = false, | 572 class PixelAccessor { |
| 573 kBGRA = true, | |
| 574 }; | |
| 575 template <SkColorProfileType colorProfile, ColorOrder colorOrder> | |
| 576 class Pixel8888 { | |
| 577 public: | 573 public: |
| 578 Pixel8888(int width, const uint32_t* src) : fSrc{src}, fWidth{width}{ } | 574 PixelAccessor(const SkPixmap& srcPixmap) |
| 579 Pixel8888(const SkPixmap& srcPixmap) | 575 : fWidth{srcPixmap.rowBytesAsPixels()} |
| 580 : fSrc{srcPixmap.addr32()} | 576 , fGetter{srcPixmap} { } |
| 581 , fWidth{static_cast<int>(srcPixmap.rowBytes() / 4)} { } | |
| 582 | 577 |
| 583 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { | 578 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { |
| 584 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | 579 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
| 585 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | 580 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
| 586 Sk4i bufferLoc = YIs * fWidth + XIs; | 581 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 587 switch (n) { | 582 switch (n) { |
| 588 case 3: | 583 case 3: |
| 589 *px2 = this->getPixelAt(fSrc, bufferLoc[2]); | 584 *px2 = fGetter.getPixelAt(bufferLoc[2]); |
| 590 case 2: | 585 case 2: |
| 591 *px1 = this->getPixelAt(fSrc, bufferLoc[1]); | 586 *px1 = fGetter.getPixelAt(bufferLoc[1]); |
| 592 case 1: | 587 case 1: |
| 593 *px0 = this->getPixelAt(fSrc, bufferLoc[0]); | 588 *px0 = fGetter.getPixelAt(bufferLoc[0]); |
| 594 default: | 589 default: |
| 595 break; | 590 break; |
| 596 } | 591 } |
| 597 } | 592 } |
| 598 | 593 |
| 599 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | 594 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { |
| 600 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | 595 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
| 601 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | 596 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
| 602 Sk4i bufferLoc = YIs * fWidth + XIs; | 597 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 603 *px0 = this->getPixelAt(fSrc, bufferLoc[0]); | 598 *px0 = fGetter.getPixelAt(bufferLoc[0]); |
| 604 *px1 = this->getPixelAt(fSrc, bufferLoc[1]); | 599 *px1 = fGetter.getPixelAt(bufferLoc[1]); |
| 605 *px2 = this->getPixelAt(fSrc, bufferLoc[2]); | 600 *px2 = fGetter.getPixelAt(bufferLoc[2]); |
| 606 *px3 = this->getPixelAt(fSrc, bufferLoc[3]); | 601 *px3 = fGetter.getPixelAt(bufferLoc[3]); |
| 607 } | 602 } |
| 608 | 603 |
| 609 void get4Pixels(const void* vsrc, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | 604 void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2,
Sk4f* px3) { |
| 610 const uint32_t* src = static_cast<const uint32_t*>(vsrc); | 605 *px0 = fGetter.getPixelFromRow(src, index + 0); |
| 611 *px0 = this->getPixelAt(src, index + 0); | 606 *px1 = fGetter.getPixelFromRow(src, index + 1); |
| 612 *px1 = this->getPixelAt(src, index + 1); | 607 *px2 = fGetter.getPixelFromRow(src, index + 2); |
| 613 *px2 = this->getPixelAt(src, index + 2); | 608 *px3 = fGetter.getPixelFromRow(src, index + 3); |
| 614 *px3 = this->getPixelAt(src, index + 3); | |
| 615 } | 609 } |
| 616 | 610 |
| 617 Sk4f getPixelAt(const void* vsrc, int index) { | 611 Sk4f getPixelFromRow(const void* row, int index) { |
| 618 const uint32_t* src = static_cast<const uint32_t*>(vsrc); | 612 return fGetter.getPixelFromRow(row, index); |
| 613 } |
| 614 |
| 615 const void* row(int y) { return fGetter.row(y); } |
| 616 |
| 617 private: |
| 618 const Sk4i fWidth; |
| 619 PixelGetter fGetter; |
| 620 }; |
| 621 |
| 622 template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGet
ter; |
| 623 |
| 624 template <SkColorProfileType colorProfile> |
| 625 class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { |
| 626 public: |
| 627 PixelGetter(const SkPixmap& srcPixmap) |
| 628 : fSrc{srcPixmap.addr32()} |
| 629 , fWidth{srcPixmap.rowBytesAsPixels()} { } |
| 630 |
| 631 Sk4f getPixelFromRow(const void* row, int index) { |
| 632 const uint32_t* src = static_cast<const uint32_t*>(row); |
| 619 Sk4b bytePixel = Sk4b::Load((uint8_t *)(&src[index])); | 633 Sk4b bytePixel = Sk4b::Load((uint8_t *)(&src[index])); |
| 620 Sk4f pixel = SkNx_cast<float, uint8_t>(bytePixel); | 634 Sk4f pixel = SkNx_cast<float, uint8_t>(bytePixel); |
| 621 if (colorOrder == ColorOrder::kBGRA) { | 635 pixel = pixel * (1.0f/255.0f); |
| 622 pixel = SkNx_shuffle<2, 1, 0, 3>(pixel); | |
| 623 } | |
| 624 pixel = pixel * Sk4f{1.0f/255.0f}; | |
| 625 if (colorProfile == kSRGB_SkColorProfileType) { | 636 if (colorProfile == kSRGB_SkColorProfileType) { |
| 626 pixel = sRGBFast::sRGBToLinear(pixel); | 637 pixel = sRGBFast::sRGBToLinear(pixel); |
| 627 } | 638 } |
| 628 return pixel; | 639 return pixel; |
| 629 } | 640 } |
| 630 | 641 |
| 631 const void* row(int y) { return fSrc + y * fWidth[0]; } | 642 Sk4f getPixelAt(int index) { |
| 643 return this->getPixelFromRow(fSrc, index); |
| 644 } |
| 645 |
| 646 const void* row(int y) { return fSrc + y * fWidth; } |
| 632 | 647 |
| 633 private: | 648 private: |
| 634 const uint32_t* const fSrc; | 649 const uint32_t* const fSrc; |
| 635 const Sk4i fWidth; | 650 const int fWidth; |
| 636 }; | 651 }; |
| 637 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>; | 652 |
| 638 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>; | 653 using Pixel8888SRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kSRGB_Sk
ColorProfileType>>; |
| 639 using Pixel8888SBGR = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kBGRA>; | 654 using Pixel8888LRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kLinear_
SkColorProfileType>>; |
| 640 using Pixel8888LBGR = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kBGRA>; | |
| 641 | 655 |
| 642 template <SkColorProfileType colorProfile> | 656 template <SkColorProfileType colorProfile> |
| 643 class PixelIndex8 { | 657 class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { |
| 644 public: | 658 public: |
| 645 PixelIndex8(const SkPixmap& srcPixmap) | 659 PixelGetter(const SkPixmap& srcPixmap) |
| 660 : fSrc{srcPixmap.addr32()} |
| 661 , fWidth{srcPixmap.rowBytesAsPixels()} { } |
| 662 |
| 663 Sk4f getPixelFromRow(const void* row, int index) { |
| 664 const uint32_t* src = static_cast<const uint32_t*>(row); |
| 665 Sk4b bytePixel = Sk4b::Load((uint8_t *)(&src[index])); |
| 666 Sk4f pixel = SkNx_cast<float, uint8_t>(bytePixel); |
| 667 pixel = SkNx_shuffle<2, 1, 0, 3>(pixel); |
| 668 pixel = pixel * (1.0f/255.0f); |
| 669 if (colorProfile == kSRGB_SkColorProfileType) { |
| 670 pixel = sRGBFast::sRGBToLinear(pixel); |
| 671 } |
| 672 return pixel; |
| 673 } |
| 674 |
| 675 Sk4f getPixelAt(int index) { |
| 676 return this->getPixelFromRow(fSrc, index); |
| 677 } |
| 678 |
| 679 const void* row(int y) { return fSrc + y * fWidth; } |
| 680 |
| 681 private: |
| 682 const uint32_t* const fSrc; |
| 683 const int fWidth; |
| 684 }; |
| 685 |
| 686 using Pixel8888SBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kSRGB_Sk
ColorProfileType>>; |
| 687 using Pixel8888LBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kLinear_
SkColorProfileType>>; |
| 688 |
| 689 template <SkColorProfileType colorProfile> |
| 690 class PixelGetter<kIndex_8_SkColorType, colorProfile> { |
| 691 public: |
| 692 PixelGetter(const SkPixmap& srcPixmap) |
| 646 : fSrc{srcPixmap.addr8()}, fWidth{static_cast<int>(srcPixmap.rowBytes())
} { | 693 : fSrc{srcPixmap.addr8()}, fWidth{static_cast<int>(srcPixmap.rowBytes())
} { |
| 647 SkASSERT(srcPixmap.colorType() == kIndex_8_SkColorType); | 694 SkASSERT(srcPixmap.colorType() == kIndex_8_SkColorType); |
| 648 SkColorTable* skColorTable = srcPixmap.ctable(); | 695 SkColorTable* skColorTable = srcPixmap.ctable(); |
| 649 SkASSERT(skColorTable != nullptr); | 696 SkASSERT(skColorTable != nullptr); |
| 650 | 697 |
| 651 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | 698 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
| 652 for (int i = 0; i < skColorTable->count(); i++) { | 699 for (int i = 0; i < skColorTable->count(); i++) { |
| 653 fColorTable[i] = this->convertPixel((*skColorTable)[i]); | 700 fColorTable[i] = this->convertPixel((*skColorTable)[i]); |
| 654 } | 701 } |
| 655 } | 702 } |
| 656 | 703 |
| 657 PixelIndex8(const PixelIndex8& strategy) | 704 PixelGetter(const PixelGetter& strategy) |
| 658 : fSrc{strategy.fSrc}, fWidth{strategy.fWidth} { | 705 : fSrc{strategy.fSrc}, fWidth{strategy.fWidth} { |
| 659 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | 706 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
| 660 // TODO: figure out the count. | 707 // TODO: figure out the count. |
| 661 for (int i = 0; i < 256; i++) { | 708 for (int i = 0; i < 256; i++) { |
| 662 fColorTable[i] = strategy.fColorTable[i]; | 709 fColorTable[i] = strategy.fColorTable[i]; |
| 663 } | 710 } |
| 664 } | 711 } |
| 665 | 712 |
| 666 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { | 713 Sk4f getPixelFromRow(const void* row, int index) { |
| 667 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | 714 const uint8_t* src = static_cast<const uint8_t*>(row); |
| 668 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
| 669 Sk4i bufferLoc = YIs * fWidth + XIs; | |
| 670 switch (n) { | |
| 671 case 3: | |
| 672 *px2 = this->getPixelAt(fSrc, bufferLoc[2]); | |
| 673 case 2: | |
| 674 *px1 = this->getPixelAt(fSrc, bufferLoc[1]); | |
| 675 case 1: | |
| 676 *px0 = this->getPixelAt(fSrc, bufferLoc[0]); | |
| 677 default: | |
| 678 break; | |
| 679 } | |
| 680 } | |
| 681 | |
| 682 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | |
| 683 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | |
| 684 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
| 685 Sk4i bufferLoc = YIs * fWidth + XIs; | |
| 686 *px0 = this->getPixelAt(fSrc, bufferLoc[0]); | |
| 687 *px1 = this->getPixelAt(fSrc, bufferLoc[1]); | |
| 688 *px2 = this->getPixelAt(fSrc, bufferLoc[2]); | |
| 689 *px3 = this->getPixelAt(fSrc, bufferLoc[3]); | |
| 690 } | |
| 691 | |
| 692 void get4Pixels(const void* vsrc, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | |
| 693 *px0 = this->getPixelAt(vsrc, index + 0); | |
| 694 *px1 = this->getPixelAt(vsrc, index + 1); | |
| 695 *px2 = this->getPixelAt(vsrc, index + 2); | |
| 696 *px3 = this->getPixelAt(vsrc, index + 3); | |
| 697 } | |
| 698 | |
| 699 Sk4f getPixelAt(const void* vsrc, int index) { | |
| 700 const uint8_t* src = static_cast<const uint8_t*>(vsrc); | |
| 701 return getPixel(src + index); | |
| 702 } | |
| 703 | |
| 704 Sk4f getPixel(const uint8_t* src) { | |
| 705 Sk4f pixel = fColorTable[*src]; | 715 Sk4f pixel = fColorTable[*src]; |
| 706 return pixel; | 716 return pixel; |
| 707 } | 717 } |
| 708 | 718 |
| 709 const void* row(int y) { return fSrc + y * fWidth[0]; } | 719 Sk4f getPixelAt(int index) { |
| 720 return this->getPixelFromRow(fSrc, index); |
| 721 } |
| 722 |
| 723 const void* row(int y) { return fSrc + y * fWidth; } |
| 710 | 724 |
| 711 private: | 725 private: |
| 712 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; | 726 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; |
| 713 Sk4f convertPixel(SkPMColor pmColor) { | 727 Sk4f convertPixel(SkPMColor pmColor) { |
| 714 Sk4b bPixel = Sk4b::Load(&pmColor); | 728 Sk4b bPixel = Sk4b::Load(&pmColor); |
| 715 Sk4f pixel = SkNx_cast<float, uint8_t>(bPixel); | 729 Sk4f pixel = SkNx_cast<float, uint8_t>(bPixel); |
| 716 float alpha = pixel[3]; | 730 float alpha = pixel[3]; |
| 717 if (alpha != 0.0f) { | 731 if (alpha != 0.0f) { |
| 718 float invAlpha = 1.0f / pixel[3]; | 732 float invAlpha = 1.0f / pixel[3]; |
| 719 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; | 733 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; |
| 720 pixel = pixel * normalize; | 734 pixel = pixel * normalize; |
| 721 if (colorProfile == kSRGB_SkColorProfileType) { | 735 if (colorProfile == kSRGB_SkColorProfileType) { |
| 722 pixel = sRGBFast::sRGBToLinear(pixel); | 736 pixel = sRGBFast::sRGBToLinear(pixel); |
| 723 } | 737 } |
| 724 return pixel; | 738 return pixel; |
| 725 } else { | 739 } else { |
| 726 return Sk4f{0.0f}; | 740 return Sk4f{0.0f}; |
| 727 } | 741 } |
| 728 } | 742 } |
| 729 const uint8_t* const fSrc; | 743 const uint8_t* const fSrc; |
| 730 const Sk4i fWidth; | 744 const int fWidth; |
| 731 SkAutoMalloc fColorTableStorage{kColorTableSize}; | 745 SkAutoMalloc fColorTableStorage{kColorTableSize}; |
| 732 Sk4f* fColorTable; | 746 Sk4f* fColorTable; |
| 733 }; | 747 }; |
| 734 | 748 |
| 735 using PixelIndex8SRGB = PixelIndex8<kSRGB_SkColorProfileType>; | 749 using PixelIndex8SRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kSRGB_Sk
ColorProfileType>>; |
| 736 using PixelIndex8LRGB = PixelIndex8<kLinear_SkColorProfileType>; | 750 using PixelIndex8LRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kLinear_
SkColorProfileType>>; |
| 737 | 751 |
| 738 class PixelHalfLinear { | 752 template <> |
| 753 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { |
| 739 public: | 754 public: |
| 740 PixelHalfLinear(int width, const uint64_t* src) : fSrc{src}, fWidth{width}{
} | 755 PixelGetter(const SkPixmap& srcPixmap) |
| 741 PixelHalfLinear(const SkPixmap& srcPixmap) | |
| 742 : fSrc{srcPixmap.addr64()} | 756 : fSrc{srcPixmap.addr64()} |
| 743 , fWidth{static_cast<int>(srcPixmap.rowBytes() / 8)} { } | 757 , fWidth{static_cast<int>(srcPixmap.rowBytesAsPixels())} { } |
| 744 | 758 |
| 745 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { | 759 Sk4f getPixelFromRow(const void* row, int index) { |
| 746 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | 760 const uint64_t* src = static_cast<const uint64_t*>(row) + index; |
| 747 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
| 748 Sk4i bufferLoc = YIs * fWidth + XIs; | |
| 749 switch (n) { | |
| 750 case 3: | |
| 751 *px2 = this->getPixelAt(fSrc, bufferLoc[2]); | |
| 752 case 2: | |
| 753 *px1 = this->getPixelAt(fSrc, bufferLoc[1]); | |
| 754 case 1: | |
| 755 *px0 = this->getPixelAt(fSrc, bufferLoc[0]); | |
| 756 default: | |
| 757 break; | |
| 758 } | |
| 759 } | |
| 760 | |
| 761 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | |
| 762 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | |
| 763 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
| 764 Sk4i bufferLoc = YIs * fWidth + XIs; | |
| 765 *px0 = this->getPixelAt(fSrc, bufferLoc[0]); | |
| 766 *px1 = this->getPixelAt(fSrc, bufferLoc[1]); | |
| 767 *px2 = this->getPixelAt(fSrc, bufferLoc[2]); | |
| 768 *px3 = this->getPixelAt(fSrc, bufferLoc[3]); | |
| 769 } | |
| 770 | |
| 771 void get4Pixels(const void* vsrc, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | |
| 772 const uint32_t* src = static_cast<const uint32_t*>(vsrc); | |
| 773 *px0 = this->getPixelAt(src, index + 0); | |
| 774 *px1 = this->getPixelAt(src, index + 1); | |
| 775 *px2 = this->getPixelAt(src, index + 2); | |
| 776 *px3 = this->getPixelAt(src, index + 3); | |
| 777 } | |
| 778 | |
| 779 Sk4f getPixelAt(const void* vsrc, int index) { | |
| 780 const uint64_t* src = static_cast<const uint64_t*>(vsrc) + index; | |
| 781 return SkHalfToFloat_01(*src); | 761 return SkHalfToFloat_01(*src); |
| 782 } | 762 } |
| 783 | 763 |
| 784 const void* row(int y) { return fSrc + y * fWidth[0]; } | 764 Sk4f getPixelAt(int index) { |
| 765 return this->getPixelFromRow(fSrc, index); |
| 766 } |
| 767 |
| 768 const void* row(int y) { return fSrc + y * fWidth; } |
| 785 | 769 |
| 786 private: | 770 private: |
| 787 const uint64_t* const fSrc; | 771 const uint64_t* const fSrc; |
| 788 const Sk4i fWidth; | 772 const int fWidth; |
| 789 }; | 773 }; |
| 790 | 774 |
| 775 using PixelHalfLinear = PixelAccessor<PixelGetter<kRGBA_F16_SkColorType, kLinear
_SkColorProfileType>>; |
| 776 |
| 791 } // namespace | 777 } // namespace |
| 792 | 778 |
| 793 #endif // SkLinearBitmapPipeline_sampler_DEFINED | 779 #endif // SkLinearBitmapPipeline_sampler_DEFINED |
| OLD | NEW |