rsdIntrinsicBlend.cpp revision fa17cda2d7e0948677035890e40498ad0b639c92
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
32enum {
33    BLEND_CLEAR = 0,
34    BLEND_SRC = 1,
35    BLEND_DST = 2,
36    BLEND_SRC_OVER = 3,
37    BLEND_DST_OVER = 4,
38    BLEND_SRC_IN = 5,
39    BLEND_DST_IN = 6,
40    BLEND_SRC_OUT = 7,
41    BLEND_DST_OUT = 8,
42    BLEND_SRC_ATOP = 9,
43    BLEND_DST_ATOP = 10,
44    BLEND_XOR = 11,
45
46    BLEND_NORMAL = 12,
47    BLEND_AVERAGE = 13,
48    BLEND_MULTIPLY = 14,
49    BLEND_SCREEN = 15,
50    BLEND_DARKEN = 16,
51    BLEND_LIGHTEN = 17,
52    BLEND_OVERLAY = 18,
53    BLEND_HARDLIGHT = 19,
54    BLEND_SOFTLIGHT = 20,
55    BLEND_DIFFERENCE = 21,
56    BLEND_NEGATION = 22,
57    BLEND_EXCLUSION = 23,
58    BLEND_COLOR_DODGE = 24,
59    BLEND_INVERSE_COLOR_DODGE = 25,
60    BLEND_SOFT_DODGE = 26,
61    BLEND_COLOR_BURN = 27,
62    BLEND_INVERSE_COLOR_BURN = 28,
63    BLEND_SOFT_BURN = 29,
64    BLEND_REFLECT = 30,
65    BLEND_GLOW = 31,
66    BLEND_FREEZE = 32,
67    BLEND_HEAT = 33,
68    BLEND_ADD = 34,
69    BLEND_SUBTRACT = 35,
70    BLEND_STAMP = 36,
71    BLEND_RED = 37,
72    BLEND_GREEN = 38,
73    BLEND_BLUE = 39,
74    BLEND_HUE = 40,
75    BLEND_SATURATION = 41,
76    BLEND_COLOR = 42,
77    BLEND_LUMINOSITY = 43
78};
79
80extern "C" void rsdIntrinsicBlendSrcOver_K(void *dst, const void *src, uint32_t count8);
81extern "C" void rsdIntrinsicBlendDstOver_K(void *dst, const void *src, uint32_t count8);
82extern "C" void rsdIntrinsicBlendSrcIn_K(void *dst, const void *src, uint32_t count8);
83extern "C" void rsdIntrinsicBlendDstIn_K(void *dst, const void *src, uint32_t count8);
84extern "C" void rsdIntrinsicBlendSrcOut_K(void *dst, const void *src, uint32_t count8);
85extern "C" void rsdIntrinsicBlendDstOut_K(void *dst, const void *src, uint32_t count8);
86extern "C" void rsdIntrinsicBlendSrcAtop_K(void *dst, const void *src, uint32_t count8);
87extern "C" void rsdIntrinsicBlendDstAtop_K(void *dst, const void *src, uint32_t count8);
88extern "C" void rsdIntrinsicBlendXor_K(void *dst, const void *src, uint32_t count8);
89extern "C" void rsdIntrinsicBlendMultiply_K(void *dst, const void *src, uint32_t count8);
90extern "C" void rsdIntrinsicBlendAdd_K(void *dst, const void *src, uint32_t count8);
91extern "C" void rsdIntrinsicBlendSub_K(void *dst, const void *src, uint32_t count8);
92
93//#undef ARCH_ARM_HAVE_NEON
94
95static void ColorMatrix_uchar4(const RsForEachStubParamStruct *p,
96                               uint32_t xstart, uint32_t xend,
97                               uint32_t instep, uint32_t outstep) {
98    ConvolveParams *cp = (ConvolveParams *)p->usr;
99
100    // instep/outstep can be ignored--sizeof(uchar4) known at compile time
101    uchar4 *out = (uchar4 *)p->out;
102    uchar4 *in = (uchar4 *)p->in;
103    uint32_t x1 = xstart;
104    uint32_t x2 = xend;
105
106    in += xstart;
107    out += xstart;
108
109    switch (p->slot) {
110    case BLEND_CLEAR:
111        for (;x1 < x2; x1++, out++) {
112            *out = 0;
113        }
114        break;
115    case BLEND_SRC:
116        for (;x1 < x2; x1++, out++, in++) {
117          *out = *in;
118        }
119        break;
120    //BLEND_DST is a NOP
121    case BLEND_DST:
122        break;
123    case BLEND_SRC_OVER:
124#if defined(ARCH_ARM_HAVE_NEON)
125        if((x1 + 8) < x2) {
126            uint32_t len = (x2 - x1) >> 3;
127            rsdIntrinsicBlendSrcOver_K(out, in, len);
128            x1 += len << 3;
129            out += len << 3;
130            in += len << 3;
131        }
132#endif
133        for (;x1 < x2; x1++, out++, in++) {
134            short4 in_s = convert_short4(*in);
135            short4 out_s = convert_short4(*out);
136            in_s = in_s + ((out_s * (short4)(255 - in_s.a)) >> (short4)8);
137            *out = convert_uchar4(in_s);
138        }
139        break;
140    case BLEND_DST_OVER:
141#if defined(ARCH_ARM_HAVE_NEON)
142        if((x1 + 8) < x2) {
143            uint32_t len = (x2 - x1) >> 3;
144            rsdIntrinsicBlendDstOver_K(out, in, len);
145            x1 += len << 3;
146            out += len << 3;
147            in += len << 3;
148        }
149#endif
150        for (;x1 < x2; x1++, out++, in++) {
151            short4 in_s = convert_short4(*in);
152            short4 out_s = convert_short4(*out);
153            in_s = out_s + ((in_s * (short4)(255 - out_s.a)) >> (short4)8);
154            *out = convert_uchar4(in_s);
155        }
156        break;
157    case BLEND_SRC_IN:
158#if defined(ARCH_ARM_HAVE_NEON)
159        if((x1 + 8) < x2) {
160            uint32_t len = (x2 - x1) >> 3;
161            rsdIntrinsicBlendSrcIn_K(out, in, len);
162            x1 += len << 3;
163            out += len << 3;
164            in += len << 3;
165        }
166#endif
167        for (;x1 < x2; x1++, out++, in++) {
168            short4 in_s = convert_short4(*in);
169            in_s = (in_s * out->a) >> (short4)8;
170            *out = convert_uchar4(in_s);
171        }
172        break;
173    case BLEND_DST_IN:
174#if defined(ARCH_ARM_HAVE_NEON)
175        if((x1 + 8) < x2) {
176            uint32_t len = (x2 - x1) >> 3;
177            rsdIntrinsicBlendDstIn_K(out, in, len);
178            x1 += len << 3;
179            out += len << 3;
180            in += len << 3;
181        }
182#endif
183        for (;x1 < x2; x1++, out++, in++) {
184            short4 out_s = convert_short4(*out);
185            out_s = (out_s * in->a) >> (short4)8;
186            *out = convert_uchar4(out_s);
187        }
188        break;
189    case BLEND_SRC_OUT:
190#if defined(ARCH_ARM_HAVE_NEON)
191        if((x1 + 8) < x2) {
192            uint32_t len = (x2 - x1) >> 3;
193            rsdIntrinsicBlendSrcOut_K(out, in, len);
194            x1 += len << 3;
195            out += len << 3;
196            in += len << 3;
197        }
198#endif
199        for (;x1 < x2; x1++, out++, in++) {
200            short4 in_s = convert_short4(*in);
201            in_s = (in_s * (short4)(255 - out->a)) >> (short4)8;
202            *out = convert_uchar4(in_s);
203        }
204        break;
205    case BLEND_DST_OUT:
206#if defined(ARCH_ARM_HAVE_NEON)
207        if((x1 + 8) < x2) {
208            uint32_t len = (x2 - x1) >> 3;
209            rsdIntrinsicBlendDstOut_K(out, in, len);
210            x1 += len << 3;
211            out += len << 3;
212            in += len << 3;
213        }
214#endif
215        for (;x1 < x2; x1++, out++, in++) {
216            short4 out_s = convert_short4(*out);
217            out_s = (out_s * (short4)(255 - in->a)) >> (short4)8;
218            *out = convert_uchar4(out_s);
219        }
220        break;
221    case BLEND_SRC_ATOP:
222#if defined(ARCH_ARM_HAVE_NEON)
223        if((x1 + 8) < x2) {
224            uint32_t len = (x2 - x1) >> 3;
225            rsdIntrinsicBlendSrcAtop_K(out, in, len);
226            x1 += len << 3;
227            out += len << 3;
228            in += len << 3;
229        }
230#endif
231        for (;x1 < x2; x1++, out++, in++) {
232            short4 in_s = convert_short4(*in);
233            short4 out_s = convert_short4(*out);
234            out_s.rgb = ((in_s.rgb * out_s.a) +
235              (out_s.rgb * ((short3)255 - (short3)in_s.a))) >> (short3)8;
236            *out = convert_uchar4(out_s);
237        }
238        break;
239    case BLEND_DST_ATOP:
240#if defined(ARCH_ARM_HAVE_NEON)
241        if((x1 + 8) < x2) {
242            uint32_t len = (x2 - x1) >> 3;
243            rsdIntrinsicBlendDstAtop_K(out, in, len);
244            x1 += len << 3;
245            out += len << 3;
246            in += len << 3;
247        }
248#endif
249        for (;x1 < x2; x1++, out++, in++) {
250            short4 in_s = convert_short4(*in);
251            short4 out_s = convert_short4(*out);
252            out_s.rgb = ((out_s.rgb * in_s.a) +
253              (in_s.rgb * ((short3)255 - (short3)out_s.a))) >> (short3)8;
254            *out = convert_uchar4(out_s);
255        }
256        break;
257    case BLEND_XOR:
258#if defined(ARCH_ARM_HAVE_NEON)
259        if((x1 + 8) < x2) {
260            uint32_t len = (x2 - x1) >> 3;
261            rsdIntrinsicBlendXor_K(out, in, len);
262            x1 += len << 3;
263            out += len << 3;
264            in += len << 3;
265        }
266#endif
267        for (;x1 < x2; x1++, out++, in++) {
268            *out = *in ^ *out;
269        }
270        break;
271    case BLEND_NORMAL:
272        ALOGE("Called unimplemented blend intrinsic BLEND_NORMAL");
273        rsAssert(false);
274        break;
275    case BLEND_AVERAGE:
276        ALOGE("Called unimplemented blend intrinsic BLEND_AVERAGE");
277        rsAssert(false);
278        break;
279    case BLEND_MULTIPLY:
280#if defined(ARCH_ARM_HAVE_NEON)
281        if((x1 + 8) < x2) {
282            uint32_t len = (x2 - x1) >> 3;
283            rsdIntrinsicBlendMultiply_K(out, in, len);
284            x1 += len << 3;
285            out += len << 3;
286            in += len << 3;
287        }
288#endif
289        for (;x1 < x2; x1++, out++, in++) {
290          *out = convert_uchar4((convert_short4(*in) * convert_short4(*out))
291                                >> (short4)8);
292        }
293        break;
294    case BLEND_SCREEN:
295        ALOGE("Called unimplemented blend intrinsic BLEND_SCREEN");
296        rsAssert(false);
297        break;
298    case BLEND_DARKEN:
299        ALOGE("Called unimplemented blend intrinsic BLEND_DARKEN");
300        rsAssert(false);
301        break;
302    case BLEND_LIGHTEN:
303        ALOGE("Called unimplemented blend intrinsic BLEND_LIGHTEN");
304        rsAssert(false);
305        break;
306    case BLEND_OVERLAY:
307        ALOGE("Called unimplemented blend intrinsic BLEND_OVERLAY");
308        rsAssert(false);
309        break;
310    case BLEND_HARDLIGHT:
311        ALOGE("Called unimplemented blend intrinsic BLEND_HARDLIGHT");
312        rsAssert(false);
313        break;
314    case BLEND_SOFTLIGHT:
315        ALOGE("Called unimplemented blend intrinsic BLEND_SOFTLIGHT");
316        rsAssert(false);
317        break;
318    case BLEND_DIFFERENCE:
319        ALOGE("Called unimplemented blend intrinsic BLEND_DIFFERENCE");
320        rsAssert(false);
321        break;
322    case BLEND_NEGATION:
323        ALOGE("Called unimplemented blend intrinsic BLEND_NEGATION");
324        rsAssert(false);
325        break;
326    case BLEND_EXCLUSION:
327        ALOGE("Called unimplemented blend intrinsic BLEND_EXCLUSION");
328        rsAssert(false);
329        break;
330    case BLEND_COLOR_DODGE:
331        ALOGE("Called unimplemented blend intrinsic BLEND_COLOR_DODGE");
332        rsAssert(false);
333        break;
334    case BLEND_INVERSE_COLOR_DODGE:
335        ALOGE("Called unimplemented blend intrinsic BLEND_INVERSE_COLOR_DODGE");
336        rsAssert(false);
337        break;
338    case BLEND_SOFT_DODGE:
339        ALOGE("Called unimplemented blend intrinsic BLEND_SOFT_DODGE");
340        rsAssert(false);
341        break;
342    case BLEND_COLOR_BURN:
343        ALOGE("Called unimplemented blend intrinsic BLEND_COLOR_BURN");
344        rsAssert(false);
345        break;
346    case BLEND_INVERSE_COLOR_BURN:
347        ALOGE("Called unimplemented blend intrinsic BLEND_INVERSE_COLOR_BURN");
348        rsAssert(false);
349        break;
350    case BLEND_SOFT_BURN:
351        ALOGE("Called unimplemented blend intrinsic BLEND_SOFT_BURN");
352        rsAssert(false);
353        break;
354    case BLEND_REFLECT:
355        ALOGE("Called unimplemented blend intrinsic BLEND_REFLECT");
356        rsAssert(false);
357        break;
358    case BLEND_GLOW:
359        ALOGE("Called unimplemented blend intrinsic BLEND_GLOW");
360        rsAssert(false);
361        break;
362    case BLEND_FREEZE:
363        ALOGE("Called unimplemented blend intrinsic BLEND_FREEZE");
364        rsAssert(false);
365        break;
366    case BLEND_HEAT:
367        ALOGE("Called unimplemented blend intrinsic BLEND_HEAT");
368        rsAssert(false);
369        break;
370    case BLEND_ADD:
371#if defined(ARCH_ARM_HAVE_NEON)
372        if((x1 + 8) < x2) {
373            uint32_t len = (x2 - x1) >> 3;
374            rsdIntrinsicBlendAdd_K(out, in, len);
375            x1 += len << 3;
376            out += len << 3;
377            in += len << 3;
378        }
379#endif
380        for (;x1 < x2; x1++, out++, in++) {
381            uint32_t iR = in->r, iG = in->g, iB = in->b, iA = in->a,
382                oR = out->r, oG = out->g, oB = out->b, oA = out->a;
383            out->r = (oR + iR) > 255 ? 255 : oR + iR;
384            out->g = (oG + iG) > 255 ? 255 : oG + iG;
385            out->b = (oB + iB) > 255 ? 255 : oB + iB;
386            out->a = (oA + iA) > 255 ? 255 : oA + iA;
387        }
388        break;
389    case BLEND_SUBTRACT:
390#if defined(ARCH_ARM_HAVE_NEON)
391        if((x1 + 8) < x2) {
392            uint32_t len = (x2 - x1) >> 3;
393            rsdIntrinsicBlendSub_K(out, in, len);
394            x1 += len << 3;
395            out += len << 3;
396            in += len << 3;
397        }
398#endif
399        for (;x1 < x2; x1++, out++, in++) {
400            int32_t iR = in->r, iG = in->g, iB = in->b, iA = in->a,
401                oR = out->r, oG = out->g, oB = out->b, oA = out->a;
402            out->r = (oR - iR) < 0 ? 0 : oR - iR;
403            out->g = (oG - iG) < 0 ? 0 : oG - iG;
404            out->b = (oB - iB) < 0 ? 0 : oB - iB;
405            out->a = (oA - iA) < 0 ? 0 : oA - iA;
406        }
407        break;
408    case BLEND_STAMP:
409        ALOGE("Called unimplemented blend intrinsic BLEND_STAMP");
410        rsAssert(false);
411        break;
412    case BLEND_RED:
413        ALOGE("Called unimplemented blend intrinsic BLEND_RED");
414        rsAssert(false);
415        break;
416    case BLEND_GREEN:
417        ALOGE("Called unimplemented blend intrinsic BLEND_GREEN");
418        rsAssert(false);
419        break;
420    case BLEND_BLUE:
421        ALOGE("Called unimplemented blend intrinsic BLEND_BLUE");
422        rsAssert(false);
423        break;
424    case BLEND_HUE:
425        ALOGE("Called unimplemented blend intrinsic BLEND_HUE");
426        rsAssert(false);
427        break;
428    case BLEND_SATURATION:
429        ALOGE("Called unimplemented blend intrinsic BLEND_SATURATION");
430        rsAssert(false);
431        break;
432    case BLEND_COLOR:
433        ALOGE("Called unimplemented blend intrinsic BLEND_COLOR");
434        rsAssert(false);
435        break;
436    case BLEND_LUMINOSITY:
437        ALOGE("Called unimplemented blend intrinsic BLEND_LUMINOSITY");
438        rsAssert(false);
439        break;
440
441    default:
442        ALOGE("Called unimplemented value %d", p->slot);
443        rsAssert(false);
444
445    }
446}
447
448void * rsdIntrinsic_InitBlend(const android::renderscript::Context *dc,
449                              android::renderscript::Script *script,
450                              RsdIntriniscFuncs_t *funcs) {
451
452    script->mHal.info.exportedVariableCount = 0;
453    funcs->root = ColorMatrix_uchar4;
454
455    ConvolveParams *cp = (ConvolveParams *)calloc(1, sizeof(ConvolveParams));
456    return cp;
457}
458
459
460