blob: a158637b87b5b0c67786a09c3747b043f2220ca3 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/sgl/SkSpriteBlitter_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 "SkSpriteBlitter.h"
19#include "SkBlitRow.h"
20#include "SkTemplates.h"
21#include "SkUtils.h"
22#include "SkColorPriv.h"
23
24#define D16_S32A_Opaque_Pixel(dst, sc) \
25do { \
26 if (sc) { \
27 *dst = SkSrcOver32To16(sc, *dst); \
28 } \
29} while (0)
30
31static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc,
32 unsigned src_scale) {
33 uint16_t dc = *dst;
34 unsigned sa = SkGetPackedA32(sc);
35 unsigned dr, dg, db;
36
37 if (255 == sa) {
38 dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
39 dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
40 db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
41 } else {
42 unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
43 dr = (SkPacked32ToR16(sc) * src_scale +
44 SkGetPackedR16(dc) * dst_scale) >> 8;
45 dg = (SkPacked32ToG16(sc) * src_scale +
46 SkGetPackedG16(dc) * dst_scale) >> 8;
47 db = (SkPacked32ToB16(sc) * src_scale +
48 SkGetPackedB16(dc) * dst_scale) >> 8;
49 }
50 *dst = SkPackRGB16(dr, dg, db);
51}
52
53#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \
54 do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0)
55
56
57///////////////////////////////////////////////////////////////////////////////
58
59class Sprite_D16_S16_Opaque : public SkSpriteBlitter {
60public:
61 Sprite_D16_S16_Opaque(const SkBitmap& source)
62 : SkSpriteBlitter(source) {}
63
64 // overrides
65 virtual void blitRect(int x, int y, int width, int height) {
66 SK_RESTRICT uint16_t* dst = fDevice->getAddr16(x, y);
67 const SK_RESTRICT uint16_t* src = fSource->getAddr16(x - fLeft,
68 y - fTop);
69 unsigned dstRB = fDevice->rowBytes();
70 unsigned srcRB = fSource->rowBytes();
71
72 while (--height >= 0) {
73 memcpy(dst, src, width << 1);
74 dst = (uint16_t*)((char*)dst + dstRB);
75 src = (const uint16_t*)((const char*)src + srcRB);
76 }
77 }
78};
79
80#define D16_S16_Blend_Pixel(dst, sc, scale) \
81 do { \
82 uint16_t dc = *dst; \
83 *dst = SkBlendRGB16(sc, dc, scale); \
84 } while (0)
85
86#define SkSPRITE_CLASSNAME Sprite_D16_S16_Blend
87#define SkSPRITE_ARGS , uint8_t alpha
88#define SkSPRITE_FIELDS uint8_t fSrcAlpha;
89#define SkSPRITE_INIT fSrcAlpha = alpha;
90#define SkSPRITE_DST_TYPE uint16_t
91#define SkSPRITE_SRC_TYPE uint16_t
92#define SkSPRITE_DST_GETADDR getAddr16
93#define SkSPRITE_SRC_GETADDR getAddr16
94#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha255To256(fSrcAlpha);
95#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, src, scale)
96#define SkSPRITE_NEXT_ROW
97#define SkSPRITE_POSTAMBLE(srcBM)
98#include "SkSpriteBlitterTemplate.h"
99
100///////////////////////////////////////////////////////////////////////////////
101
102#define D16_S4444_Opaque(dst, sc) \
103 do { \
104 uint16_t dc = *dst; \
105 *dst = SkSrcOver4444To16(sc, dc); \
106 } while (0)
107
108#define SkSPRITE_CLASSNAME Sprite_D16_S4444_Opaque
109#define SkSPRITE_ARGS
110#define SkSPRITE_FIELDS
111#define SkSPRITE_INIT
112#define SkSPRITE_DST_TYPE uint16_t
113#define SkSPRITE_SRC_TYPE SkPMColor16
114#define SkSPRITE_DST_GETADDR getAddr16
115#define SkSPRITE_SRC_GETADDR getAddr16
116#define SkSPRITE_PREAMBLE(srcBM, x, y)
117#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Opaque(dst, src)
118#define SkSPRITE_NEXT_ROW
119#define SkSPRITE_POSTAMBLE(srcBM)
120#include "SkSpriteBlitterTemplate.h"
121
122#define D16_S4444_Blend(dst, sc, scale16) \
123 do { \
124 uint16_t dc = *dst; \
125 *dst = SkBlend4444To16(sc, dc, scale16); \
126 } while (0)
127
128
129#define SkSPRITE_CLASSNAME Sprite_D16_S4444_Blend
130#define SkSPRITE_ARGS , uint8_t alpha
131#define SkSPRITE_FIELDS uint8_t fSrcAlpha;
132#define SkSPRITE_INIT fSrcAlpha = alpha;
133#define SkSPRITE_DST_TYPE uint16_t
134#define SkSPRITE_SRC_TYPE uint16_t
135#define SkSPRITE_DST_GETADDR getAddr16
136#define SkSPRITE_SRC_GETADDR getAddr16
137#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha15To16(fSrcAlpha);
138#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Blend(dst, src, scale)
139#define SkSPRITE_NEXT_ROW
140#define SkSPRITE_POSTAMBLE(srcBM)
141#include "SkSpriteBlitterTemplate.h"
142
143///////////////////////////////////////////////////////////////////////////////
144
145#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Opaque
146#define SkSPRITE_ARGS
147#define SkSPRITE_FIELDS
148#define SkSPRITE_INIT
149#define SkSPRITE_DST_TYPE uint16_t
150#define SkSPRITE_SRC_TYPE uint8_t
151#define SkSPRITE_DST_GETADDR getAddr16
152#define SkSPRITE_SRC_GETADDR getAddr8
153#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
154#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, ctable[src])
155#define SkSPRITE_NEXT_ROW
156#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false)
157#include "SkSpriteBlitterTemplate.h"
158
159#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Blend
160#define SkSPRITE_ARGS , uint8_t alpha
161#define SkSPRITE_FIELDS uint8_t fSrcAlpha;
162#define SkSPRITE_INIT fSrcAlpha = alpha;
163#define SkSPRITE_DST_TYPE uint16_t
164#define SkSPRITE_SRC_TYPE uint8_t
165#define SkSPRITE_DST_GETADDR getAddr16
166#define SkSPRITE_SRC_GETADDR getAddr8
167#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
168#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
169#define SkSPRITE_NEXT_ROW
170#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false);
171#include "SkSpriteBlitterTemplate.h"
172
173///////////////////////////////////////////////////////////////////////////////
174
175#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Opaque
176#define SkSPRITE_ARGS
177#define SkSPRITE_FIELDS
178#define SkSPRITE_INIT
179#define SkSPRITE_DST_TYPE uint16_t
180#define SkSPRITE_SRC_TYPE uint8_t
181#define SkSPRITE_DST_GETADDR getAddr16
182#define SkSPRITE_SRC_GETADDR getAddr8
183#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache()
184#define SkSPRITE_BLIT_PIXEL(dst, src) *dst = ctable[src]
185#define SkSPRITE_NEXT_ROW
186#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache()
187#include "SkSpriteBlitterTemplate.h"
188
189#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Blend
190#define SkSPRITE_ARGS , uint8_t alpha
191#define SkSPRITE_FIELDS uint8_t fSrcAlpha;
192#define SkSPRITE_INIT fSrcAlpha = alpha;
193#define SkSPRITE_DST_TYPE uint16_t
194#define SkSPRITE_SRC_TYPE uint8_t
195#define SkSPRITE_DST_GETADDR getAddr16
196#define SkSPRITE_SRC_GETADDR getAddr8
197#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
198#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
199#define SkSPRITE_NEXT_ROW
200#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache();
201#include "SkSpriteBlitterTemplate.h"
202
203///////////////////////////////////////////////////////////////////////////////
204
205class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
206public:
207 Sprite_D16_S32_BlitRowProc(const SkBitmap& source)
208 : SkSpriteBlitter(source) {}
209
210 // overrides
211
212 virtual void setup(const SkBitmap& device, int left, int top,
213 const SkPaint& paint) {
214 this->INHERITED::setup(device, left, top, paint);
215
216 unsigned flags = 0;
217
218 if (paint.getAlpha() < 0xFF) {
219 flags |= SkBlitRow::kGlobalAlpha_Flag;
220 }
221 if (!fSource->isOpaque()) {
222 flags |= SkBlitRow::kSrcPixelAlpha_Flag;
223 }
224 if (paint.isDither()) {
225 flags |= SkBlitRow::kDither_Flag;
226 }
227 fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
228 }
229
230 virtual void blitRect(int x, int y, int width, int height) {
231 SK_RESTRICT uint16_t* dst = fDevice->getAddr16(x, y);
232 const SK_RESTRICT SkPMColor* src = fSource->getAddr32(x - fLeft,
233 y - fTop);
234 unsigned dstRB = fDevice->rowBytes();
235 unsigned srcRB = fSource->rowBytes();
236 SkBlitRow::Proc proc = fProc;
237 U8CPU alpha = fPaint->getAlpha();
238
239 while (--height >= 0) {
240 proc(dst, src, width, alpha, x, y);
241 y += 1;
242 dst = (SK_RESTRICT uint16_t*)((char*)dst + dstRB);
243 src = (const SK_RESTRICT SkPMColor*)((const char*)src + srcRB);
244 }
245 }
246
247private:
248 SkBlitRow::Proc fProc;
249
250 typedef SkSpriteBlitter INHERITED;
251};
252
253///////////////////////////////////////////////////////////////////////////////
254
255#include "SkTemplatesPriv.h"
256
257SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
258 const SkPaint& paint,
259 void* storage, size_t storageSize) {
260 if (paint.getMaskFilter() != NULL) { // may add cases for this
261 return NULL;
262 }
263 if (paint.getXfermode() != NULL) { // may add cases for this
264 return NULL;
265 }
266 if (paint.getColorFilter() != NULL) { // may add cases for this
267 return NULL;
268 }
269
270 SkSpriteBlitter* blitter = NULL;
271 unsigned alpha = paint.getAlpha();
272
273 switch (source.getConfig()) {
274 case SkBitmap::kARGB_8888_Config:
275 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc,
276 storage, storageSize, (source));
277 break;
278 case SkBitmap::kARGB_4444_Config:
279 if (255 == alpha) {
280 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque,
281 storage, storageSize, (source));
282 } else {
283 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend,
284 storage, storageSize, (source, alpha >> 4));
285 }
286 break;
287 case SkBitmap::kRGB_565_Config:
288 if (255 == alpha) {
289 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque,
290 storage, storageSize, (source));
291 } else {
292 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend,
293 storage, storageSize, (source, alpha));
294 }
295 break;
296 case SkBitmap::kIndex8_Config:
297 if (source.isOpaque()) {
298 if (255 == alpha) {
299 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque,
300 storage, storageSize, (source));
301 } else {
302 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend,
303 storage, storageSize, (source, alpha));
304 }
305 } else {
306 if (255 == alpha) {
307 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque,
308 storage, storageSize, (source));
309 } else {
310 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend,
311 storage, storageSize, (source, alpha));
312 }
313 }
314 break;
315 default:
316 break;
317 }
318 return blitter;
319}
320