Home | History | Annotate | Download | only in core
      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 
     32 class NOFILTER_BITMAP_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader {
     33 public:
     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     }
    294 private:
    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