1 #include "SkBitmapProcState.h"
2 #include "SkBitmapProcState_filter.h"
3 #include "SkColorPriv.h"
4 #include "SkFilterProc.h"
5 #include "SkPaint.h"
6 #include "SkShader.h" // for tilemodes
7
8 // returns expanded * 5bits
Filter_565_Expanded(unsigned x,unsigned y,uint32_t a00,uint32_t a01,uint32_t a10,uint32_t a11)9 static inline uint32_t Filter_565_Expanded(unsigned x, unsigned y,
10 uint32_t a00, uint32_t a01,
11 uint32_t a10, uint32_t a11) {
12 SkASSERT((unsigned)x <= 0xF);
13 SkASSERT((unsigned)y <= 0xF);
14
15 a00 = SkExpand_rgb_16(a00);
16 a01 = SkExpand_rgb_16(a01);
17 a10 = SkExpand_rgb_16(a10);
18 a11 = SkExpand_rgb_16(a11);
19
20 int xy = x * y >> 3;
21 return a00 * (32 - 2*y - 2*x + xy) +
22 a01 * (2*x - xy) +
23 a10 * (2*y - xy) +
24 a11 * xy;
25 }
26
27 // turn an expanded 565 * 5bits into SkPMColor
28 // g:11 | r:10 | x:1 | b:10
SkExpanded_565_To_PMColor(uint32_t c)29 static inline SkPMColor SkExpanded_565_To_PMColor(uint32_t c) {
30 unsigned r = (c >> 13) & 0xFF;
31 unsigned g = (c >> 24);
32 unsigned b = (c >> 2) & 0xFF;
33 return SkPackARGB32(0xFF, r, g, b);
34 }
35
36 // returns answer in SkPMColor format
Filter_4444_D32(unsigned x,unsigned y,uint32_t a00,uint32_t a01,uint32_t a10,uint32_t a11)37 static inline SkPMColor Filter_4444_D32(unsigned x, unsigned y,
38 uint32_t a00, uint32_t a01,
39 uint32_t a10, uint32_t a11) {
40 SkASSERT((unsigned)x <= 0xF);
41 SkASSERT((unsigned)y <= 0xF);
42
43 a00 = SkExpand_4444(a00);
44 a01 = SkExpand_4444(a01);
45 a10 = SkExpand_4444(a10);
46 a11 = SkExpand_4444(a11);
47
48 int xy = x * y >> 4;
49 uint32_t result = a00 * (16 - y - x + xy) +
50 a01 * (x - xy) +
51 a10 * (y - xy) +
52 a11 * xy;
53
54 return SkCompact_8888(result);
55 }
56
Filter_8(unsigned x,unsigned y,U8CPU a00,U8CPU a01,U8CPU a10,U8CPU a11)57 static inline U8CPU Filter_8(unsigned x, unsigned y,
58 U8CPU a00, U8CPU a01,
59 U8CPU a10, U8CPU a11) {
60 SkASSERT((unsigned)x <= 0xF);
61 SkASSERT((unsigned)y <= 0xF);
62
63 int xy = x * y;
64 unsigned result = a00 * (256 - 16*y - 16*x + xy) +
65 a01 * (16*x - xy) +
66 a10 * (16*y - xy) +
67 a11 * xy;
68
69 return result >> 8;
70 }
71
72 /*****************************************************************************
73 *
74 * D32 functions
75 *
76 */
77
78 // SRC == 8888
79
80 #define FILTER_PROC(x, y, a, b, c, d, dst) Filter_32_opaque(x, y, a, b, c, d, dst)
81
82 #define MAKENAME(suffix) S32_opaque_D32 ## suffix
83 #define DSTSIZE 32
84 #define SRCTYPE SkPMColor
85 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
86 SkASSERT(state.fAlphaScale == 256)
87 #define RETURNDST(src) src
88 #define SRC_TO_FILTER(src) src
89 #include "SkBitmapProcState_sample.h"
90
91 #undef FILTER_PROC
92 #define FILTER_PROC(x, y, a, b, c, d, dst) Filter_32_alpha(x, y, a, b, c, d, dst, alphaScale)
93
94 #define MAKENAME(suffix) S32_alpha_D32 ## suffix
95 #define DSTSIZE 32
96 #define SRCTYPE SkPMColor
97 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
98 SkASSERT(state.fAlphaScale < 256)
99 #define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale
100 #define RETURNDST(src) SkAlphaMulQ(src, alphaScale)
101 #define SRC_TO_FILTER(src) src
102 #include "SkBitmapProcState_sample.h"
103
104 // SRC == 565
105
106 #undef FILTER_PROC
107 #define FILTER_PROC(x, y, a, b, c, d, dst) \
108 do { \
109 uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d); \
110 *(dst) = SkExpanded_565_To_PMColor(tmp); \
111 } while (0)
112
113 #define MAKENAME(suffix) S16_opaque_D32 ## suffix
114 #define DSTSIZE 32
115 #define SRCTYPE uint16_t
116 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config); \
117 SkASSERT(state.fAlphaScale == 256)
118 #define RETURNDST(src) SkPixel16ToPixel32(src)
119 #define SRC_TO_FILTER(src) src
120 #include "SkBitmapProcState_sample.h"
121
122 #undef FILTER_PROC
123 #define FILTER_PROC(x, y, a, b, c, d, dst) \
124 do { \
125 uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d); \
126 *(dst) = SkAlphaMulQ(SkExpanded_565_To_PMColor(tmp), alphaScale); \
127 } while (0)
128
129 #define MAKENAME(suffix) S16_alpha_D32 ## suffix
130 #define DSTSIZE 32
131 #define SRCTYPE uint16_t
132 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config); \
133 SkASSERT(state.fAlphaScale < 256)
134 #define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale
135 #define RETURNDST(src) SkAlphaMulQ(SkPixel16ToPixel32(src), alphaScale)
136 #define SRC_TO_FILTER(src) src
137 #include "SkBitmapProcState_sample.h"
138
139 // SRC == Index8
140
141 #undef FILTER_PROC
142 #define FILTER_PROC(x, y, a, b, c, d, dst) Filter_32_opaque(x, y, a, b, c, d, dst)
143
144 #define MAKENAME(suffix) SI8_opaque_D32 ## suffix
145 #define DSTSIZE 32
146 #define SRCTYPE uint8_t
147 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
148 SkASSERT(state.fAlphaScale == 256)
149 #define PREAMBLE(state) const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
150 #define RETURNDST(src) table[src]
151 #define SRC_TO_FILTER(src) table[src]
152 #define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false)
153 #include "SkBitmapProcState_sample.h"
154
155 #undef FILTER_PROC
156 #define FILTER_PROC(x, y, a, b, c, d, dst) Filter_32_alpha(x, y, a, b, c, d, dst, alphaScale)
157
158 #define MAKENAME(suffix) SI8_alpha_D32 ## suffix
159 #define DSTSIZE 32
160 #define SRCTYPE uint8_t
161 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
162 SkASSERT(state.fAlphaScale < 256)
163 #define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale; \
164 const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
165 #define RETURNDST(src) SkAlphaMulQ(table[src], alphaScale)
166 #define SRC_TO_FILTER(src) table[src]
167 #define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false)
168 #include "SkBitmapProcState_sample.h"
169
170 // SRC == 4444
171
172 #undef FILTER_PROC
173 #define FILTER_PROC(x, y, a, b, c, d, dst) *(dst) = Filter_4444_D32(x, y, a, b, c, d)
174
175 #define MAKENAME(suffix) S4444_opaque_D32 ## suffix
176 #define DSTSIZE 32
177 #define SRCTYPE SkPMColor16
178 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_4444_Config); \
179 SkASSERT(state.fAlphaScale == 256)
180 #define RETURNDST(src) SkPixel4444ToPixel32(src)
181 #define SRC_TO_FILTER(src) src
182 #include "SkBitmapProcState_sample.h"
183
184 #undef FILTER_PROC
185 #define FILTER_PROC(x, y, a, b, c, d, dst) \
186 do { \
187 uint32_t tmp = Filter_4444_D32(x, y, a, b, c, d); \
188 *(dst) = SkAlphaMulQ(tmp, alphaScale); \
189 } while (0)
190
191 #define MAKENAME(suffix) S4444_alpha_D32 ## suffix
192 #define DSTSIZE 32
193 #define SRCTYPE SkPMColor16
194 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_4444_Config); \
195 SkASSERT(state.fAlphaScale < 256)
196 #define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale
197 #define RETURNDST(src) SkAlphaMulQ(SkPixel4444ToPixel32(src), alphaScale)
198 #define SRC_TO_FILTER(src) src
199 #include "SkBitmapProcState_sample.h"
200
201 // SRC == A8
202
203 #undef FILTER_PROC
204 #define FILTER_PROC(x, y, a, b, c, d, dst) \
205 do { \
206 unsigned tmp = Filter_8(x, y, a, b, c, d); \
207 *(dst) = SkAlphaMulQ(pmColor, SkAlpha255To256(tmp)); \
208 } while (0)
209
210 #define MAKENAME(suffix) SA8_alpha_D32 ## suffix
211 #define DSTSIZE 32
212 #define SRCTYPE uint8_t
213 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kA8_Config); \
214 SkASSERT(state.fAlphaScale == 256)
215 #define PREAMBLE(state) const SkPMColor pmColor = state.fPaintPMColor;
216 #define RETURNDST(src) SkAlphaMulQ(pmColor, SkAlpha255To256(src))
217 #define SRC_TO_FILTER(src) src
218 #include "SkBitmapProcState_sample.h"
219
220 /*****************************************************************************
221 *
222 * D16 functions
223 *
224 */
225
226 // SRC == 8888
227
228 #undef FILTER_PROC
229 #define FILTER_PROC(x, y, a, b, c, d, dst) \
230 do { \
231 SkPMColor dstColor; \
232 Filter_32_opaque(x, y, a, b, c, d, &dstColor); \
233 (*dst) = SkPixel32ToPixel16(dstColor); \
234 } while (0)
235
236 #define MAKENAME(suffix) S32_D16 ## suffix
237 #define DSTSIZE 16
238 #define SRCTYPE SkPMColor
239 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
240 SkASSERT(state.fBitmap->isOpaque())
241 #define RETURNDST(src) SkPixel32ToPixel16(src)
242 #define SRC_TO_FILTER(src) src
243 #include "SkBitmapProcState_sample.h"
244
245 // SRC == 565
246
247 #undef FILTER_PROC
248 #define FILTER_PROC(x, y, a, b, c, d, dst) \
249 do { \
250 uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d); \
251 *(dst) = SkCompact_rgb_16((tmp) >> 5); \
252 } while (0)
253
254 #define MAKENAME(suffix) S16_D16 ## suffix
255 #define DSTSIZE 16
256 #define SRCTYPE uint16_t
257 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
258 #define RETURNDST(src) src
259 #define SRC_TO_FILTER(src) src
260 #include "SkBitmapProcState_sample.h"
261
262 // SRC == Index8
263
264 #undef FILTER_PROC
265 #define FILTER_PROC(x, y, a, b, c, d, dst) \
266 do { \
267 uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d); \
268 *(dst) = SkCompact_rgb_16((tmp) >> 5); \
269 } while (0)
270
271 #define MAKENAME(suffix) SI8_D16 ## suffix
272 #define DSTSIZE 16
273 #define SRCTYPE uint8_t
274 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
275 SkASSERT(state.fBitmap->isOpaque())
276 #define PREAMBLE(state) const uint16_t* SK_RESTRICT table = state.fBitmap->getColorTable()->lock16BitCache()
277 #define RETURNDST(src) table[src]
278 #define SRC_TO_FILTER(src) table[src]
279 #define POSTAMBLE(state) state.fBitmap->getColorTable()->unlock16BitCache()
280 #include "SkBitmapProcState_sample.h"
281
282 ///////////////////////////////////////////////////////////////////////////////
283
284 #undef FILTER_PROC
285 #define FILTER_PROC(x, y, a, b, c, d, dst) \
286 do { \
287 uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d); \
288 *(dst) = SkCompact_rgb_16((tmp) >> 5); \
289 } while (0)
290
291
292 #define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
293 #define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
294 #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
295 #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
296
297 #define MAKENAME(suffix) Clamp_S16_D16 ## suffix
298 #define SRCTYPE uint16_t
299 #define DSTTYPE uint16_t
300 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
301 #define SRC_TO_FILTER(src) src
302 #include "SkBitmapProcState_shaderproc.h"
303
304
305 #define TILEX_PROCF(fx, max) (((fx) & 0xFFFF) * ((max) + 1) >> 16)
306 #define TILEY_PROCF(fy, max) (((fy) & 0xFFFF) * ((max) + 1) >> 16)
307 #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
308 #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
309
310 #define MAKENAME(suffix) Repeat_S16_D16 ## suffix
311 #define SRCTYPE uint16_t
312 #define DSTTYPE uint16_t
313 #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
314 #define SRC_TO_FILTER(src) src
315 #include "SkBitmapProcState_shaderproc.h"
316
317 ///////////////////////////////////////////////////////////////////////////////
318
valid_for_filtering(unsigned dimension)319 static bool valid_for_filtering(unsigned dimension) {
320 // for filtering, width and height must fit in 14bits, since we use steal
321 // 2 bits from each to store our 4bit subpixel data
322 return (dimension & ~0x3FFF) == 0;
323 }
324
chooseProcs(const SkMatrix & inv,const SkPaint & paint)325 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
326 if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) {
327 return false;
328 }
329
330 const SkMatrix* m;
331 bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0;
332 bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX &&
333 SkShader::kClamp_TileMode == fTileModeY;
334
335 if (clamp_clamp || trivial_matrix) {
336 m = &inv;
337 } else {
338 fUnitInvMatrix = inv;
339 fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
340 m = &fUnitInvMatrix;
341 }
342
343 fBitmap = &fOrigBitmap;
344 if (fOrigBitmap.hasMipMap()) {
345 int shift = fOrigBitmap.extractMipLevel(&fMipBitmap,
346 SkScalarToFixed(m->getScaleX()),
347 SkScalarToFixed(m->getSkewY()));
348
349 if (shift > 0) {
350 if (m != &fUnitInvMatrix) {
351 fUnitInvMatrix = *m;
352 m = &fUnitInvMatrix;
353 }
354
355 SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
356 fUnitInvMatrix.postScale(scale, scale);
357
358 // now point here instead of fOrigBitmap
359 fBitmap = &fMipBitmap;
360 }
361 }
362
363 fInvMatrix = m;
364 fInvProc = m->getMapXYProc();
365 fInvType = m->getType();
366 fInvSx = SkScalarToFixed(m->getScaleX());
367 fInvKy = SkScalarToFixed(m->getSkewY());
368
369 fAlphaScale = SkAlpha255To256(paint.getAlpha());
370
371 // pick-up filtering from the paint, but only if the matrix is
372 // more complex than identity/translate (i.e. no need to pay the cost
373 // of filtering if we're not scaled etc.).
374 // note: we explicitly check inv, since m might be scaled due to unitinv
375 // trickery, but we don't want to see that for this test
376 fDoFilter = paint.isFilterBitmap() &&
377 (inv.getType() > SkMatrix::kTranslate_Mask &&
378 valid_for_filtering(fBitmap->width() | fBitmap->height()));
379
380 fShaderProc32 = NULL;
381 fShaderProc16 = NULL;
382 fSampleProc32 = NULL;
383 fSampleProc16 = NULL;
384
385 fMatrixProc = this->chooseMatrixProc(trivial_matrix);
386 if (NULL == fMatrixProc) {
387 return false;
388 }
389
390 ///////////////////////////////////////////////////////////////////////
391
392 int index = 0;
393 if (fAlphaScale < 256) { // note: this distinction is not used for D16
394 index |= 1;
395 }
396 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
397 index |= 2;
398 }
399 if (fDoFilter) {
400 index |= 4;
401 }
402 // bits 3,4,5 encoding the source bitmap format
403 switch (fBitmap->config()) {
404 case SkBitmap::kARGB_8888_Config:
405 index |= 0;
406 break;
407 case SkBitmap::kRGB_565_Config:
408 index |= 8;
409 break;
410 case SkBitmap::kIndex8_Config:
411 index |= 16;
412 break;
413 case SkBitmap::kARGB_4444_Config:
414 index |= 24;
415 break;
416 case SkBitmap::kA8_Config:
417 index |= 32;
418 fPaintPMColor = SkPreMultiplyColor(paint.getColor());
419 break;
420 default:
421 return false;
422 }
423
424 static const SampleProc32 gSample32[] = {
425 S32_opaque_D32_nofilter_DXDY,
426 S32_alpha_D32_nofilter_DXDY,
427 S32_opaque_D32_nofilter_DX,
428 S32_alpha_D32_nofilter_DX,
429 S32_opaque_D32_filter_DXDY,
430 S32_alpha_D32_filter_DXDY,
431 S32_opaque_D32_filter_DX,
432 S32_alpha_D32_filter_DX,
433
434 S16_opaque_D32_nofilter_DXDY,
435 S16_alpha_D32_nofilter_DXDY,
436 S16_opaque_D32_nofilter_DX,
437 S16_alpha_D32_nofilter_DX,
438 S16_opaque_D32_filter_DXDY,
439 S16_alpha_D32_filter_DXDY,
440 S16_opaque_D32_filter_DX,
441 S16_alpha_D32_filter_DX,
442
443 SI8_opaque_D32_nofilter_DXDY,
444 SI8_alpha_D32_nofilter_DXDY,
445 SI8_opaque_D32_nofilter_DX,
446 SI8_alpha_D32_nofilter_DX,
447 SI8_opaque_D32_filter_DXDY,
448 SI8_alpha_D32_filter_DXDY,
449 SI8_opaque_D32_filter_DX,
450 SI8_alpha_D32_filter_DX,
451
452 S4444_opaque_D32_nofilter_DXDY,
453 S4444_alpha_D32_nofilter_DXDY,
454 S4444_opaque_D32_nofilter_DX,
455 S4444_alpha_D32_nofilter_DX,
456 S4444_opaque_D32_filter_DXDY,
457 S4444_alpha_D32_filter_DXDY,
458 S4444_opaque_D32_filter_DX,
459 S4444_alpha_D32_filter_DX,
460
461 // A8 treats alpha/opauqe the same (equally efficient)
462 SA8_alpha_D32_nofilter_DXDY,
463 SA8_alpha_D32_nofilter_DXDY,
464 SA8_alpha_D32_nofilter_DX,
465 SA8_alpha_D32_nofilter_DX,
466 SA8_alpha_D32_filter_DXDY,
467 SA8_alpha_D32_filter_DXDY,
468 SA8_alpha_D32_filter_DX,
469 SA8_alpha_D32_filter_DX
470 };
471
472 static const SampleProc16 gSample16[] = {
473 S32_D16_nofilter_DXDY,
474 S32_D16_nofilter_DX,
475 S32_D16_filter_DXDY,
476 S32_D16_filter_DX,
477
478 S16_D16_nofilter_DXDY,
479 S16_D16_nofilter_DX,
480 S16_D16_filter_DXDY,
481 S16_D16_filter_DX,
482
483 SI8_D16_nofilter_DXDY,
484 SI8_D16_nofilter_DX,
485 SI8_D16_filter_DXDY,
486 SI8_D16_filter_DX,
487
488 // Don't support 4444 -> 565
489 NULL, NULL, NULL, NULL,
490 // Don't support A8 -> 565
491 NULL, NULL, NULL, NULL
492 };
493
494 fSampleProc32 = gSample32[index];
495 index >>= 1; // shift away any opaque/alpha distinction
496 fSampleProc16 = gSample16[index];
497
498 // our special-case shaderprocs
499 if (S16_D16_filter_DX == fSampleProc16) {
500 if (clamp_clamp) {
501 fShaderProc16 = Clamp_S16_D16_filter_DX_shaderproc;
502 } else if (SkShader::kRepeat_TileMode == fTileModeX &&
503 SkShader::kRepeat_TileMode == fTileModeY) {
504 fShaderProc16 = Repeat_S16_D16_filter_DX_shaderproc;
505 }
506 }
507
508 // see if our platform has any accelerated overrides
509 this->platformProcs();
510 return true;
511 }
512
513 ///////////////////////////////////////////////////////////////////////////////
514 /*
515 The storage requirements for the different matrix procs are as follows,
516 where each X or Y is 2 bytes, and N is the number of pixels/elements:
517
518 scale/translate nofilter Y(4bytes) + N * X
519 affine/perspective nofilter N * (X Y)
520 scale/translate filter Y Y + N * (X X)
521 affine/perspective filter N * (Y Y X X)
522 */
maxCountForBufferSize(size_t bufferSize) const523 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
524 int32_t size = static_cast<int32_t>(bufferSize);
525 int perElemShift;
526
527 size &= ~3; // only care about 4-byte aligned chunks
528 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
529 size -= 4; // the shared Y (or YY) coordinate
530 if (size < 0) {
531 size = 0;
532 }
533 perElemShift = fDoFilter ? 2 : 1;
534 } else {
535 perElemShift = fDoFilter ? 3 : 2;
536 }
537
538 return size >> perElemShift;
539 }
540
541