1/* libs/graphics/sgl/SkBitmapShaderTemplate.h
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
19#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE
20    #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb)
21#endif
22#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE
23    #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap)
24#endif
25#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE16
26    #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb)
27#endif
28#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE16
29    #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap)
30#endif
31
32class NOFILTER_BITMAP_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader {
33public:
34    NOFILTER_BITMAP_SHADER_CLASS(const SkBitmap& src)
35        : HasSpan16_Sampler_BitmapShader(src, false,
36                                         NOFILTER_BITMAP_SHADER_TILEMODE,
37                                         NOFILTER_BITMAP_SHADER_TILEMODE)
38    {
39    }
40
41    virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
42    {
43        if (!this->INHERITED::setContext(device, paint, matrix))
44            return false;
45
46#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
47        this->computeUnitInverse();
48#endif
49        return true;
50    }
51
52    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
53    {
54        SkASSERT(count > 0);
55
56#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC32
57        if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
58        {
59            NOFILTER_BITMAP_SHADER_SPRITEPROC32(this, x, y, dstC, count);
60            return;
61        }
62#endif
63
64        unsigned        scale = SkAlpha255To256(this->getPaintAlpha());
65#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
66        const SkMatrix& inv = this->getUnitInverse();
67        SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
68#else
69        const SkMatrix& inv = this->getTotalInverse();
70        SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
71#endif
72        const SkBitmap& srcBitmap = this->getSrcBitmap();
73        unsigned        srcMaxX = srcBitmap.width() - 1;
74        unsigned        srcMaxY = srcBitmap.height() - 1;
75        unsigned        srcRB = srcBitmap.rowBytes();
76        SkFixed         fx, fy, dx, dy;
77
78        const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
79        NOFILTER_BITMAP_SHADER_PREAMBLE(srcBitmap, srcRB);
80
81        if (this->getInverseClass() == kPerspective_MatrixClass)
82        {
83            SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
84                                    SkIntToScalar(y) + SK_ScalarHalf, count);
85            while ((count = iter.next()) != 0)
86            {
87                const SkFixed* srcXY = iter.getXY();
88
89/*  Do I need this?
90#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
91            fx >>= level;
92            fy >>= level;
93#endif
94*/
95                if (256 == scale)
96                {
97                    while (--count >= 0)
98                    {
99                        fx = *srcXY++;
100                        fy = *srcXY++;
101                        unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
102                        unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
103                        *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
104                    }
105                }
106                else
107                {
108                    while (--count >= 0)
109                    {
110                        fx = *srcXY++;
111                        fy = *srcXY++;
112                        unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
113                        unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
114                        uint32_t c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
115                        *dstC++ = SkAlphaMulQ(c, scale);
116                    }
117                }
118            }
119            return;
120        }
121
122        // now init fx, fy, dx, dy
123        {
124            SkPoint srcPt;
125            invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
126                         SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
127
128            fx = SkScalarToFixed(srcPt.fX);
129            fy = SkScalarToFixed(srcPt.fY);
130
131            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
132                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
133            else
134            {
135                dx = SkScalarToFixed(inv.getScaleX());
136                dy = SkScalarToFixed(inv.getSkewY());
137            }
138        }
139
140#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
141        {   int level = this->getMipLevel() >> 16;
142            fx >>= level;
143            fy >>= level;
144            dx >>= level;
145            dy >>= level;
146        }
147#endif
148
149        if (dy == 0)
150        {
151            int y_index = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
152//          SkDEBUGF(("fy = %g, srcMaxY = %d, y_index = %d\n", SkFixedToFloat(fy), srcMaxY, y_index));
153            srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + y_index * srcRB);
154            if (scale == 256)
155                while (--count >= 0)
156                {
157                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
158                    fx += dx;
159                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
160                }
161            else
162                while (--count >= 0)
163                {
164                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
165                    SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
166                    fx += dx;
167                    *dstC++ = SkAlphaMulQ(c, scale);
168                }
169        }
170        else    // dy != 0
171        {
172            if (scale == 256)
173                while (--count >= 0)
174                {
175                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
176                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
177                    fx += dx;
178                    fy += dy;
179                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
180                }
181            else
182                while (--count >= 0)
183                {
184                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
185                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
186                    SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
187                    fx += dx;
188                    fy += dy;
189                    *dstC++ = SkAlphaMulQ(c, scale);
190                }
191        }
192
193        NOFILTER_BITMAP_SHADER_POSTAMBLE(srcBitmap);
194    }
195
196    virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count)
197    {
198        SkASSERT(count > 0);
199        SkASSERT(this->getFlags() & SkShader::kHasSpan16_Flag);
200
201#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC16
202        if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
203        {
204            NOFILTER_BITMAP_SHADER_SPRITEPROC16(this, x, y, dstC, count);
205            return;
206        }
207#endif
208
209#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
210        const SkMatrix& inv = this->getUnitInverse();
211        SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
212#else
213        const SkMatrix& inv = this->getTotalInverse();
214        SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
215#endif
216        const SkBitmap& srcBitmap = this->getSrcBitmap();
217        unsigned        srcMaxX = srcBitmap.width() - 1;
218        unsigned        srcMaxY = srcBitmap.height() - 1;
219        unsigned        srcRB = srcBitmap.rowBytes();
220        SkFixed         fx, fy, dx, dy;
221
222        const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
223        NOFILTER_BITMAP_SHADER_PREAMBLE16(srcBitmap, srcRB);
224
225        if (this->getInverseClass() == kPerspective_MatrixClass)
226        {
227            SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
228                                    SkIntToScalar(y) + SK_ScalarHalf, count);
229            while ((count = iter.next()) != 0)
230            {
231                const SkFixed* srcXY = iter.getXY();
232
233                while (--count >= 0)
234                {
235                    fx = *srcXY++;
236                    fy = *srcXY++;
237                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
238                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
239                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
240                }
241            }
242            return;
243        }
244
245        // now init fx, fy, dx, dy
246        {
247            SkPoint srcPt;
248            invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
249                         SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
250
251            fx = SkScalarToFixed(srcPt.fX);
252            fy = SkScalarToFixed(srcPt.fY);
253
254            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
255                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
256            else
257            {
258                dx = SkScalarToFixed(inv.getScaleX());
259                dy = SkScalarToFixed(inv.getSkewY());
260            }
261        }
262
263#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
264        {   int level = this->getMipLevel() >> 16;
265            fx >>= level;
266            fy >>= level;
267            dx >>= level;
268            dy >>= level;
269        }
270#endif
271
272        if (dy == 0)
273        {
274            srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY) * srcRB);
275            do {
276                unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
277                fx += dx;
278                *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X16(srcPixels, x);
279            } while (--count != 0);
280        }
281        else    // dy != 0
282        {
283            do {
284                unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
285                unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
286                fx += dx;
287                fy += dy;
288                *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
289            } while (--count != 0);
290        }
291
292        NOFILTER_BITMAP_SHADER_POSTAMBLE16(srcBitmap);
293    }
294private:
295    typedef HasSpan16_Sampler_BitmapShader INHERITED;
296};
297
298#undef NOFILTER_BITMAP_SHADER_CLASS
299#undef NOFILTER_BITMAP_SHADER_TYPE
300#undef NOFILTER_BITMAP_SHADER_PREAMBLE
301#undef NOFILTER_BITMAP_SHADER_POSTAMBLE
302#undef NOFILTER_BITMAP_SHADER_SAMPLE_X      //(x)
303#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY     //(x, y, rowBytes)
304#undef NOFILTER_BITMAP_SHADER_TILEMODE
305#undef NOFILTER_BITMAP_SHADER_TILEPROC
306
307#undef NOFILTER_BITMAP_SHADER_PREAMBLE16
308#undef NOFILTER_BITMAP_SHADER_POSTAMBLE16
309#undef NOFILTER_BITMAP_SHADER_SAMPLE_X16        //(x)
310#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY16       //(x, y, rowBytes)
311
312#undef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
313#undef NOFILTER_BITMAP_SHADER_SPRITEPROC16
314#undef NOFILTER_BITMAP_SHADER_SPRITEPROC32
315