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