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 }