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