1 /*
2 * Copyright (C) 2008-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 #include <malloc.h>
18
19 #include "RenderScript.h"
20 #include "rsCppInternal.h"
21
22 using namespace android;
23 using namespace RSC;
24
ScriptIntrinsic(sp<RS> rs,int id,sp<const Element> e)25 ScriptIntrinsic::ScriptIntrinsic(sp<RS> rs, int id, sp<const Element> e)
26 : Script(nullptr, rs) {
27 mID = createDispatch(rs, RS::dispatch->ScriptIntrinsicCreate(rs->getContext(), id,
28 e != nullptr ? e->getID() : 0));
29 mElement = e;
30 }
31
~ScriptIntrinsic()32 ScriptIntrinsic::~ScriptIntrinsic() {
33
34 }
35
create(sp<RS> rs,sp<const Element> e)36 sp<ScriptIntrinsic3DLUT> ScriptIntrinsic3DLUT::create(sp<RS> rs, sp<const Element> e) {
37 if (e->isCompatible(Element::U8_4(rs)) == false) {
38 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic");
39 return nullptr;
40 }
41 return new ScriptIntrinsic3DLUT(rs, e);
42 }
43
ScriptIntrinsic3DLUT(sp<RS> rs,sp<const Element> e)44 ScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e)
45 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_3DLUT, e) {
46
47 }
forEach(sp<Allocation> ain,sp<Allocation> aout)48 void ScriptIntrinsic3DLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) {
49 if (ain->getType()->getElement()->isCompatible(mElement) == false ||
50 aout->getType()->getElement()->isCompatible(mElement) == false) {
51 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "3DLUT forEach element mismatch");
52 return;
53 }
54 Script::forEach(0, ain, aout, nullptr, 0);
55 }
setLUT(sp<Allocation> lut)56 void ScriptIntrinsic3DLUT::setLUT(sp<Allocation> lut) {
57 sp<const Type> t = lut->getType();
58 if (!t->getElement()->isCompatible(mElement)) {
59 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "setLUT element does not match");
60 return;
61 }
62 if (t->getZ() == 0) {
63 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "setLUT Allocation must be 3D");
64 return;
65 }
66
67 Script::setVar(0, lut);
68 }
69
create(sp<RS> rs,sp<const Element> e)70 sp<ScriptIntrinsicBlend> ScriptIntrinsicBlend::create(sp<RS> rs, sp<const Element> e) {
71 if (e->isCompatible(Element::U8_4(rs)) == false) {
72 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic");
73 return nullptr;
74 }
75 return new ScriptIntrinsicBlend(rs, e);
76 }
77
ScriptIntrinsicBlend(sp<RS> rs,sp<const Element> e)78 ScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e)
79 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLEND, e) {
80 }
81
forEachClear(sp<Allocation> in,sp<Allocation> out)82 void ScriptIntrinsicBlend::forEachClear(sp<Allocation> in, sp<Allocation> out) {
83 if (in->getType()->getElement()->isCompatible(mElement) == false ||
84 out->getType()->getElement()->isCompatible(mElement) == false) {
85 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
86 }
87 Script::forEach(0, in, out, nullptr, 0);
88 }
89
forEachSrc(sp<Allocation> in,sp<Allocation> out)90 void ScriptIntrinsicBlend::forEachSrc(sp<Allocation> in, sp<Allocation> out) {
91 if (in->getType()->getElement()->isCompatible(mElement) == false ||
92 out->getType()->getElement()->isCompatible(mElement) == false) {
93 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
94 }
95 Script::forEach(1, in, out, nullptr, 0);
96 }
97
forEachDst(sp<Allocation> in,sp<Allocation> out)98 void ScriptIntrinsicBlend::forEachDst(sp<Allocation> in, sp<Allocation> out) {
99 if (in->getType()->getElement()->isCompatible(mElement) == false ||
100 out->getType()->getElement()->isCompatible(mElement) == false) {
101 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
102 }
103 Script::forEach(2, in, out, nullptr, 0);
104 }
105
forEachSrcOver(sp<Allocation> in,sp<Allocation> out)106 void ScriptIntrinsicBlend::forEachSrcOver(sp<Allocation> in, sp<Allocation> out) {
107 if (in->getType()->getElement()->isCompatible(mElement) == false ||
108 out->getType()->getElement()->isCompatible(mElement) == false) {
109 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
110 }
111 Script::forEach(3, in, out, nullptr, 0);
112 }
113
forEachDstOver(sp<Allocation> in,sp<Allocation> out)114 void ScriptIntrinsicBlend::forEachDstOver(sp<Allocation> in, sp<Allocation> out) {
115 if (in->getType()->getElement()->isCompatible(mElement) == false ||
116 out->getType()->getElement()->isCompatible(mElement) == false) {
117 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
118 }
119 Script::forEach(4, in, out, nullptr, 0);
120 }
121
forEachSrcIn(sp<Allocation> in,sp<Allocation> out)122 void ScriptIntrinsicBlend::forEachSrcIn(sp<Allocation> in, sp<Allocation> out) {
123 if (in->getType()->getElement()->isCompatible(mElement) == false ||
124 out->getType()->getElement()->isCompatible(mElement) == false) {
125 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
126 }
127 Script::forEach(5, in, out, nullptr, 0);
128 }
129
forEachDstIn(sp<Allocation> in,sp<Allocation> out)130 void ScriptIntrinsicBlend::forEachDstIn(sp<Allocation> in, sp<Allocation> out) {
131 if (in->getType()->getElement()->isCompatible(mElement) == false ||
132 out->getType()->getElement()->isCompatible(mElement) == false) {
133 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
134 }
135 Script::forEach(6, in, out, nullptr, 0);
136 }
137
forEachSrcOut(sp<Allocation> in,sp<Allocation> out)138 void ScriptIntrinsicBlend::forEachSrcOut(sp<Allocation> in, sp<Allocation> out) {
139 if (in->getType()->getElement()->isCompatible(mElement) == false ||
140 out->getType()->getElement()->isCompatible(mElement) == false) {
141 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
142 }
143 Script::forEach(7, in, out, nullptr, 0);
144 }
145
forEachDstOut(sp<Allocation> in,sp<Allocation> out)146 void ScriptIntrinsicBlend::forEachDstOut(sp<Allocation> in, sp<Allocation> out) {
147 if (in->getType()->getElement()->isCompatible(mElement) == false ||
148 out->getType()->getElement()->isCompatible(mElement) == false) {
149 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
150 }
151 Script::forEach(8, in, out, nullptr, 0);
152 }
153
forEachSrcAtop(sp<Allocation> in,sp<Allocation> out)154 void ScriptIntrinsicBlend::forEachSrcAtop(sp<Allocation> in, sp<Allocation> out) {
155 if (in->getType()->getElement()->isCompatible(mElement) == false ||
156 out->getType()->getElement()->isCompatible(mElement) == false) {
157 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
158 }
159 Script::forEach(9, in, out, nullptr, 0);
160 }
161
forEachDstAtop(sp<Allocation> in,sp<Allocation> out)162 void ScriptIntrinsicBlend::forEachDstAtop(sp<Allocation> in, sp<Allocation> out) {
163 if (in->getType()->getElement()->isCompatible(mElement) == false ||
164 out->getType()->getElement()->isCompatible(mElement) == false) {
165 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
166 }
167 Script::forEach(10, in, out, nullptr, 0);
168 }
169
forEachXor(sp<Allocation> in,sp<Allocation> out)170 void ScriptIntrinsicBlend::forEachXor(sp<Allocation> in, sp<Allocation> out) {
171 if (in->getType()->getElement()->isCompatible(mElement) == false ||
172 out->getType()->getElement()->isCompatible(mElement) == false) {
173 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
174 }
175 Script::forEach(11, in, out, nullptr, 0);
176 }
177
forEachMultiply(sp<Allocation> in,sp<Allocation> out)178 void ScriptIntrinsicBlend::forEachMultiply(sp<Allocation> in, sp<Allocation> out) {
179 if (in->getType()->getElement()->isCompatible(mElement) == false ||
180 out->getType()->getElement()->isCompatible(mElement) == false) {
181 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
182 }
183 Script::forEach(14, in, out, nullptr, 0);
184 }
185
forEachAdd(sp<Allocation> in,sp<Allocation> out)186 void ScriptIntrinsicBlend::forEachAdd(sp<Allocation> in, sp<Allocation> out) {
187 if (in->getType()->getElement()->isCompatible(mElement) == false ||
188 out->getType()->getElement()->isCompatible(mElement) == false) {
189 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
190 }
191 Script::forEach(34, in, out, nullptr, 0);
192 }
193
forEachSubtract(sp<Allocation> in,sp<Allocation> out)194 void ScriptIntrinsicBlend::forEachSubtract(sp<Allocation> in, sp<Allocation> out) {
195 if (in->getType()->getElement()->isCompatible(mElement) == false ||
196 out->getType()->getElement()->isCompatible(mElement) == false) {
197 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
198 }
199 Script::forEach(35, in, out, nullptr, 0);
200 }
201
202
203
204
create(sp<RS> rs,sp<const Element> e)205 sp<ScriptIntrinsicBlur> ScriptIntrinsicBlur::create(sp<RS> rs, sp<const Element> e) {
206 if ((e->isCompatible(Element::U8_4(rs)) == false) &&
207 (e->isCompatible(Element::U8(rs)) == false)) {
208 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur");
209 return nullptr;
210 }
211 return new ScriptIntrinsicBlur(rs, e);
212 }
213
ScriptIntrinsicBlur(sp<RS> rs,sp<const Element> e)214 ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e)
215 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLUR, e) {
216
217 }
218
setInput(sp<Allocation> in)219 void ScriptIntrinsicBlur::setInput(sp<Allocation> in) {
220 if (in->getType()->getElement()->isCompatible(mElement) == false) {
221 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur input");
222 return;
223 }
224 Script::setVar(1, in);
225 }
226
forEach(sp<Allocation> out)227 void ScriptIntrinsicBlur::forEach(sp<Allocation> out) {
228 if (out->getType()->getElement()->isCompatible(mElement) == false) {
229 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur output");
230 return;
231 }
232 Script::forEach(0, nullptr, out, nullptr, 0);
233 }
234
setRadius(float radius)235 void ScriptIntrinsicBlur::setRadius(float radius) {
236 if (radius > 0.f && radius <= 25.f) {
237 Script::setVar(0, &radius, sizeof(float));
238 } else {
239 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Blur radius out of 0-25 pixel bound");
240 }
241 }
242
243
244
create(sp<RS> rs)245 sp<ScriptIntrinsicColorMatrix> ScriptIntrinsicColorMatrix::create(sp<RS> rs) {
246 return new ScriptIntrinsicColorMatrix(rs, Element::RGBA_8888(rs));
247 }
248
ScriptIntrinsicColorMatrix(sp<RS> rs,sp<const Element> e)249 ScriptIntrinsicColorMatrix::ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Element> e)
250 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_COLOR_MATRIX, e) {
251 float add[4] = {0.f, 0.f, 0.f, 0.f};
252 setAdd(add);
253
254 }
255
forEach(sp<Allocation> in,sp<Allocation> out)256 void ScriptIntrinsicColorMatrix::forEach(sp<Allocation> in, sp<Allocation> out) {
257 if (!(in->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
258 !(in->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
259 !(in->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
260 !(in->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
261 !(in->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
262 !(in->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
263 !(in->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
264 !(in->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
265 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix");
266 return;
267 }
268
269 if (!(out->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
270 !(out->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
271 !(out->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
272 !(out->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
273 !(out->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
274 !(out->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
275 !(out->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
276 !(out->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
277 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix");
278 return;
279 }
280
281 Script::forEach(0, in, out, nullptr, 0);
282 }
283
setAdd(float * add)284 void ScriptIntrinsicColorMatrix::setAdd(float* add) {
285 Script::setVar(1, (void*)add, sizeof(float) * 4);
286 }
287
setColorMatrix3(float * m)288 void ScriptIntrinsicColorMatrix::setColorMatrix3(float* m) {
289 float temp[16];
290 temp[0] = m[0];
291 temp[1] = m[1];
292 temp[2] = m[2];
293 temp[3] = 0.f;
294
295 temp[4] = m[3];
296 temp[5] = m[4];
297 temp[6] = m[5];
298 temp[7] = 0.f;
299
300 temp[8] = m[6];
301 temp[9] = m[7];
302 temp[10] = m[8];
303 temp[11] = 0.f;
304
305 temp[12] = 0.f;
306 temp[13] = 0.f;
307 temp[14] = 0.f;
308 temp[15] = 1.f;
309
310 setColorMatrix4(temp);
311 }
312
313
setColorMatrix4(float * m)314 void ScriptIntrinsicColorMatrix::setColorMatrix4(float* m) {
315 Script::setVar(0, (void*)m, sizeof(float) * 16);
316 }
317
318
setGreyscale()319 void ScriptIntrinsicColorMatrix::setGreyscale() {
320 float matrix[] = {0.299f, 0.299f, 0.299f,0.587f,0.587f,0.587f,0.114f,0.114f, 0.114f};
321 setColorMatrix3(matrix);
322 }
323
324
setRGBtoYUV()325 void ScriptIntrinsicColorMatrix::setRGBtoYUV() {
326 float matrix[] = { 0.299f, -0.14713f, 0.615f, 0.587f, -0.28886f, -0.51499f, 0.114f, 0.436f, -0.10001f};
327 setColorMatrix3(matrix);
328 }
329
330
setYUVtoRGB()331 void ScriptIntrinsicColorMatrix::setYUVtoRGB() {
332 float matrix[] = {1.f, 1.f, 1.f, 0.f, -0.39465f, 2.03211f, 1.13983f, -0.5806f, 0.f};
333 setColorMatrix3(matrix);
334 }
335
336
337
create(sp<RS> rs,sp<const Element> e)338 sp<ScriptIntrinsicConvolve3x3> ScriptIntrinsicConvolve3x3::create(sp<RS> rs, sp<const Element> e) {
339 if (!(e->isCompatible(Element::U8(rs))) &&
340 !(e->isCompatible(Element::U8_2(rs))) &&
341 !(e->isCompatible(Element::U8_3(rs))) &&
342 !(e->isCompatible(Element::U8_4(rs))) &&
343 !(e->isCompatible(Element::F32(rs))) &&
344 !(e->isCompatible(Element::F32_2(rs))) &&
345 !(e->isCompatible(Element::F32_3(rs))) &&
346 !(e->isCompatible(Element::F32_4(rs)))) {
347 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve3x3");
348 return nullptr;
349 }
350
351 return new ScriptIntrinsicConvolve3x3(rs, e);
352 }
353
ScriptIntrinsicConvolve3x3(sp<RS> rs,sp<const Element> e)354 ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e)
355 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) {
356
357 }
358
setInput(sp<Allocation> in)359 void ScriptIntrinsicConvolve3x3::setInput(sp<Allocation> in) {
360 if (!(in->getType()->getElement()->isCompatible(mElement))) {
361 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3");
362 return;
363 }
364 Script::setVar(1, in);
365 }
366
forEach(sp<Allocation> out)367 void ScriptIntrinsicConvolve3x3::forEach(sp<Allocation> out) {
368 if (!(out->getType()->getElement()->isCompatible(mElement))) {
369 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3");
370 return;
371 }
372 Script::forEach(0, nullptr, out, nullptr, 0);
373 }
374
setCoefficients(float * v)375 void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) {
376 Script::setVar(0, (void*)v, sizeof(float) * 9);
377 }
378
create(sp<RS> rs,sp<const Element> e)379 sp<ScriptIntrinsicConvolve5x5> ScriptIntrinsicConvolve5x5::create(sp<RS> rs, sp<const Element> e) {
380 if (!(e->isCompatible(Element::U8(rs))) &&
381 !(e->isCompatible(Element::U8_2(rs))) &&
382 !(e->isCompatible(Element::U8_3(rs))) &&
383 !(e->isCompatible(Element::U8_4(rs))) &&
384 !(e->isCompatible(Element::F32(rs))) &&
385 !(e->isCompatible(Element::F32_2(rs))) &&
386 !(e->isCompatible(Element::F32_3(rs))) &&
387 !(e->isCompatible(Element::F32_4(rs)))) {
388 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve5x5");
389 return nullptr;
390 }
391
392 return new ScriptIntrinsicConvolve5x5(rs, e);
393 }
394
ScriptIntrinsicConvolve5x5(sp<RS> rs,sp<const Element> e)395 ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e)
396 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) {
397
398 }
399
setInput(sp<Allocation> in)400 void ScriptIntrinsicConvolve5x5::setInput(sp<Allocation> in) {
401 if (!(in->getType()->getElement()->isCompatible(mElement))) {
402 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 input");
403 return;
404 }
405 Script::setVar(1, in);
406 }
407
forEach(sp<Allocation> out)408 void ScriptIntrinsicConvolve5x5::forEach(sp<Allocation> out) {
409 if (!(out->getType()->getElement()->isCompatible(mElement))) {
410 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 output");
411 return;
412 }
413
414 Script::forEach(0, nullptr, out, nullptr, 0);
415 }
416
setCoefficients(float * v)417 void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) {
418 Script::setVar(0, (void*)v, sizeof(float) * 25);
419 }
420
create(sp<RS> rs,sp<const Element> e)421 sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs, sp<const Element> e) {
422 return new ScriptIntrinsicHistogram(rs, e);
423 }
424
ScriptIntrinsicHistogram(sp<RS> rs,sp<const Element> e)425 ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e)
426 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) {
427
428 }
429
setOutput(sp<Allocation> out)430 void ScriptIntrinsicHistogram::setOutput(sp<Allocation> out) {
431 if (!(out->getType()->getElement()->isCompatible(Element::U32(mRS))) &&
432 !(out->getType()->getElement()->isCompatible(Element::U32_2(mRS))) &&
433 !(out->getType()->getElement()->isCompatible(Element::U32_3(mRS))) &&
434 !(out->getType()->getElement()->isCompatible(Element::U32_4(mRS))) &&
435 !(out->getType()->getElement()->isCompatible(Element::I32(mRS))) &&
436 !(out->getType()->getElement()->isCompatible(Element::I32_2(mRS))) &&
437 !(out->getType()->getElement()->isCompatible(Element::I32_3(mRS))) &&
438 !(out->getType()->getElement()->isCompatible(Element::I32_4(mRS)))) {
439 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Histogram output");
440 return;
441 }
442
443 if (out->getType()->getX() != 256 ||
444 out->getType()->getY() != 0 ||
445 out->getType()->hasMipmaps()) {
446 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid Allocation type for Histogram output");
447 return;
448 }
449 mOut = out;
450 Script::setVar(1, out);
451 }
452
setDotCoefficients(float r,float g,float b,float a)453 void ScriptIntrinsicHistogram::setDotCoefficients(float r, float g, float b, float a) {
454 if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) {
455 return;
456 }
457 if ((r + g + b + a) > 1.f) {
458 return;
459 }
460
461 FieldPacker fp(16);
462 fp.add(r);
463 fp.add(g);
464 fp.add(b);
465 fp.add(a);
466 Script::setVar(0, fp.getData(), fp.getLength());
467
468 }
469
forEach(sp<Allocation> ain)470 void ScriptIntrinsicHistogram::forEach(sp<Allocation> ain) {
471 if (ain->getType()->getElement()->getVectorSize() <
472 mOut->getType()->getElement()->getVectorSize()) {
473 mRS->throwError(RS_ERROR_INVALID_PARAMETER,
474 "Input vector size must be >= output vector size");
475 return;
476 }
477
478 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
479 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
480 mRS->throwError(RS_ERROR_INVALID_ELEMENT,
481 "Input allocation to Histogram must be U8 or U8_4");
482 return;
483 }
484
485 Script::forEach(0, ain, nullptr, nullptr, 0);
486 }
487
488
forEach_dot(sp<Allocation> ain)489 void ScriptIntrinsicHistogram::forEach_dot(sp<Allocation> ain) {
490 if (mOut->getType()->getElement()->getVectorSize() != 1) {
491 mRS->throwError(RS_ERROR_INVALID_PARAMETER,
492 "Output Histogram allocation must have vector size of 1 " \
493 "when used with forEach_dot");
494 return;
495 }
496 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
497 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
498 mRS->throwError(RS_ERROR_INVALID_ELEMENT,
499 "Input allocation to Histogram must be U8 or U8_4");
500 return;
501 }
502
503 Script::forEach(1, ain, nullptr, nullptr, 0);
504 }
505
create(sp<RS> rs,sp<const Element> e)506 sp<ScriptIntrinsicLUT> ScriptIntrinsicLUT::create(sp<RS> rs, sp<const Element> e) {
507 if (!(e->isCompatible(Element::U8_4(rs)))) {
508 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT");
509 return nullptr;
510 }
511 return new ScriptIntrinsicLUT(rs, e);
512 }
513
ScriptIntrinsicLUT(sp<RS> rs,sp<const Element> e)514 ScriptIntrinsicLUT::ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e)
515 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_LUT, e), mDirty(true) {
516 LUT = Allocation::createSized(rs, Element::U8(rs), 1024);
517 for (int i = 0; i < 256; i++) {
518 mCache[i] = i;
519 mCache[i+256] = i;
520 mCache[i+512] = i;
521 mCache[i+768] = i;
522 }
523 setVar(0, LUT);
524 }
525
forEach(sp<Allocation> ain,sp<Allocation> aout)526 void ScriptIntrinsicLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) {
527 if (mDirty) {
528 LUT->copy1DFrom((void*)mCache);
529 mDirty = false;
530 }
531 if (!(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) ||
532 !(aout->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
533 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT");
534 return;
535 }
536 Script::forEach(0, ain, aout, nullptr, 0);
537
538 }
539
setTable(unsigned int offset,unsigned char base,unsigned int length,unsigned char * lutValues)540 void ScriptIntrinsicLUT::setTable(unsigned int offset, unsigned char base, unsigned int length, unsigned char* lutValues) {
541 if ((base + length) > 256 || length == 0) {
542 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range");
543 return;
544 }
545 mDirty = true;
546 for (unsigned int i = 0; i < length; i++) {
547 mCache[offset + base + i] = lutValues[i];
548 }
549 }
550
setRed(unsigned char base,unsigned int length,unsigned char * lutValues)551 void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned int length, unsigned char* lutValues) {
552 setTable(0, base, length, lutValues);
553 }
554
setGreen(unsigned char base,unsigned int length,unsigned char * lutValues)555 void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned int length, unsigned char* lutValues) {
556 setTable(256, base, length, lutValues);
557 }
558
setBlue(unsigned char base,unsigned int length,unsigned char * lutValues)559 void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned int length, unsigned char* lutValues) {
560 setTable(512, base, length, lutValues);
561 }
562
setAlpha(unsigned char base,unsigned int length,unsigned char * lutValues)563 void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned int length, unsigned char* lutValues) {
564 setTable(768, base, length, lutValues);
565 }
566
~ScriptIntrinsicLUT()567 ScriptIntrinsicLUT::~ScriptIntrinsicLUT() {
568
569 }
570
create(sp<RS> rs)571 sp<ScriptIntrinsicResize> ScriptIntrinsicResize::create(sp<RS> rs) {
572 return new ScriptIntrinsicResize(rs, nullptr);
573 }
574
ScriptIntrinsicResize(sp<RS> rs,sp<const Element> e)575 ScriptIntrinsicResize::ScriptIntrinsicResize(sp<RS> rs, sp<const Element> e)
576 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_RESIZE, e) {
577
578 }
forEach_bicubic(sp<Allocation> aout)579 void ScriptIntrinsicResize::forEach_bicubic(sp<Allocation> aout) {
580 if (aout == mInput) {
581 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Resize Input and Ouput cannot be the same");
582 }
583
584 if (!(mInput->getType()->getElement()->isCompatible(aout->getType()->getElement()))) {
585 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Resize forEach element mismatch");
586 return;
587 }
588 Script::forEach(0, nullptr, aout, nullptr, 0);
589 }
setInput(sp<Allocation> ain)590 void ScriptIntrinsicResize::setInput(sp<Allocation> ain) {
591 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
592 !(ain->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
593 !(ain->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
594 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
595 !(ain->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
596 !(ain->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
597 !(ain->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
598 !(ain->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
599 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Resize Input");
600 return;
601 }
602
603 mInput = ain;
604 Script::setVar(0, ain);
605 }
606
607
create(sp<RS> rs,sp<const Element> e)608 sp<ScriptIntrinsicYuvToRGB> ScriptIntrinsicYuvToRGB::create(sp<RS> rs, sp<const Element> e) {
609 if (!(e->isCompatible(Element::U8_4(rs)))) {
610 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for YuvToRGB");
611 return nullptr;
612 }
613 return new ScriptIntrinsicYuvToRGB(rs, e);
614 }
615
ScriptIntrinsicYuvToRGB(sp<RS> rs,sp<const Element> e)616 ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e)
617 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) {
618
619 }
620
setInput(sp<Allocation> in)621 void ScriptIntrinsicYuvToRGB::setInput(sp<Allocation> in) {
622 if (!(in->getType()->getElement()->isCompatible(Element::YUV(mRS)))) {
623 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for input in YuvToRGB");
624 return;
625 }
626 Script::setVar(0, in);
627 }
628
forEach(sp<Allocation> out)629 void ScriptIntrinsicYuvToRGB::forEach(sp<Allocation> out) {
630 if (!(out->getType()->getElement()->isCompatible(mElement))) {
631 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for output in YuvToRGB");
632 return;
633 }
634
635 Script::forEach(0, nullptr, out, nullptr, 0);
636 }