rsdIntrinsicBlend.cpp revision 36889a0ecf564e3d47e7f69bb030c6b927061792
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#include "rsdCore.h"
19#include "rsdIntrinsics.h"
20#include "rsdAllocation.h"
21
22#include "rsdIntrinsicInlines.h"
23
24using namespace android;
25using namespace android::renderscript;
26
27struct ConvolveParams {
28    float f[4];
29};
30
31
32static void One(const RsForEachStubParamStruct *p, uchar4 *out,
33                const uchar4 *py, const float* coeff) {
34    float4 i = convert_float4(py[0]);
35
36    float4 sum;
37    sum.x = i.x * coeff[0] +
38            i.y * coeff[4] +
39            i.z * coeff[8] +
40            i.w * coeff[12];
41    sum.y = i.x * coeff[1] +
42            i.y * coeff[5] +
43            i.z * coeff[9] +
44            i.w * coeff[13];
45    sum.z = i.x * coeff[2] +
46            i.y * coeff[6] +
47            i.z * coeff[10] +
48            i.w * coeff[14];
49    sum.w = i.x * coeff[3] +
50            i.y * coeff[7] +
51            i.z * coeff[11] +
52            i.w * coeff[15];
53
54    sum.x = sum.x < 0 ? 0 : (sum.x > 255 ? 255 : sum.x);
55    sum.y = sum.y < 0 ? 0 : (sum.y > 255 ? 255 : sum.y);
56    sum.z = sum.z < 0 ? 0 : (sum.z > 255 ? 255 : sum.z);
57    sum.w = sum.w < 0 ? 0 : (sum.w > 255 ? 255 : sum.w);
58
59    *out = convert_uchar4(sum);
60}
61
62enum {
63    BLEND_CLEAR = 0,
64    BLEND_SRC = 1,
65    BLEND_DST = 2,
66    BLEND_SRC_OVER = 3,
67    BLEND_DST_OVER = 4,
68    BLEND_SRC_IN = 5,
69    BLEND_DST_IN = 6,
70    BLEND_SRC_OUT = 7,
71    BLEND_DST_OUT = 8,
72    BLEND_SRC_ATOP = 9,
73    BLEND_DST_ATOP = 10,
74    BLEND_XOR = 11,
75
76    BLEND_NORMAL = 12,
77    BLEND_AVERAGE = 13,
78    BLEND_MULTIPLY = 14,
79    BLEND_SCREEN = 15,
80    BLEND_DARKEN = 16,
81    BLEND_LIGHTEN = 17,
82    BLEND_OVERLAY = 18,
83    BLEND_HARDLIGHT = 19,
84    BLEND_SOFTLIGHT = 20,
85    BLEND_DIFFERENCE = 21,
86    BLEND_NEGATION = 22,
87    BLEND_EXCLUSION = 23,
88    BLEND_COLOR_DODGE = 24,
89    BLEND_INVERSE_COLOR_DODGE = 25,
90    BLEND_SOFT_DODGE = 26,
91    BLEND_COLOR_BURN = 27,
92    BLEND_INVERSE_COLOR_BURN = 28,
93    BLEND_SOFT_BURN = 29,
94    BLEND_REFLECT = 30,
95    BLEND_GLOW = 31,
96    BLEND_FREEZE = 32,
97    BLEND_HEAT = 33,
98    BLEND_ADD = 34,
99    BLEND_SUBTRACT = 35,
100    BLEND_STAMP = 36,
101    BLEND_RED = 37,
102    BLEND_GREEN = 38,
103    BLEND_BLUE = 39,
104    BLEND_HUE = 40,
105    BLEND_SATURATION = 41,
106    BLEND_COLOR = 42,
107    BLEND_LUMINOSITY = 43
108};
109
110static void ColorMatrix_uchar4(const RsForEachStubParamStruct *p,
111                               uint32_t xstart, uint32_t xend,
112                               uint32_t instep, uint32_t outstep) {
113    ConvolveParams *cp = (ConvolveParams *)p->usr;
114
115    // instep/outstep can be ignored--sizeof(uchar4) known at compile time
116    uchar4 *out = (uchar4 *)p->out;
117    uchar4 *in = (uchar4 *)p->in;
118    uint32_t x1 = xstart;
119    uint32_t x2 = xend;
120
121    in += xstart;
122    out += xstart;
123
124    switch (p->slot) {
125    case BLEND_CLEAR:
126        for (;x1 < x2; x1++, out++) {
127            *out = 0;
128        }
129        break;
130    case BLEND_SRC:
131        for (;x1 < x2; x1++, out++, in++) {
132          *out = *in;
133        }
134        break;
135    //BLEND_DST is a NOP
136    case BLEND_DST:
137        break;
138    case BLEND_SRC_OVER:
139        for (;x1 < x2; x1++, out++, in++) {
140            short4 in_s = convert_short4(*in);
141            short4 out_s = convert_short4(*out);
142            in_s = in_s + ((out_s * (short4)(255 - in_s.a)) >> (short4)8);
143            *out = convert_uchar4(in_s);
144        }
145        break;
146    case BLEND_DST_OVER:
147        for (;x1 < x2; x1++, out++, in++) {
148            short4 in_s = convert_short4(*in);
149            short4 out_s = convert_short4(*out);
150            in_s = out_s + ((in_s * (short4)(255 - out_s.a)) >> (short4)8);
151            *out = convert_uchar4(in_s);
152        }
153        break;
154    case BLEND_SRC_IN:
155        for (;x1 < x2; x1++, out++, in++) {
156            short4 in_s = convert_short4(*in);
157            in_s = (in_s * out->a) >> (short4)8;
158            *out = convert_uchar4(in_s);
159        }
160        break;
161    case BLEND_DST_IN:
162        for (;x1 < x2; x1++, out++, in++) {
163            short4 out_s = convert_short4(*out);
164            out_s = (out_s * in->a) >> (short4)8;
165            *out = convert_uchar4(out_s);
166        }
167        break;
168    case BLEND_SRC_OUT:
169        for (;x1 < x2; x1++, out++, in++) {
170            short4 in_s = convert_short4(*in);
171            in_s = (in_s * (short4)(255 - out->a)) >> (short4)8;
172            *out = convert_uchar4(in_s);
173        }
174        break;
175    case BLEND_DST_OUT:
176        for (;x1 < x2; x1++, out++, in++) {
177            short4 out_s = convert_short4(*out);
178            out_s = (out_s * (short4)(255 - in->a)) >> (short4)8;
179            *out = convert_uchar4(out_s);
180        }
181        break;
182    case BLEND_SRC_ATOP:
183        for (;x1 < x2; x1++, out++, in++) {
184            short4 in_s = convert_short4(*in);
185            short4 out_s = convert_short4(*out);
186            out_s.rgb = ((in_s.rgb * out_s.a) >> (short3)8) +
187              ((out_s.rgb * ((short3)255 - (short3)in_s.a)) >> (short3)8);
188            *out = convert_uchar4(out_s);
189        }
190        break;
191    case BLEND_DST_ATOP:
192        for (;x1 < x2; x1++, out++, in++) {
193            short4 in_s = convert_short4(*in);
194            short4 out_s = convert_short4(*out);
195            out_s.rgb = ((out_s.rgb * in_s.a) >> (short3)8) +
196              ((in_s.rgb * ((short3)255 - (short3)out_s.a)) >> (short3)8);
197            *out = convert_uchar4(out_s);
198        }
199        break;
200    case BLEND_XOR:
201        for (;x1 < x2; x1++, out++, in++) {
202            *out = *in ^ *out;
203        }
204        break;
205    case BLEND_NORMAL:
206        ALOGE("Called unimplemented blend intrinsic BLEND_NORMAL");
207        rsAssert(false);
208        break;
209    case BLEND_AVERAGE:
210        ALOGE("Called unimplemented blend intrinsic BLEND_AVERAGE");
211        rsAssert(false);
212        break;
213    case BLEND_MULTIPLY:
214        for (;x1 < x2; x1++, out++, in++) {
215          *out = convert_uchar4((convert_short4(*in) * convert_short4(*out))
216                                >> (short4)8);
217        }
218        break;
219    case BLEND_SCREEN:
220        ALOGE("Called unimplemented blend intrinsic BLEND_SCREEN");
221        rsAssert(false);
222        break;
223    case BLEND_DARKEN:
224        ALOGE("Called unimplemented blend intrinsic BLEND_DARKEN");
225        rsAssert(false);
226        break;
227    case BLEND_LIGHTEN:
228        ALOGE("Called unimplemented blend intrinsic BLEND_LIGHTEN");
229        rsAssert(false);
230        break;
231    case BLEND_OVERLAY:
232        ALOGE("Called unimplemented blend intrinsic BLEND_OVERLAY");
233        rsAssert(false);
234        break;
235    case BLEND_HARDLIGHT:
236        ALOGE("Called unimplemented blend intrinsic BLEND_HARDLIGHT");
237        rsAssert(false);
238        break;
239    case BLEND_SOFTLIGHT:
240        ALOGE("Called unimplemented blend intrinsic BLEND_SOFTLIGHT");
241        rsAssert(false);
242        break;
243    case BLEND_DIFFERENCE:
244        ALOGE("Called unimplemented blend intrinsic BLEND_DIFFERENCE");
245        rsAssert(false);
246        break;
247    case BLEND_NEGATION:
248        ALOGE("Called unimplemented blend intrinsic BLEND_NEGATION");
249        rsAssert(false);
250        break;
251    case BLEND_EXCLUSION:
252        ALOGE("Called unimplemented blend intrinsic BLEND_EXCLUSION");
253        rsAssert(false);
254        break;
255    case BLEND_COLOR_DODGE:
256        ALOGE("Called unimplemented blend intrinsic BLEND_COLOR_DODGE");
257        rsAssert(false);
258        break;
259    case BLEND_INVERSE_COLOR_DODGE:
260        ALOGE("Called unimplemented blend intrinsic BLEND_INVERSE_COLOR_DODGE");
261        rsAssert(false);
262        break;
263    case BLEND_SOFT_DODGE:
264        ALOGE("Called unimplemented blend intrinsic BLEND_SOFT_DODGE");
265        rsAssert(false);
266        break;
267    case BLEND_COLOR_BURN:
268        ALOGE("Called unimplemented blend intrinsic BLEND_COLOR_BURN");
269        rsAssert(false);
270        break;
271    case BLEND_INVERSE_COLOR_BURN:
272        ALOGE("Called unimplemented blend intrinsic BLEND_INVERSE_COLOR_BURN");
273        rsAssert(false);
274        break;
275    case BLEND_SOFT_BURN:
276        ALOGE("Called unimplemented blend intrinsic BLEND_SOFT_BURN");
277        rsAssert(false);
278        break;
279    case BLEND_REFLECT:
280        ALOGE("Called unimplemented blend intrinsic BLEND_REFLECT");
281        rsAssert(false);
282        break;
283    case BLEND_GLOW:
284        ALOGE("Called unimplemented blend intrinsic BLEND_GLOW");
285        rsAssert(false);
286        break;
287    case BLEND_FREEZE:
288        ALOGE("Called unimplemented blend intrinsic BLEND_FREEZE");
289        rsAssert(false);
290        break;
291    case BLEND_HEAT:
292        ALOGE("Called unimplemented blend intrinsic BLEND_HEAT");
293        rsAssert(false);
294        break;
295    case BLEND_ADD:
296        for (;x1 < x2; x1++, out++, in++) {
297            uint32_t iR = in->r, iG = in->g, iB = in->b, iA = in->a,
298                oR = out->r, oG = out->g, oB = out->b, oA = out->a;
299            out->r = (oR + iR) > 255 ? 255 : oR + iR;
300            out->g = (oG + iG) > 255 ? 255 : oG + iG;
301            out->b = (oB + iB) > 255 ? 255 : oB + iB;
302            out->a = (oA + iA) > 255 ? 255 : oA + iA;
303        }
304        break;
305    case BLEND_SUBTRACT:
306        for (;x1 < x2; x1++, out++, in++) {
307            int32_t iR = in->r, iG = in->g, iB = in->b, iA = in->a,
308                oR = out->r, oG = out->g, oB = out->b, oA = out->a;
309            out->r = (oR - iR) < 0 ? 0 : oR - iR;
310            out->g = (oG - iG) < 0 ? 0 : oG - iG;
311            out->b = (oB - iB) < 0 ? 0 : oB - iB;
312            out->a = (oA - iA) < 0 ? 0 : oA - iA;
313        }
314        break;
315    case BLEND_STAMP:
316        ALOGE("Called unimplemented blend intrinsic BLEND_STAMP");
317        rsAssert(false);
318        break;
319    case BLEND_RED:
320        ALOGE("Called unimplemented blend intrinsic BLEND_RED");
321        rsAssert(false);
322        break;
323    case BLEND_GREEN:
324        ALOGE("Called unimplemented blend intrinsic BLEND_GREEN");
325        rsAssert(false);
326        break;
327    case BLEND_BLUE:
328        ALOGE("Called unimplemented blend intrinsic BLEND_BLUE");
329        rsAssert(false);
330        break;
331    case BLEND_HUE:
332        ALOGE("Called unimplemented blend intrinsic BLEND_HUE");
333        rsAssert(false);
334        break;
335    case BLEND_SATURATION:
336        ALOGE("Called unimplemented blend intrinsic BLEND_SATURATION");
337        rsAssert(false);
338        break;
339    case BLEND_COLOR:
340        ALOGE("Called unimplemented blend intrinsic BLEND_COLOR");
341        rsAssert(false);
342        break;
343    case BLEND_LUMINOSITY:
344        ALOGE("Called unimplemented blend intrinsic BLEND_LUMINOSITY");
345        rsAssert(false);
346        break;
347
348    default:
349        ALOGE("Called unimplemented value %d", p->slot);
350        rsAssert(false);
351
352    }
353
354    if(x2 > x1) {
355        while(x1 != x2) {
356            One(p, out++, in++, cp->f);
357            x1++;
358        }
359    }
360}
361
362void * rsdIntrinsic_InitBlend(const android::renderscript::Context *dc,
363                              android::renderscript::Script *script,
364                              RsdIntriniscFuncs_t *funcs) {
365
366    script->mHal.info.exportedVariableCount = 0;
367    funcs->root = ColorMatrix_uchar4;
368
369    ConvolveParams *cp = (ConvolveParams *)calloc(1, sizeof(ConvolveParams));
370    return cp;
371}
372
373
374