OLD | NEW |
| (Empty) |
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 | |
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 warnin
gs | |
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 | |
53 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPai
nt& 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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
223 static int Bool2Int(bool value) { | |
224 return !!value; | |
225 } | |
226 | |
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 | |
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_col
or | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
588 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() { | |
589 sk_free(fBuffer); | |
590 } | |
591 | |
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 | |
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 | |
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 | |
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)) * siz
eof(SkPMColor)); | |
674 fAAExpand = (uint8_t*)(fBuffer + width); | |
675 } | |
676 | |
677 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() { | |
678 fXfermode->unref(); | |
679 sk_free(fBuffer); | |
680 } | |
681 | |
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 | |
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 | |
OLD | NEW |