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
178 // Numbering jumps here
forEachMultiply(sp<Allocation> in,sp<Allocation> out)179 void ScriptIntrinsicBlend::forEachMultiply(sp<Allocation> in, sp<Allocation> out) {
180 if (in->getType()->getElement()->isCompatible(mElement) == false ||
181 out->getType()->getElement()->isCompatible(mElement) == false) {
182 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
183 }
184 Script::forEach(14, in, out, nullptr, 0);
185 }
186
187 // Numbering jumps here
forEachAdd(sp<Allocation> in,sp<Allocation> out)188 void ScriptIntrinsicBlend::forEachAdd(sp<Allocation> in, sp<Allocation> out) {
189 if (in->getType()->getElement()->isCompatible(mElement) == false ||
190 out->getType()->getElement()->isCompatible(mElement) == false) {
191 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
192 }
193 Script::forEach(34, in, out, nullptr, 0);
194 }
195
forEachSubtract(sp<Allocation> in,sp<Allocation> out)196 void ScriptIntrinsicBlend::forEachSubtract(sp<Allocation> in, sp<Allocation> out) {
197 if (in->getType()->getElement()->isCompatible(mElement) == false ||
198 out->getType()->getElement()->isCompatible(mElement) == false) {
199 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
200 }
201 Script::forEach(35, in, out, nullptr, 0);
202 }
203
204
205
206
create(sp<RS> rs,sp<const Element> e)207 sp<ScriptIntrinsicBlur> ScriptIntrinsicBlur::create(sp<RS> rs, sp<const Element> e) {
208 if ((e->isCompatible(Element::U8_4(rs)) == false) &&
209 (e->isCompatible(Element::U8(rs)) == false)) {
210 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur");
211 return nullptr;
212 }
213 return new ScriptIntrinsicBlur(rs, e);
214 }
215
ScriptIntrinsicBlur(sp<RS> rs,sp<const Element> e)216 ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e)
217 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLUR, e) {
218
219 }
220
setInput(sp<Allocation> in)221 void ScriptIntrinsicBlur::setInput(sp<Allocation> in) {
222 if (in->getType()->getElement()->isCompatible(mElement) == false) {
223 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur input");
224 return;
225 }
226 Script::setVar(1, in);
227 }
228
forEach(sp<Allocation> out)229 void ScriptIntrinsicBlur::forEach(sp<Allocation> out) {
230 if (out->getType()->getElement()->isCompatible(mElement) == false) {
231 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur output");
232 return;
233 }
234 Script::forEach(0, nullptr, out, nullptr, 0);
235 }
236
setRadius(float radius)237 void ScriptIntrinsicBlur::setRadius(float radius) {
238 if (radius > 0.f && radius <= 25.f) {
239 Script::setVar(0, &radius, sizeof(float));
240 } else {
241 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Blur radius out of 0-25 pixel bound");
242 }
243 }
244
245
246
create(sp<RS> rs)247 sp<ScriptIntrinsicColorMatrix> ScriptIntrinsicColorMatrix::create(sp<RS> rs) {
248 return new ScriptIntrinsicColorMatrix(rs, Element::RGBA_8888(rs));
249 }
250
ScriptIntrinsicColorMatrix(sp<RS> rs,sp<const Element> e)251 ScriptIntrinsicColorMatrix::ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Element> e)
252 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_COLOR_MATRIX, e) {
253 float add[4] = {0.f, 0.f, 0.f, 0.f};
254 setAdd(add);
255
256 }
257
forEach(sp<Allocation> in,sp<Allocation> out)258 void ScriptIntrinsicColorMatrix::forEach(sp<Allocation> in, sp<Allocation> out) {
259 if (!(in->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
260 !(in->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
261 !(in->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
262 !(in->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
263 !(in->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
264 !(in->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
265 !(in->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
266 !(in->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
267 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix");
268 return;
269 }
270
271 if (!(out->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
272 !(out->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
273 !(out->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
274 !(out->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
275 !(out->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
276 !(out->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
277 !(out->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
278 !(out->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
279 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix");
280 return;
281 }
282
283 Script::forEach(0, in, out, nullptr, 0);
284 }
285
setAdd(float * add)286 void ScriptIntrinsicColorMatrix::setAdd(float* add) {
287 Script::setVar(1, (void*)add, sizeof(float) * 4);
288 }
289
setColorMatrix3(float * m)290 void ScriptIntrinsicColorMatrix::setColorMatrix3(float* m) {
291 float temp[16];
292 temp[0] = m[0];
293 temp[1] = m[1];
294 temp[2] = m[2];
295 temp[3] = 0.f;
296
297 temp[4] = m[3];
298 temp[5] = m[4];
299 temp[6] = m[5];
300 temp[7] = 0.f;
301
302 temp[8] = m[6];
303 temp[9] = m[7];
304 temp[10] = m[8];
305 temp[11] = 0.f;
306
307 temp[12] = 0.f;
308 temp[13] = 0.f;
309 temp[14] = 0.f;
310 temp[15] = 1.f;
311
312 setColorMatrix4(temp);
313 }
314
315
setColorMatrix4(float * m)316 void ScriptIntrinsicColorMatrix::setColorMatrix4(float* m) {
317 Script::setVar(0, (void*)m, sizeof(float) * 16);
318 }
319
320
setGreyscale()321 void ScriptIntrinsicColorMatrix::setGreyscale() {
322 float matrix[] = {0.299f, 0.299f, 0.299f,0.587f,0.587f,0.587f,0.114f,0.114f, 0.114f};
323 setColorMatrix3(matrix);
324 }
325
326
setRGBtoYUV()327 void ScriptIntrinsicColorMatrix::setRGBtoYUV() {
328 float matrix[] = { 0.299f, -0.14713f, 0.615f, 0.587f, -0.28886f, -0.51499f, 0.114f, 0.436f, -0.10001f};
329 setColorMatrix3(matrix);
330 }
331
332
setYUVtoRGB()333 void ScriptIntrinsicColorMatrix::setYUVtoRGB() {
334 float matrix[] = {1.f, 1.f, 1.f, 0.f, -0.39465f, 2.03211f, 1.13983f, -0.5806f, 0.f};
335 setColorMatrix3(matrix);
336 }
337
338
339
create(sp<RS> rs,sp<const Element> e)340 sp<ScriptIntrinsicConvolve3x3> ScriptIntrinsicConvolve3x3::create(sp<RS> rs, sp<const Element> e) {
341 if (!(e->isCompatible(Element::U8(rs))) &&
342 !(e->isCompatible(Element::U8_2(rs))) &&
343 !(e->isCompatible(Element::U8_3(rs))) &&
344 !(e->isCompatible(Element::U8_4(rs))) &&
345 !(e->isCompatible(Element::F32(rs))) &&
346 !(e->isCompatible(Element::F32_2(rs))) &&
347 !(e->isCompatible(Element::F32_3(rs))) &&
348 !(e->isCompatible(Element::F32_4(rs)))) {
349 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve3x3");
350 return nullptr;
351 }
352
353 return new ScriptIntrinsicConvolve3x3(rs, e);
354 }
355
ScriptIntrinsicConvolve3x3(sp<RS> rs,sp<const Element> e)356 ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e)
357 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) {
358
359 }
360
setInput(sp<Allocation> in)361 void ScriptIntrinsicConvolve3x3::setInput(sp<Allocation> in) {
362 if (!(in->getType()->getElement()->isCompatible(mElement))) {
363 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3");
364 return;
365 }
366 Script::setVar(1, in);
367 }
368
forEach(sp<Allocation> out)369 void ScriptIntrinsicConvolve3x3::forEach(sp<Allocation> out) {
370 if (!(out->getType()->getElement()->isCompatible(mElement))) {
371 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3");
372 return;
373 }
374 Script::forEach(0, nullptr, out, nullptr, 0);
375 }
376
setCoefficients(float * v)377 void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) {
378 Script::setVar(0, (void*)v, sizeof(float) * 9);
379 }
380
create(sp<RS> rs,sp<const Element> e)381 sp<ScriptIntrinsicConvolve5x5> ScriptIntrinsicConvolve5x5::create(sp<RS> rs, sp<const Element> e) {
382 if (!(e->isCompatible(Element::U8(rs))) &&
383 !(e->isCompatible(Element::U8_2(rs))) &&
384 !(e->isCompatible(Element::U8_3(rs))) &&
385 !(e->isCompatible(Element::U8_4(rs))) &&
386 !(e->isCompatible(Element::F32(rs))) &&
387 !(e->isCompatible(Element::F32_2(rs))) &&
388 !(e->isCompatible(Element::F32_3(rs))) &&
389 !(e->isCompatible(Element::F32_4(rs)))) {
390 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve5x5");
391 return nullptr;
392 }
393
394 return new ScriptIntrinsicConvolve5x5(rs, e);
395 }
396
ScriptIntrinsicConvolve5x5(sp<RS> rs,sp<const Element> e)397 ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e)
398 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) {
399
400 }
401
setInput(sp<Allocation> in)402 void ScriptIntrinsicConvolve5x5::setInput(sp<Allocation> in) {
403 if (!(in->getType()->getElement()->isCompatible(mElement))) {
404 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 input");
405 return;
406 }
407 Script::setVar(1, in);
408 }
409
forEach(sp<Allocation> out)410 void ScriptIntrinsicConvolve5x5::forEach(sp<Allocation> out) {
411 if (!(out->getType()->getElement()->isCompatible(mElement))) {
412 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 output");
413 return;
414 }
415
416 Script::forEach(0, nullptr, out, nullptr, 0);
417 }
418
setCoefficients(float * v)419 void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) {
420 Script::setVar(0, (void*)v, sizeof(float) * 25);
421 }
422
create(sp<RS> rs,sp<const Element> e)423 sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs, sp<const Element> e) {
424 return new ScriptIntrinsicHistogram(rs, e);
425 }
426
ScriptIntrinsicHistogram(sp<RS> rs,sp<const Element> e)427 ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e)
428 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) {
429
430 }
431
setOutput(sp<Allocation> out)432 void ScriptIntrinsicHistogram::setOutput(sp<Allocation> out) {
433 if (!(out->getType()->getElement()->isCompatible(Element::U32(mRS))) &&
434 !(out->getType()->getElement()->isCompatible(Element::U32_2(mRS))) &&
435 !(out->getType()->getElement()->isCompatible(Element::U32_3(mRS))) &&
436 !(out->getType()->getElement()->isCompatible(Element::U32_4(mRS))) &&
437 !(out->getType()->getElement()->isCompatible(Element::I32(mRS))) &&
438 !(out->getType()->getElement()->isCompatible(Element::I32_2(mRS))) &&
439 !(out->getType()->getElement()->isCompatible(Element::I32_3(mRS))) &&
440 !(out->getType()->getElement()->isCompatible(Element::I32_4(mRS)))) {
441 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Histogram output");
442 return;
443 }
444
445 if (out->getType()->getX() != 256 ||
446 out->getType()->getY() != 0 ||
447 out->getType()->hasMipmaps()) {
448 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid Allocation type for Histogram output");
449 return;
450 }
451 mOut = out;
452 Script::setVar(1, out);
453 }
454
setDotCoefficients(float r,float g,float b,float a)455 void ScriptIntrinsicHistogram::setDotCoefficients(float r, float g, float b, float a) {
456 if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) {
457 return;
458 }
459 if ((r + g + b + a) > 1.f) {
460 return;
461 }
462
463 FieldPacker fp(16);
464 fp.add(r);
465 fp.add(g);
466 fp.add(b);
467 fp.add(a);
468 Script::setVar(0, fp.getData(), fp.getLength());
469
470 }
471
forEach(sp<Allocation> ain)472 void ScriptIntrinsicHistogram::forEach(sp<Allocation> ain) {
473 if (ain->getType()->getElement()->getVectorSize() <
474 mOut->getType()->getElement()->getVectorSize()) {
475 mRS->throwError(RS_ERROR_INVALID_PARAMETER,
476 "Input vector size must be >= output vector size");
477 return;
478 }
479
480 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
481 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
482 mRS->throwError(RS_ERROR_INVALID_ELEMENT,
483 "Input allocation to Histogram must be U8 or U8_4");
484 return;
485 }
486
487 Script::forEach(0, ain, nullptr, nullptr, 0);
488 }
489
490
forEach_dot(sp<Allocation> ain)491 void ScriptIntrinsicHistogram::forEach_dot(sp<Allocation> ain) {
492 if (mOut->getType()->getElement()->getVectorSize() != 1) {
493 mRS->throwError(RS_ERROR_INVALID_PARAMETER,
494 "Output Histogram allocation must have vector size of 1 " \
495 "when used with forEach_dot");
496 return;
497 }
498 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
499 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
500 mRS->throwError(RS_ERROR_INVALID_ELEMENT,
501 "Input allocation to Histogram must be U8 or U8_4");
502 return;
503 }
504
505 Script::forEach(1, ain, nullptr, nullptr, 0);
506 }
507
create(sp<RS> rs,sp<const Element> e)508 sp<ScriptIntrinsicLUT> ScriptIntrinsicLUT::create(sp<RS> rs, sp<const Element> e) {
509 if (!(e->isCompatible(Element::U8_4(rs)))) {
510 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT");
511 return nullptr;
512 }
513 return new ScriptIntrinsicLUT(rs, e);
514 }
515
ScriptIntrinsicLUT(sp<RS> rs,sp<const Element> e)516 ScriptIntrinsicLUT::ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e)
517 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_LUT, e), mDirty(true) {
518 LUT = Allocation::createSized(rs, Element::U8(rs), 1024);
519 for (int i = 0; i < 256; i++) {
520 mCache[i] = i;
521 mCache[i+256] = i;
522 mCache[i+512] = i;
523 mCache[i+768] = i;
524 }
525 setVar(0, LUT);
526 }
527
forEach(sp<Allocation> ain,sp<Allocation> aout)528 void ScriptIntrinsicLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) {
529 if (mDirty) {
530 LUT->copy1DFrom((void*)mCache);
531 mDirty = false;
532 }
533 if (!(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) ||
534 !(aout->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
535 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT");
536 return;
537 }
538 Script::forEach(0, ain, aout, nullptr, 0);
539
540 }
541
setTable(unsigned int offset,unsigned char base,unsigned int length,unsigned char * lutValues)542 void ScriptIntrinsicLUT::setTable(unsigned int offset, unsigned char base, unsigned int length, unsigned char* lutValues) {
543 if ((base + length) > 256 || length == 0) {
544 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range");
545 return;
546 }
547 mDirty = true;
548 for (unsigned int i = 0; i < length; i++) {
549 mCache[offset + base + i] = lutValues[i];
550 }
551 }
552
setRed(unsigned char base,unsigned int length,unsigned char * lutValues)553 void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned int length, unsigned char* lutValues) {
554 setTable(0, base, length, lutValues);
555 }
556
setGreen(unsigned char base,unsigned int length,unsigned char * lutValues)557 void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned int length, unsigned char* lutValues) {
558 setTable(256, base, length, lutValues);
559 }
560
setBlue(unsigned char base,unsigned int length,unsigned char * lutValues)561 void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned int length, unsigned char* lutValues) {
562 setTable(512, base, length, lutValues);
563 }
564
setAlpha(unsigned char base,unsigned int length,unsigned char * lutValues)565 void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned int length, unsigned char* lutValues) {
566 setTable(768, base, length, lutValues);
567 }
568
~ScriptIntrinsicLUT()569 ScriptIntrinsicLUT::~ScriptIntrinsicLUT() {
570
571 }
572
create(sp<RS> rs)573 sp<ScriptIntrinsicResize> ScriptIntrinsicResize::create(sp<RS> rs) {
574 return new ScriptIntrinsicResize(rs, nullptr);
575 }
576
ScriptIntrinsicResize(sp<RS> rs,sp<const Element> e)577 ScriptIntrinsicResize::ScriptIntrinsicResize(sp<RS> rs, sp<const Element> e)
578 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_RESIZE, e) {
579
580 }
forEach_bicubic(sp<Allocation> aout)581 void ScriptIntrinsicResize::forEach_bicubic(sp<Allocation> aout) {
582 if (aout == mInput) {
583 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Resize Input and Ouput cannot be the same");
584 }
585
586 if (!(mInput->getType()->getElement()->isCompatible(aout->getType()->getElement()))) {
587 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Resize forEach element mismatch");
588 return;
589 }
590 Script::forEach(0, nullptr, aout, nullptr, 0);
591 }
setInput(sp<Allocation> ain)592 void ScriptIntrinsicResize::setInput(sp<Allocation> ain) {
593 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
594 !(ain->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
595 !(ain->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
596 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
597 !(ain->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
598 !(ain->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
599 !(ain->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
600 !(ain->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
601 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Resize Input");
602 return;
603 }
604
605 mInput = ain;
606 Script::setVar(0, ain);
607 }
608
609
create(sp<RS> rs,sp<const Element> e)610 sp<ScriptIntrinsicYuvToRGB> ScriptIntrinsicYuvToRGB::create(sp<RS> rs, sp<const Element> e) {
611 if (!(e->isCompatible(Element::U8_4(rs)))) {
612 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for YuvToRGB");
613 return nullptr;
614 }
615 return new ScriptIntrinsicYuvToRGB(rs, e);
616 }
617
ScriptIntrinsicYuvToRGB(sp<RS> rs,sp<const Element> e)618 ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e)
619 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) {
620
621 }
622
setInput(sp<Allocation> in)623 void ScriptIntrinsicYuvToRGB::setInput(sp<Allocation> in) {
624 if (!(in->getType()->getElement()->isCompatible(Element::YUV(mRS)))) {
625 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for input in YuvToRGB");
626 return;
627 }
628 Script::setVar(0, in);
629 }
630
forEach(sp<Allocation> out)631 void ScriptIntrinsicYuvToRGB::forEach(sp<Allocation> out) {
632 if (!(out->getType()->getElement()->isCompatible(mElement))) {
633 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for output in YuvToRGB");
634 return;
635 }
636
637 Script::forEach(0, nullptr, out, nullptr, 0);
638 }
639