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