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