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