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 |