ScriptIntrinsics.cpp revision 49b1226e8399f2ad4a9fd4482ece95dab2ad53b8
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
22using namespace android;
23using namespace RSC;
24
25ScriptIntrinsic::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
32ScriptIntrinsic::~ScriptIntrinsic() {
33
34}
35
36sp<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
44ScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e)
45    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_3DLUT, e) {
46
47}
48void 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}
56void 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
70sp<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
78ScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e)
79    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLEND, e) {
80}
81
82void 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
90void 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
98void 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
106void 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
114void 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
122void 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
130void 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
138void 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
146void 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
154void 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
162void 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
170void 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
179void 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
188void 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
196void 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
207sp<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
216ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e)
217    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLUR, e) {
218
219}
220
221void 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
229void 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
237void 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
247sp<ScriptIntrinsicColorMatrix> ScriptIntrinsicColorMatrix::create(sp<RS> rs) {
248    return new ScriptIntrinsicColorMatrix(rs, Element::RGBA_8888(rs));
249}
250
251ScriptIntrinsicColorMatrix::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
258void 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
286void ScriptIntrinsicColorMatrix::setAdd(float* add) {
287    Script::setVar(1, (void*)add, sizeof(float) * 4);
288}
289
290void 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
316void ScriptIntrinsicColorMatrix::setColorMatrix4(float* m) {
317    Script::setVar(0, (void*)m, sizeof(float) * 16);
318}
319
320
321void 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
327void 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
333void 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
340sp<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
356ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e)
357    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) {
358
359}
360
361void 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
369void 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
377void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) {
378    Script::setVar(0, (void*)v, sizeof(float) * 9);
379}
380
381sp<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
397ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e)
398    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) {
399
400}
401
402void 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
410void 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
419void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) {
420    Script::setVar(0, (void*)v, sizeof(float) * 25);
421}
422
423sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs, sp<const Element> e) {
424    return new ScriptIntrinsicHistogram(rs, e);
425}
426
427ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e)
428    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) {
429
430}
431
432void 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
455void 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
472void 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
491void 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
508sp<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
516ScriptIntrinsicLUT::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
528void 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
542void 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
553void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned int length, unsigned char* lutValues) {
554    setTable(0, base, length, lutValues);
555}
556
557void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned int length, unsigned char* lutValues) {
558    setTable(256, base, length, lutValues);
559}
560
561void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned int length, unsigned char* lutValues) {
562    setTable(512, base, length, lutValues);
563}
564
565void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned int length, unsigned char* lutValues) {
566    setTable(768, base, length, lutValues);
567}
568
569ScriptIntrinsicLUT::~ScriptIntrinsicLUT() {
570
571}
572
573sp<ScriptIntrinsicResize> ScriptIntrinsicResize::create(sp<RS> rs) {
574    return new ScriptIntrinsicResize(rs, nullptr);
575}
576
577ScriptIntrinsicResize::ScriptIntrinsicResize(sp<RS> rs, sp<const Element> e)
578    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_RESIZE, e) {
579
580}
581void 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}
592void 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
610sp<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
618ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e)
619    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) {
620
621}
622
623void 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
631void 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}