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 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
rsdIntrinsic_InitBlend(const android::renderscript::Context * dc,android::renderscript::Script * script,RsdIntriniscFuncs_t * funcs)448 void * 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