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