1 /* libs/graphics/sgl/SkBlitter_RGB16.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkBlitRow.h"
19 #include "SkCoreBlitters.h"
20 #include "SkColorPriv.h"
21 #include "SkDither.h"
22 #include "SkShader.h"
23 #include "SkUtils.h"
24 #include "SkXfermode.h"
25
sk_dither_memset16(uint16_t dst[],uint16_t value,uint16_t other,int count)26 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
27 int count) {
28 if (count > 0) {
29 // see if we need to write one short before we can cast to an 4byte ptr
30 // (we do this subtract rather than (unsigned)dst so we don't get warnings
31 // on 64bit machines)
32 if (((char*)dst - (char*)0) & 2) {
33 *dst++ = value;
34 count -= 1;
35 SkTSwap(value, other);
36 }
37
38 // fast way to set [value,other] pairs
39 #ifdef SK_CPU_BENDIAN
40 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
41 #else
42 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
43 #endif
44
45 if (count & 1) {
46 dst[count - 1] = value;
47 }
48 }
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52
SkRGB16_Black_Blitter(const SkBitmap & device,const SkPaint & paint)53 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
54 : SkRGB16_Blitter(device, paint) {
55 SkASSERT(paint.getShader() == NULL);
56 SkASSERT(paint.getColorFilter() == NULL);
57 SkASSERT(paint.getXfermode() == NULL);
58 SkASSERT(paint.getColor() == SK_ColorBLACK);
59 }
60
61 #if 1
62 #define black_8_pixels(mask, dst) \
63 do { \
64 if (mask & 0x80) dst[0] = 0; \
65 if (mask & 0x40) dst[1] = 0; \
66 if (mask & 0x20) dst[2] = 0; \
67 if (mask & 0x10) dst[3] = 0; \
68 if (mask & 0x08) dst[4] = 0; \
69 if (mask & 0x04) dst[5] = 0; \
70 if (mask & 0x02) dst[6] = 0; \
71 if (mask & 0x01) dst[7] = 0; \
72 } while (0)
73 #else
black_8_pixels(U8CPU mask,uint16_t dst[])74 static inline black_8_pixels(U8CPU mask, uint16_t dst[])
75 {
76 if (mask & 0x80) dst[0] = 0;
77 if (mask & 0x40) dst[1] = 0;
78 if (mask & 0x20) dst[2] = 0;
79 if (mask & 0x10) dst[3] = 0;
80 if (mask & 0x08) dst[4] = 0;
81 if (mask & 0x04) dst[5] = 0;
82 if (mask & 0x02) dst[6] = 0;
83 if (mask & 0x01) dst[7] = 0;
84 }
85 #endif
86
87 #define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW
88 #define SK_BLITBWMASK_ARGS
89 #define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst)
90 #define SK_BLITBWMASK_GETADDR getAddr16
91 #define SK_BLITBWMASK_DEVTYPE uint16_t
92 #include "SkBlitBWMaskTemplate.h"
93
blitMask(const SkMask & SK_RESTRICT mask,const SkIRect & SK_RESTRICT clip)94 void SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
95 const SkIRect& SK_RESTRICT clip)
96 SK_RESTRICT {
97 if (mask.fFormat == SkMask::kBW_Format) {
98 SkRGB16_Black_BlitBW(fDevice, mask, clip);
99 } else {
100 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
101 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
102 unsigned width = clip.width();
103 unsigned height = clip.height();
104 unsigned deviceRB = fDevice.rowBytes() - (width << 1);
105 unsigned maskRB = mask.fRowBytes - width;
106
107 SkASSERT((int)height > 0);
108 SkASSERT((int)width > 0);
109 SkASSERT((int)deviceRB >= 0);
110 SkASSERT((int)maskRB >= 0);
111
112 do {
113 unsigned w = width;
114 do {
115 unsigned aa = *alpha++;
116 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
117 device += 1;
118 } while (--w != 0);
119 device = (uint16_t*)((char*)device + deviceRB);
120 alpha += maskRB;
121 } while (--height != 0);
122 }
123 }
124
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)125 void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
126 const SkAlpha* SK_RESTRICT antialias,
127 const int16_t* SK_RESTRICT runs)
128 SK_RESTRICT {
129 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
130
131 for (;;) {
132 int count = runs[0];
133 SkASSERT(count >= 0);
134 if (count <= 0) {
135 return;
136 }
137 runs += count;
138
139 unsigned aa = antialias[0];
140 antialias += count;
141 if (aa) {
142 if (aa == 255) {
143 memset(device, 0, count << 1);
144 } else {
145 aa = SkAlpha255To256(255 - aa);
146 do {
147 *device = SkAlphaMulRGB16(*device, aa);
148 device += 1;
149 } while (--count != 0);
150 continue;
151 }
152 }
153 device += count;
154 }
155 }
156
157 //////////////////////////////////////////////////////////////////////////////////////////////////
158 //////////////////////////////////////////////////////////////////////////////////////////////////
159
SkRGB16_Blitter(const SkBitmap & device,const SkPaint & paint)160 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
161 : INHERITED(device) {
162 SkColor color = paint.getColor();
163
164 fSrcColor32 = SkPreMultiplyColor(color);
165 fScale = SkAlpha255To256(SkColorGetA(color));
166
167 int r = SkColorGetR(color);
168 int g = SkColorGetG(color);
169 int b = SkColorGetB(color);
170
171 fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
172 // if we're dithered, use fRawDither16 to hold that.
173 if ((fDoDither = paint.isDither()) != false) {
174 fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
175 }
176
177 fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
178 SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
179 SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
180 }
181
justAnOpaqueColor(uint32_t * value)182 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
183 if (!fDoDither && 256 == fScale) {
184 *value = fRawColor16;
185 return &fDevice;
186 }
187 return NULL;
188 }
189
blitH(int x,int y,int width)190 void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
191 SkASSERT(width > 0);
192 SkASSERT(x + width <= fDevice.width());
193
194 if (fScale == 0) {
195 return;
196 }
197
198 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
199 uint16_t srcColor = fColor16;
200
201 if (256 == fScale) {
202 SkASSERT(fRawColor16 == srcColor);
203 if (fDoDither) {
204 uint16_t ditherColor = fRawDither16;
205 if ((x ^ y) & 1) {
206 SkTSwap(ditherColor, srcColor);
207 }
208 sk_dither_memset16(device, srcColor, ditherColor, width);
209 } else {
210 sk_memset16(device, srcColor, width);
211 }
212 } else {
213 // TODO: respect fDoDither
214 SkPMColor src32 = fSrcColor32;
215 do {
216 *device = SkSrcOver32To16(src32, *device);
217 device += 1;
218 } while (--width != 0);
219 }
220 }
221
222 // return 1 or 0 from a bool
Bool2Int(bool value)223 static int Bool2Int(bool value) {
224 return !!value;
225 }
226
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)227 void SkRGB16_Blitter::blitAntiH(int x, int y,
228 const SkAlpha* SK_RESTRICT antialias,
229 const int16_t* SK_RESTRICT runs) SK_RESTRICT {
230 if (fScale == 0) {
231 return;
232 }
233
234 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
235 uint16_t srcColor = fRawColor16;
236 unsigned scale = fScale;
237 int ditherInt = Bool2Int(fDoDither);
238
239 if (256 == scale) {
240 uint16_t ditherColor = fRawDither16;
241 // if we have no dithering, this will always fail
242 if ((x ^ y) & ditherInt) {
243 SkTSwap(ditherColor, srcColor);
244 }
245 for (;;) {
246 int count = runs[0];
247 SkASSERT(count >= 0);
248 if (count <= 0) {
249 return;
250 }
251 runs += count;
252
253 unsigned aa = antialias[0];
254 antialias += count;
255 if (aa) {
256 if (aa == 255) {
257 if (ditherInt) {
258 sk_dither_memset16(device, srcColor,
259 ditherColor, count);
260 } else {
261 sk_memset16(device, srcColor, count);
262 }
263 } else {
264 // TODO: respect fDoDither
265 unsigned scale5 = SkAlpha255To256(aa) >> 3;
266 uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5;
267 scale5 = 32 - scale5; // now we can use it on the device
268 int n = count;
269 do {
270 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
271 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
272 } while (--n != 0);
273 goto DONE;
274 }
275 }
276 device += count;
277
278 DONE:
279 // if we have no dithering, this will always fail
280 if (count & ditherInt) {
281 SkTSwap(ditherColor, srcColor);
282 }
283 }
284 } else {
285 // TODO: respect fDoDither
286 for (;;) {
287 int count = runs[0];
288 SkASSERT(count >= 0);
289 if (count <= 0) {
290 return;
291 }
292 runs += count;
293
294 unsigned aa = antialias[0];
295 antialias += count;
296 if (aa) {
297 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
298 uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5;
299 scale5 = 32 - scale5;
300 do {
301 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
302 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
303 } while (--count != 0);
304 continue;
305 }
306 device += count;
307 }
308 }
309 }
310
311 //////////////////////////////////////////////////////////////////////////////////////
312
313 #define solid_8_pixels(mask, dst, color) \
314 do { \
315 if (mask & 0x80) dst[0] = color; \
316 if (mask & 0x40) dst[1] = color; \
317 if (mask & 0x20) dst[2] = color; \
318 if (mask & 0x10) dst[3] = color; \
319 if (mask & 0x08) dst[4] = color; \
320 if (mask & 0x04) dst[5] = color; \
321 if (mask & 0x02) dst[6] = color; \
322 if (mask & 0x01) dst[7] = color; \
323 } while (0)
324
325 #define SK_BLITBWMASK_NAME SkRGB16_BlitBW
326 #define SK_BLITBWMASK_ARGS , uint16_t color
327 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
328 #define SK_BLITBWMASK_GETADDR getAddr16
329 #define SK_BLITBWMASK_DEVTYPE uint16_t
330 #include "SkBlitBWMaskTemplate.h"
331
blend_8_pixels(U8CPU bw,uint16_t dst[],unsigned dst_scale,U16CPU srcColor)332 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
333 U16CPU srcColor) {
334 if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
335 if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
336 if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
337 if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
338 if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
339 if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
340 if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
341 if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
342 }
343
344 #define SK_BLITBWMASK_NAME SkRGB16_BlendBW
345 #define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color
346 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color)
347 #define SK_BLITBWMASK_GETADDR getAddr16
348 #define SK_BLITBWMASK_DEVTYPE uint16_t
349 #include "SkBlitBWMaskTemplate.h"
350
blend_compact(uint32_t src32,uint32_t dst32,unsigned scale5)351 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
352 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
353 }
354
blitMask(const SkMask & SK_RESTRICT mask,const SkIRect & SK_RESTRICT clip)355 void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
356 const SkIRect& SK_RESTRICT clip) SK_RESTRICT {
357 if (fScale == 0) {
358 return;
359 }
360 if (mask.fFormat == SkMask::kBW_Format) {
361 if (fScale == 256) {
362 SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
363 } else {
364 SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
365 }
366 return;
367 }
368
369 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
370 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
371 int width = clip.width();
372 int height = clip.height();
373 unsigned deviceRB = fDevice.rowBytes() - (width << 1);
374 unsigned maskRB = mask.fRowBytes - width;
375 uint32_t color32 = SkExpand_rgb_16(fRawColor16);
376
377 if (256 == fScale) {
378 do {
379 int w = width;
380 do {
381 *device = blend_compact(color32, SkExpand_rgb_16(*device),
382 SkAlpha255To256(*alpha++) >> 3);
383 device += 1;
384 } while (--w != 0);
385 device = (uint16_t*)((char*)device + deviceRB);
386 alpha += maskRB;
387 } while (--height != 0);
388 } else { // scale < 256
389 unsigned scale256 = fScale;
390 do {
391 int w = width;
392 do {
393 unsigned aa = *alpha++;
394 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
395 uint32_t src32 = color32 * scale;
396 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
397 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
398 } while (--w != 0);
399 device = (uint16_t*)((char*)device + deviceRB);
400 alpha += maskRB;
401 } while (--height != 0);
402 }
403 }
404
blitV(int x,int y,int height,SkAlpha alpha)405 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
406 if (fScale == 0) {
407 return;
408 }
409 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
410 uint16_t color16 = fRawColor16;
411 unsigned deviceRB = fDevice.rowBytes();
412
413 if (alpha + fScale == (255 + 256)) {
414 if (fDoDither) {
415 uint16_t ditherColor = fRawDither16;
416 if ((x ^ y) & 1) {
417 SkTSwap(ditherColor, color16);
418 }
419 do {
420 device[0] = color16;
421 device = (uint16_t*)((char*)device + deviceRB);
422 SkTSwap(ditherColor, color16);
423 } while (--height != 0);
424 } else {
425 do {
426 device[0] = color16;
427 device = (uint16_t*)((char*)device + deviceRB);
428 } while (--height != 0);
429 }
430 } else {
431 // TODO: respect fDoDither
432 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
433 uint32_t src32 = SkExpand_rgb_16(color16) * scale5;
434 scale5 = 32 - scale5;
435 do {
436 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
437 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
438 device = (uint16_t*)((char*)device + deviceRB);
439 } while (--height != 0);
440 }
441 }
442
blitRect(int x,int y,int width,int height)443 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
444 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
445
446 if (fScale == 0) {
447 return;
448 }
449 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
450 unsigned deviceRB = fDevice.rowBytes();
451 uint16_t color16 = fColor16;
452
453 if (256 == fScale) {
454 if (fDoDither) {
455 uint16_t ditherColor = fRawDither16;
456 if ((x ^ y) & 1) {
457 SkTSwap(ditherColor, color16);
458 }
459 while (--height >= 0) {
460 sk_dither_memset16(device, color16, ditherColor, width);
461 SkTSwap(ditherColor, color16);
462 device = (uint16_t*)((char*)device + deviceRB);
463 }
464 } else { // no dither
465 while (--height >= 0) {
466 sk_memset16(device, color16, width);
467 device = (uint16_t*)((char*)device + deviceRB);
468 }
469 }
470 } else {
471 SkPMColor src32 = fSrcColor32;
472 while (--height >= 0) {
473 for (int i = width - 1; i >= 0; --i) {
474 device[i] = SkSrcOver32To16(src32, device[i]);
475 }
476 device = (uint16_t*)((char*)device + deviceRB);
477 }
478 }
479 }
480
481 ///////////////////////////////////////////////////////////////////////////////
482
SkRGB16_Shader16_Blitter(const SkBitmap & device,const SkPaint & paint)483 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
484 const SkPaint& paint)
485 : SkRGB16_Shader_Blitter(device, paint) {
486 SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags()));
487 }
488
blitH(int x,int y,int width)489 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
490 SkASSERT(x + width <= fDevice.width());
491
492 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
493 SkShader* shader = fShader;
494
495 int alpha = shader->getSpan16Alpha();
496 if (0xFF == alpha) {
497 shader->shadeSpan16(x, y, device, width);
498 } else {
499 uint16_t* span16 = (uint16_t*)fBuffer;
500 shader->shadeSpan16(x, y, span16, width);
501 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
502 }
503 }
504
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)505 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
506 const SkAlpha* SK_RESTRICT antialias,
507 const int16_t* SK_RESTRICT runs)
508 SK_RESTRICT {
509 SkShader* shader = fShader;
510 SkPMColor* SK_RESTRICT span = fBuffer;
511 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
512
513 int alpha = shader->getSpan16Alpha();
514 uint16_t* span16 = (uint16_t*)span;
515
516 if (0xFF == alpha) {
517 for (;;) {
518 int count = *runs;
519 if (count <= 0) {
520 break;
521 }
522 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
523
524 int aa = *antialias;
525 if (aa == 255) {
526 // go direct to the device!
527 shader->shadeSpan16(x, y, device, count);
528 } else if (aa) {
529 shader->shadeSpan16(x, y, span16, count);
530 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
531 }
532 device += count;
533 runs += count;
534 antialias += count;
535 x += count;
536 }
537 } else { // span alpha is < 255
538 alpha = SkAlpha255To256(alpha);
539 for (;;) {
540 int count = *runs;
541 if (count <= 0) {
542 break;
543 }
544 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
545
546 int aa = SkAlphaMul(*antialias, alpha);
547 if (aa) {
548 shader->shadeSpan16(x, y, span16, count);
549 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
550 }
551
552 device += count;
553 runs += count;
554 antialias += count;
555 x += count;
556 }
557 }
558 }
559
560 ///////////////////////////////////////////////////////////////////////////////
561
SkRGB16_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)562 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
563 const SkPaint& paint)
564 : INHERITED(device, paint) {
565 SkASSERT(paint.getXfermode() == NULL);
566
567 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
568
569 // compute SkBlitRow::Procs
570 unsigned flags = 0;
571
572 uint32_t shaderFlags = fShader->getFlags();
573 // shaders take care of global alpha, so we never set it in SkBlitRow
574 if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
575 flags |= SkBlitRow::kSrcPixelAlpha_Flag;
576 }
577 // don't dither if the shader is really 16bit
578 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
579 flags |= SkBlitRow::kDither_Flag;
580 }
581 // used when we know our global alpha is 0xFF
582 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
583 // used when we know our global alpha is < 0xFF
584 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
585 SkBitmap::kRGB_565_Config);
586 }
587
~SkRGB16_Shader_Blitter()588 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
589 sk_free(fBuffer);
590 }
591
blitH(int x,int y,int width)592 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
593 SkASSERT(x + width <= fDevice.width());
594
595 fShader->shadeSpan(x, y, fBuffer, width);
596 // shaders take care of global alpha, so we pass 0xFF (should be ignored)
597 fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
598 }
599
count_nonzero_span(const int16_t runs[],const SkAlpha aa[])600 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
601 int count = 0;
602 for (;;) {
603 int n = *runs;
604 if (n == 0 || *aa == 0) {
605 break;
606 }
607 runs += n;
608 aa += n;
609 count += n;
610 }
611 return count;
612 }
613
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)614 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
615 const SkAlpha* SK_RESTRICT antialias,
616 const int16_t* SK_RESTRICT runs)
617 SK_RESTRICT {
618 SkShader* shader = fShader;
619 SkPMColor* SK_RESTRICT span = fBuffer;
620 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
621
622 for (;;) {
623 int count = *runs;
624 if (count <= 0) {
625 break;
626 }
627 int aa = *antialias;
628 if (0 == aa) {
629 device += count;
630 runs += count;
631 antialias += count;
632 x += count;
633 continue;
634 }
635
636 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
637
638 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
639 shader->shadeSpan(x, y, span, nonZeroCount);
640
641 SkPMColor* localSpan = span;
642 for (;;) {
643 SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
644 proc(device, localSpan, count, aa, x, y);
645
646 x += count;
647 device += count;
648 runs += count;
649 antialias += count;
650 nonZeroCount -= count;
651 if (nonZeroCount == 0) {
652 break;
653 }
654 localSpan += count;
655 SkASSERT(nonZeroCount > 0);
656 count = *runs;
657 SkASSERT(count > 0);
658 aa = *antialias;
659 }
660 }
661 }
662
663 ///////////////////////////////////////////////////////////////////////
664
SkRGB16_Shader_Xfermode_Blitter(const SkBitmap & device,const SkPaint & paint)665 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
666 const SkBitmap& device, const SkPaint& paint)
667 : INHERITED(device, paint) {
668 fXfermode = paint.getXfermode();
669 SkASSERT(fXfermode);
670 fXfermode->ref();
671
672 int width = device.width();
673 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
674 fAAExpand = (uint8_t*)(fBuffer + width);
675 }
676
~SkRGB16_Shader_Xfermode_Blitter()677 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
678 fXfermode->unref();
679 sk_free(fBuffer);
680 }
681
blitH(int x,int y,int width)682 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
683 SkASSERT(x + width <= fDevice.width());
684
685 uint16_t* device = fDevice.getAddr16(x, y);
686 SkPMColor* span = fBuffer;
687
688 fShader->shadeSpan(x, y, span, width);
689 fXfermode->xfer16(device, span, width, NULL);
690 }
691
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)692 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
693 const SkAlpha* SK_RESTRICT antialias,
694 const int16_t* SK_RESTRICT runs) SK_RESTRICT {
695 SkShader* shader = fShader;
696 SkXfermode* mode = fXfermode;
697 SkPMColor* SK_RESTRICT span = fBuffer;
698 uint8_t* SK_RESTRICT aaExpand = fAAExpand;
699 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
700
701 for (;;) {
702 int count = *runs;
703 if (count <= 0) {
704 break;
705 }
706 int aa = *antialias;
707 if (0 == aa) {
708 device += count;
709 runs += count;
710 antialias += count;
711 x += count;
712 continue;
713 }
714
715 int nonZeroCount = count + count_nonzero_span(runs + count,
716 antialias + count);
717
718 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
719 shader->shadeSpan(x, y, span, nonZeroCount);
720
721 x += nonZeroCount;
722 SkPMColor* localSpan = span;
723 for (;;) {
724 if (aa == 0xFF) {
725 mode->xfer16(device, localSpan, count, NULL);
726 } else {
727 SkASSERT(aa);
728 memset(aaExpand, aa, count);
729 mode->xfer16(device, localSpan, count, aaExpand);
730 }
731 device += count;
732 runs += count;
733 antialias += count;
734 nonZeroCount -= count;
735 if (nonZeroCount == 0) {
736 break;
737 }
738 localSpan += count;
739 SkASSERT(nonZeroCount > 0);
740 count = *runs;
741 SkASSERT(count > 0);
742 aa = *antialias;
743 }
744 }
745 }
746
747 ////////////////////////
748
749 #if 0
750 static inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa
751 #ifdef DITHER_SHADER
752 , int dither
753 #endif
754 )
755 {
756 SkASSERT((unsigned)aa <= 255);
757
758 int src_scale = SkAlpha255To256(aa);
759 int sa = SkGetPackedA32(src);
760 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
761
762 #ifdef DITHER_SHADER
763 int sr = SkGetPackedR32(src);
764 int sg = SkGetPackedG32(src);
765 int sb = SkGetPackedB32(src);
766 sr = SkDITHER_R32To16(sr, dither);
767 sg = SkDITHER_G32To16(sg, dither);
768 sb = SkDITHER_B32To16(sb, dither);
769 #else
770 int sr = SkPacked32ToR16(src);
771 int sg = SkPacked32ToG16(src);
772 int sb = SkPacked32ToB16(src);
773 #endif
774
775 int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8;
776 int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8;
777 int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8;
778
779 return SkPackRGB16(dr, dg, db);
780 }
781 #endif
782
783