Home | History | Annotate | Download | only in core
      1 /* libs/graphics/sgl/SkSpriteBlitter_ARGB32.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 "SkSpriteBlitter.h"
     19 #include "SkBlitRow.h"
     20 #include "SkColorFilter.h"
     21 #include "SkColorPriv.h"
     22 #include "SkTemplates.h"
     23 #include "SkUtils.h"
     24 #include "SkXfermode.h"
     25 
     26 ///////////////////////////////////////////////////////////////////////////////
     27 
     28 class Sprite_D32_S32 : public SkSpriteBlitter {
     29 public:
     30     Sprite_D32_S32(const SkBitmap& src, U8CPU alpha)  : INHERITED(src) {
     31         SkASSERT(src.config() == SkBitmap::kARGB_8888_Config);
     32 
     33         unsigned flags32 = 0;
     34         if (255 != alpha) {
     35             flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
     36         }
     37         if (!src.isOpaque()) {
     38             flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
     39         }
     40 
     41         fProc32 = SkBlitRow::Factory32(flags32);
     42         fAlpha = alpha;
     43     }
     44 
     45     virtual void blitRect(int x, int y, int width, int height) {
     46         SkASSERT(width > 0 && height > 0);
     47         SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y);
     48         const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft,
     49                                                              y - fTop);
     50         size_t dstRB = fDevice->rowBytes();
     51         size_t srcRB = fSource->rowBytes();
     52         SkBlitRow::Proc32 proc = fProc32;
     53         U8CPU             alpha = fAlpha;
     54 
     55         do {
     56             proc(dst, src, width, alpha);
     57             dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB);
     58             src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB);
     59         } while (--height != 0);
     60     }
     61 
     62 private:
     63     SkBlitRow::Proc32   fProc32;
     64     U8CPU               fAlpha;
     65 
     66     typedef SkSpriteBlitter INHERITED;
     67 };
     68 
     69 ///////////////////////////////////////////////////////////////////////////////
     70 
     71 class Sprite_D32_XferFilter : public SkSpriteBlitter {
     72 public:
     73     Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint)
     74         : SkSpriteBlitter(source) {
     75         fColorFilter = paint.getColorFilter();
     76         SkSafeRef(fColorFilter);
     77 
     78         fXfermode = paint.getXfermode();
     79         SkSafeRef(fXfermode);
     80 
     81         fBufferSize = 0;
     82         fBuffer = NULL;
     83 
     84         unsigned flags32 = 0;
     85         if (255 != paint.getAlpha()) {
     86             flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
     87         }
     88         if (!source.isOpaque()) {
     89             flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
     90         }
     91 
     92         fProc32 = SkBlitRow::Factory32(flags32);
     93         fAlpha = paint.getAlpha();
     94     }
     95 
     96     virtual ~Sprite_D32_XferFilter() {
     97         delete[] fBuffer;
     98         SkSafeUnref(fXfermode);
     99         SkSafeUnref(fColorFilter);
    100     }
    101 
    102     virtual void setup(const SkBitmap& device, int left, int top,
    103                        const SkPaint& paint) {
    104         this->INHERITED::setup(device, left, top, paint);
    105 
    106         int width = device.width();
    107         if (width > fBufferSize) {
    108             fBufferSize = width;
    109             delete[] fBuffer;
    110             fBuffer = new SkPMColor[width];
    111         }
    112     }
    113 
    114 protected:
    115     SkColorFilter*      fColorFilter;
    116     SkXfermode*         fXfermode;
    117     int                 fBufferSize;
    118     SkPMColor*          fBuffer;
    119     SkBlitRow::Proc32   fProc32;
    120     U8CPU               fAlpha;
    121 
    122 private:
    123     typedef SkSpriteBlitter INHERITED;
    124 };
    125 
    126 ///////////////////////////////////////////////////////////////////////////////
    127 
    128 class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
    129 public:
    130     Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint)
    131         : Sprite_D32_XferFilter(source, paint) {}
    132 
    133     virtual void blitRect(int x, int y, int width, int height) {
    134         SkASSERT(width > 0 && height > 0);
    135         SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y);
    136         const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft,
    137                                                              y - fTop);
    138         unsigned dstRB = fDevice->rowBytes();
    139         unsigned srcRB = fSource->rowBytes();
    140         SkColorFilter* colorFilter = fColorFilter;
    141         SkXfermode* xfermode = fXfermode;
    142 
    143         do {
    144             const SkPMColor* tmp = src;
    145 
    146             if (NULL != colorFilter) {
    147                 colorFilter->filterSpan(src, width, fBuffer);
    148                 tmp = fBuffer;
    149             }
    150 
    151             if (NULL != xfermode) {
    152                 xfermode->xfer32(dst, tmp, width, NULL);
    153             } else {
    154                 fProc32(dst, tmp, width, fAlpha);
    155             }
    156 
    157             dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB);
    158             src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB);
    159         } while (--height != 0);
    160     }
    161 
    162 private:
    163     typedef Sprite_D32_XferFilter INHERITED;
    164 };
    165 
    166 static void fillbuffer(SK_RESTRICT SkPMColor dst[],
    167                        const SK_RESTRICT SkPMColor16 src[], int count) {
    168     SkASSERT(count > 0);
    169 
    170     do {
    171         *dst++ = SkPixel4444ToPixel32(*src++);
    172     } while (--count != 0);
    173 }
    174 
    175 class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
    176 public:
    177     Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint)
    178         : Sprite_D32_XferFilter(source, paint) {}
    179 
    180     virtual void blitRect(int x, int y, int width, int height) {
    181         SkASSERT(width > 0 && height > 0);
    182         SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
    183         const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
    184                                                                 y - fTop);
    185         unsigned dstRB = fDevice->rowBytes();
    186         unsigned srcRB = fSource->rowBytes();
    187         SK_RESTRICT SkPMColor* buffer = fBuffer;
    188         SkColorFilter* colorFilter = fColorFilter;
    189         SkXfermode* xfermode = fXfermode;
    190 
    191         do {
    192             fillbuffer(buffer, src, width);
    193 
    194             if (NULL != colorFilter) {
    195                 colorFilter->filterSpan(buffer, width, buffer);
    196             }
    197             if (NULL != xfermode) {
    198                 xfermode->xfer32(dst, buffer, width, NULL);
    199             } else {
    200                 fProc32(dst, buffer, width, fAlpha);
    201             }
    202 
    203             dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
    204             src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
    205         } while (--height != 0);
    206     }
    207 
    208 private:
    209     typedef Sprite_D32_XferFilter INHERITED;
    210 };
    211 
    212 ///////////////////////////////////////////////////////////////////////////////
    213 
    214 static void src_row(SK_RESTRICT SkPMColor dst[],
    215                     const SK_RESTRICT SkPMColor16 src[], int count) {
    216     do {
    217         *dst = SkPixel4444ToPixel32(*src);
    218         src += 1;
    219         dst += 1;
    220     } while (--count != 0);
    221 }
    222 
    223 class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
    224 public:
    225     Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {}
    226 
    227     virtual void blitRect(int x, int y, int width, int height) {
    228         SkASSERT(width > 0 && height > 0);
    229         SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
    230         const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
    231                                                                 y - fTop);
    232         unsigned dstRB = fDevice->rowBytes();
    233         unsigned srcRB = fSource->rowBytes();
    234 
    235         do {
    236             src_row(dst, src, width);
    237             dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
    238             src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
    239         } while (--height != 0);
    240     }
    241 };
    242 
    243 static void srcover_row(SK_RESTRICT SkPMColor dst[],
    244                         const SK_RESTRICT SkPMColor16 src[], int count) {
    245     do {
    246         *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
    247         src += 1;
    248         dst += 1;
    249     } while (--count != 0);
    250 }
    251 
    252 class Sprite_D32_S4444 : public SkSpriteBlitter {
    253 public:
    254     Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {}
    255 
    256     virtual void blitRect(int x, int y, int width, int height) {
    257         SkASSERT(width > 0 && height > 0);
    258         SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
    259         const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
    260                                                                 y - fTop);
    261         unsigned dstRB = fDevice->rowBytes();
    262         unsigned srcRB = fSource->rowBytes();
    263 
    264         do {
    265             srcover_row(dst, src, width);
    266             dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
    267             src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
    268         } while (--height != 0);
    269     }
    270 };
    271 
    272 ///////////////////////////////////////////////////////////////////////////////
    273 
    274 #include "SkTemplatesPriv.h"
    275 
    276 SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
    277                                             const SkPaint& paint,
    278                                             void* storage, size_t storageSize) {
    279     if (paint.getMaskFilter() != NULL) {
    280         return NULL;
    281     }
    282 
    283     U8CPU       alpha = paint.getAlpha();
    284     SkXfermode* xfermode = paint.getXfermode();
    285     SkColorFilter* filter = paint.getColorFilter();
    286     SkSpriteBlitter* blitter = NULL;
    287 
    288     switch (source.getConfig()) {
    289         case SkBitmap::kARGB_4444_Config:
    290             if (alpha != 0xFF) {
    291                 return NULL;    // we only have opaque sprites
    292             }
    293             if (xfermode || filter) {
    294                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter,
    295                                       storage, storageSize, (source, paint));
    296             } else if (source.isOpaque()) {
    297                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque,
    298                                       storage, storageSize, (source));
    299             } else {
    300                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444,
    301                                       storage, storageSize, (source));
    302             }
    303             break;
    304         case SkBitmap::kARGB_8888_Config:
    305             if (xfermode || filter) {
    306                 if (255 == alpha) {
    307                     // this can handle xfermode or filter, but not alpha
    308                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter,
    309                                       storage, storageSize, (source, paint));
    310                 }
    311             } else {
    312                 // this can handle alpha, but not xfermode or filter
    313                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32,
    314                               storage, storageSize, (source, alpha));
    315             }
    316             break;
    317         default:
    318             break;
    319     }
    320     return blitter;
    321 }
    322 
    323