ScriptIntrinsics.cpp revision fa77db83d3e36d6aa23622cec5bdcb5e373f0a3b
124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown/*
224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Copyright (C) 2008-2012 The Android Open Source Project
324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *
424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * you may not use this file except in compliance with the License.
624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * You may obtain a copy of the License at
724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *
824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *
1024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Unless required by applicable law or agreed to in writing, software
1124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * See the License for the specific language governing permissions and
1424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * limitations under the License.
1524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */
1624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
1724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown#include <malloc.h>
1824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
198e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas#include "RenderScript.h"
208e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas#include "rsCppInternal.h"
2124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
22f0e4dea75691d2fd1256508136ecce88bef6067bIan Lakeusing namespace android;
23c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteusing namespace RSC;
2424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
2524fa6c0dd42df057729e1a258388183f94da7f82Jeff BrownScriptIntrinsic::ScriptIntrinsic(sp<RS> rs, int id, sp<const Element> e)
26f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    : Script(NULL, rs) {
27f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    mID = createDispatch(rs, RS::dispatch->ScriptIntrinsicCreate(rs->getContext(), id, e->getID()));
28f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    mElement = e;
2924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
3024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
3124fa6c0dd42df057729e1a258388183f94da7f82Jeff BrownScriptIntrinsic::~ScriptIntrinsic() {
3224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
3324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
3424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
3524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownsp<ScriptIntrinsic3DLUT> ScriptIntrinsic3DLUT::create(sp<RS> rs, sp<const Element> e) {
36f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    if (e->isCompatible(Element::U8_4(rs)) == false) {
37f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake        rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic");
38f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake        return NULL;
39f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    }
408e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas    return new ScriptIntrinsic3DLUT(rs, e);
41f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake}
42f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake
43f0e4dea75691d2fd1256508136ecce88bef6067bIan LakeScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e)
44f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_3DLUT, e) {
4524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
4624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
4724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsic3DLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) {
4824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (ain->getType()->getElement()->isCompatible(mElement) == false ||
4924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        aout->getType()->getElement()->isCompatible(mElement) == false) {
5024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "3DLUT forEach element mismatch");
5124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return;
5224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
53ead061ff8567599fa905a1ee1de2532b7050d7faRoboErik    Script::forEach(0, ain, aout, NULL, 0);
5424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
5524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsic3DLUT::setLUT(sp<Allocation> lut) {
5624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    sp<const Type> t = lut->getType();
5724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (!t->getElement()->isCompatible(mElement)) {
5824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "setLUT element does not match");
5924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return;
60ead061ff8567599fa905a1ee1de2532b7050d7faRoboErik    }
6124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (t->getZ() == 0) {
6224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "setLUT Allocation must be 3D");
6324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return;
6424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
6524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
6624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::setVar(0, lut);
67e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik}
6824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
6924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownsp<ScriptIntrinsicBlend> ScriptIntrinsicBlend::create(sp<RS> rs, sp<const Element> e) {
7024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (e->isCompatible(Element::U8_4(rs)) == false) {
7124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic");
7224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return NULL;
7324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
7424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    return new ScriptIntrinsicBlend(rs, e);
7524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
7624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
7724fa6c0dd42df057729e1a258388183f94da7f82Jeff BrownScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e)
7824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLEND, e) {
79e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik}
8024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
81f0e4dea75691d2fd1256508136ecce88bef6067bIan Lakevoid ScriptIntrinsicBlend::blendClear(sp<Allocation> in, sp<Allocation> out) {
8224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
8324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
84e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
8524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
8624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(0, in, out, NULL, 0);
8724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
88e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik
8924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendSrc(sp<Allocation> in, sp<Allocation> out) {
9024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
9124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
92e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
93e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik    }
94e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik    Script::forEach(1, in, out, NULL, 0);
9524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
9624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
9724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendDst(sp<Allocation> in, sp<Allocation> out) {
9824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
9924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
10024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
101f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    }
10224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(2, in, out, NULL, 0);
10324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
10424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
10524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendSrcOver(sp<Allocation> in, sp<Allocation> out) {
10624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
10724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
10824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
10924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
11024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(3, in, out, NULL, 0);
11124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
11224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
11324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendDstOver(sp<Allocation> in, sp<Allocation> out) {
11424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
11524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
116e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
117e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik    }
118e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik    Script::forEach(4, in, out, NULL, 0);
119e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErik}
12024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
121e0c3fd8d5c24c7e8bcc54234f30c01e78137b67eRoboErikvoid ScriptIntrinsicBlend::blendSrcIn(sp<Allocation> in, sp<Allocation> out) {
1229b032988d409ee6bff579d8f21ef79f4c5fd5fb5Ian Lake    if (in->getType()->getElement()->isCompatible(mElement) == false ||
1239b032988d409ee6bff579d8f21ef79f4c5fd5fb5Ian Lake        out->getType()->getElement()->isCompatible(mElement) == false) {
124c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
1259b032988d409ee6bff579d8f21ef79f4c5fd5fb5Ian Lake    }
1269b032988d409ee6bff579d8f21ef79f4c5fd5fb5Ian Lake    Script::forEach(5, in, out, NULL, 0);
12724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
12824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
12924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendDstIn(sp<Allocation> in, sp<Allocation> out) {
13024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
13124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
13224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
13324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
13424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(6, in, out, NULL, 0);
13524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
13624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
13724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendSrcOut(sp<Allocation> in, sp<Allocation> out) {
13824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
13924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
14024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
141ead061ff8567599fa905a1ee1de2532b7050d7faRoboErik    }
14224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(7, in, out, NULL, 0);
143ead061ff8567599fa905a1ee1de2532b7050d7faRoboErik}
14424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
145ead061ff8567599fa905a1ee1de2532b7050d7faRoboErikvoid ScriptIntrinsicBlend::blendDstOut(sp<Allocation> in, sp<Allocation> out) {
14624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
14724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
14824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
14924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
15024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(8, in, out, NULL, 0);
15124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
15224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
15324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendSrcAtop(sp<Allocation> in, sp<Allocation> out) {
15424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
15524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
15624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
15724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
15824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(9, in, out, NULL, 0);
15924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
16024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
16124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendDstAtop(sp<Allocation> in, sp<Allocation> out) {
16224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
16324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
16424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
16524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
16624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(10, in, out, NULL, 0);
167c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette}
168c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette
169c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverettevoid ScriptIntrinsicBlend::blendXor(sp<Allocation> in, sp<Allocation> out) {
170c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    if (in->getType()->getElement()->isCompatible(mElement) == false ||
171c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        out->getType()->getElement()->isCompatible(mElement) == false) {
172c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
173c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    }
174c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    Script::forEach(11, in, out, NULL, 0);
175c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette}
176c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette
177c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette// Numbering jumps here
178c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverettevoid ScriptIntrinsicBlend::blendMultiply(sp<Allocation> in, sp<Allocation> out) {
179c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    if (in->getType()->getElement()->isCompatible(mElement) == false ||
180c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        out->getType()->getElement()->isCompatible(mElement) == false) {
181c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
18224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
18324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    Script::forEach(14, in, out, NULL, 0);
18424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
18524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
18624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown// Numbering jumps here
18724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownvoid ScriptIntrinsicBlend::blendAdd(sp<Allocation> in, sp<Allocation> out) {
18824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    if (in->getType()->getElement()->isCompatible(mElement) == false ||
18924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        out->getType()->getElement()->isCompatible(mElement) == false) {
19024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend");
19124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
192f0e4dea75691d2fd1256508136ecce88bef6067bIan Lake    Script::forEach(34, in, out, NULL, 0);
193}
194
195void ScriptIntrinsicBlend::blendSubtract(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, sp<const Element> e) {
247    return new ScriptIntrinsicColorMatrix(rs, e);
248}
249
250ScriptIntrinsicColorMatrix::ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Element> e)
251    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_COLOR_MATRIX, e) {
252
253}
254
255void ScriptIntrinsicColorMatrix::forEach(sp<Allocation> in, sp<Allocation> out) {
256    if (!(in->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
257        !(in->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
258        !(in->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
259        !(in->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
260        !(in->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
261        !(in->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
262        !(in->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
263        !(in->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
264        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix");
265        return;
266    }
267
268    if (!(out->getType()->getElement()->isCompatible(Element::U8(mRS))) &&
269        !(out->getType()->getElement()->isCompatible(Element::U8_2(mRS))) &&
270        !(out->getType()->getElement()->isCompatible(Element::U8_3(mRS))) &&
271        !(out->getType()->getElement()->isCompatible(Element::U8_4(mRS))) &&
272        !(out->getType()->getElement()->isCompatible(Element::F32(mRS))) &&
273        !(out->getType()->getElement()->isCompatible(Element::F32_2(mRS))) &&
274        !(out->getType()->getElement()->isCompatible(Element::F32_3(mRS))) &&
275        !(out->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) {
276        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix");
277        return;
278    }
279
280    Script::forEach(0, in, out, NULL, 0);
281}
282
283void ScriptIntrinsicColorMatrix::setAdd(float* add) {
284    Script::setVar(1, (void*)add, sizeof(float) * 4);
285}
286
287void ScriptIntrinsicColorMatrix::setColorMatrix3(float* m) {
288    Script::setVar(0, (void*)m, sizeof(float) * 9);
289}
290
291
292void ScriptIntrinsicColorMatrix::setColorMatrix4(float* m) {
293    Script::setVar(0, (void*)m, sizeof(float) * 16);
294}
295
296
297void ScriptIntrinsicColorMatrix::setGreyscale() {
298    float matrix[] = {0.299f, 0.587f,  0.114f, 0.299f, 0.587f, 0.114f, 0.299f, 0.587f, 0.114f};
299    setColorMatrix3(matrix);
300}
301
302
303void ScriptIntrinsicColorMatrix::setRGBtoYUV() {
304    float matrix[] = {0.299f,0.587f,0.114f,-0.14713f,-0.28886f,0.436f,0.615f,-0.51499f,-0.10001f};
305    setColorMatrix3(matrix);
306}
307
308
309void ScriptIntrinsicColorMatrix::setYUVtoRGB() {
310    float matrix[] = {1.f,0.f,1.13983f,1.f,-0.39465f,-0.5806f,1.f,2.03211f,0.f};
311    setColorMatrix3(matrix);
312}
313
314
315
316sp<ScriptIntrinsicConvolve3x3> ScriptIntrinsicConvolve3x3::create(sp<RS> rs, sp<const Element> e) {
317    if (!(e->isCompatible(Element::U8(rs))) &&
318        !(e->isCompatible(Element::U8_2(rs))) &&
319        !(e->isCompatible(Element::U8_3(rs))) &&
320        !(e->isCompatible(Element::U8_4(rs))) &&
321        !(e->isCompatible(Element::F32(rs))) &&
322        !(e->isCompatible(Element::F32_2(rs))) &&
323        !(e->isCompatible(Element::F32_3(rs))) &&
324        !(e->isCompatible(Element::F32_4(rs)))) {
325        rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve3x3");
326        return NULL;
327    }
328
329    return new ScriptIntrinsicConvolve3x3(rs, e);
330}
331
332ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e)
333    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) {
334
335}
336
337void ScriptIntrinsicConvolve3x3::setInput(sp<Allocation> in) {
338    if (!(in->getType()->getElement()->isCompatible(mElement))) {
339        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3");
340        return;
341    }
342    Script::setVar(1, in);
343}
344
345void ScriptIntrinsicConvolve3x3::forEach(sp<Allocation> out) {
346    if (!(out->getType()->getElement()->isCompatible(mElement))) {
347        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3");
348        return;
349    }
350    Script::forEach(0, NULL, out, NULL, 0);
351}
352
353void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) {
354    Script::setVar(0, (void*)v, sizeof(float) * 9);
355}
356
357sp<ScriptIntrinsicConvolve5x5> ScriptIntrinsicConvolve5x5::create(sp<RS> rs, sp<const Element> e) {
358    if (!(e->isCompatible(Element::U8(rs))) &&
359        !(e->isCompatible(Element::U8_2(rs))) &&
360        !(e->isCompatible(Element::U8_3(rs))) &&
361        !(e->isCompatible(Element::U8_4(rs))) &&
362        !(e->isCompatible(Element::F32(rs))) &&
363        !(e->isCompatible(Element::F32_2(rs))) &&
364        !(e->isCompatible(Element::F32_3(rs))) &&
365        !(e->isCompatible(Element::F32_4(rs)))) {
366        rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve5x5");
367        return NULL;
368    }
369
370    return new ScriptIntrinsicConvolve5x5(rs, e);
371}
372
373ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e)
374    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) {
375
376}
377
378void ScriptIntrinsicConvolve5x5::setInput(sp<Allocation> in) {
379    if (!(in->getType()->getElement()->isCompatible(mElement))) {
380        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 input");
381        return;
382    }
383    Script::setVar(1, in);
384}
385
386void ScriptIntrinsicConvolve5x5::forEach(sp<Allocation> out) {
387    if (!(out->getType()->getElement()->isCompatible(mElement))) {
388        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 output");
389        return;
390    }
391
392    Script::forEach(0, NULL, out, NULL, 0);
393}
394
395void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) {
396    Script::setVar(0, (void*)v, sizeof(float) * 25);
397}
398
399sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs) {
400    return new ScriptIntrinsicHistogram(rs, NULL);
401}
402
403ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e)
404    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) {
405
406}
407
408void ScriptIntrinsicHistogram::setOutput(sp<Allocation> out) {
409    if (!(out->getType()->getElement()->isCompatible(Element::U32(mRS))) &&
410        !(out->getType()->getElement()->isCompatible(Element::U32_2(mRS))) &&
411        !(out->getType()->getElement()->isCompatible(Element::U32_3(mRS))) &&
412        !(out->getType()->getElement()->isCompatible(Element::U32_4(mRS))) &&
413        !(out->getType()->getElement()->isCompatible(Element::I32(mRS))) &&
414        !(out->getType()->getElement()->isCompatible(Element::I32_2(mRS))) &&
415        !(out->getType()->getElement()->isCompatible(Element::I32_3(mRS))) &&
416        !(out->getType()->getElement()->isCompatible(Element::I32_4(mRS)))) {
417        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Histogram output");
418        return;
419    }
420
421    if (out->getType()->getX() != 256 ||
422        out->getType()->getY() != 0 ||
423        out->getType()->hasMipmaps()) {
424        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid Allocation type for Histogram output");
425        return;
426    }
427    mOut = out;
428    Script::setVar(1, out);
429}
430
431void ScriptIntrinsicHistogram::setDotCoefficients(float r, float g, float b, float a) {
432    if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) {
433        return;
434    }
435    if ((r + g + b + a) > 1.f) {
436        return;
437    }
438
439    FieldPacker fp(16);
440    fp.add(r);
441    fp.add(g);
442    fp.add(b);
443    fp.add(a);
444    Script::setVar(0, fp.getData(), fp.getLength());
445
446}
447
448void ScriptIntrinsicHistogram::forEach(sp<Allocation> ain) {
449    if (ain->getType()->getElement()->getVectorSize() <
450        mOut->getType()->getElement()->getVectorSize()) {
451        mRS->throwError(RS_ERROR_INVALID_PARAMETER,
452                        "Input vector size must be >= output vector size");
453        return;
454    }
455
456    if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) ||
457        !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
458        mRS->throwError(RS_ERROR_INVALID_ELEMENT,
459                        "Input allocation to Histogram must be U8 or U8_4");
460        return;
461    }
462
463    Script::forEach(0, ain, NULL, NULL, 0);
464}
465
466
467void ScriptIntrinsicHistogram::forEach_dot(sp<Allocation> ain) {
468    if (mOut->getType()->getElement()->getVectorSize() != 1) {
469        mRS->throwError(RS_ERROR_INVALID_PARAMETER,
470                        "Output Histogram allocation must have vector size of 1 " \
471                        "when used with forEach_dot");
472        return;
473    }
474    if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) ||
475        !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
476        mRS->throwError(RS_ERROR_INVALID_ELEMENT,
477                        "Input allocation to Histogram must be U8 or U8_4");
478        return;
479    }
480
481    Script::forEach(1, ain, NULL, NULL, 0);
482}
483
484sp<ScriptIntrinsicLUT> ScriptIntrinsicLUT::create(sp<RS> rs, sp<const Element> e) {
485    if (!(e->isCompatible(Element::U8_4(rs)))) {
486        rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT");
487        return NULL;
488    }
489    return new ScriptIntrinsicLUT(rs, e);
490}
491
492ScriptIntrinsicLUT::ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e)
493    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_LUT, e), mDirty(true) {
494    LUT = Allocation::createSized(rs, Element::U8(rs), 1024);
495    for (int i = 0; i < 256; i++) {
496        mCache[i] = i;
497        mCache[i+256] = i;
498        mCache[i+512] = i;
499        mCache[i+768] = i;
500    }
501    setVar(0, LUT);
502}
503
504void ScriptIntrinsicLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) {
505    if (mDirty) {
506        LUT->copy1DFrom((void*)mCache);
507        mDirty = false;
508    }
509    if (!(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) ||
510        !(aout->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) {
511        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT");
512        return;
513    }
514    Script::forEach(0, ain, aout, NULL, 0);
515
516}
517
518void ScriptIntrinsicLUT::setTable(unsigned int offset, unsigned char base, unsigned int length, unsigned char* lutValues) {
519    if ((base + length) > 256 || length == 0) {
520        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range");
521        return;
522    }
523    mDirty = true;
524    for (unsigned int i = 0; i < length; i++) {
525        mCache[offset + base + i] = lutValues[i];
526    }
527}
528
529void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned int length, unsigned char* lutValues) {
530    setTable(0, base, length, lutValues);
531}
532
533void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned int length, unsigned char* lutValues) {
534    setTable(256, base, length, lutValues);
535}
536
537void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned int length, unsigned char* lutValues) {
538    setTable(512, base, length, lutValues);
539}
540
541void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned int length, unsigned char* lutValues) {
542    setTable(768, base, length, lutValues);
543}
544
545ScriptIntrinsicLUT::~ScriptIntrinsicLUT() {
546
547}
548
549sp<ScriptIntrinsicYuvToRGB> ScriptIntrinsicYuvToRGB::create(sp<RS> rs, sp<const Element> e) {
550    if (!(e->isCompatible(Element::U8_4(rs)))) {
551        rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for YuvToRGB");
552        return NULL;
553    }
554    return new ScriptIntrinsicYuvToRGB(rs, e);
555}
556
557ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e)
558    : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) {
559
560}
561
562void ScriptIntrinsicYuvToRGB::setInput(sp<Allocation> in) {
563    if (!(in->getType()->getElement()->isCompatible(Element::YUV(mRS)))) {
564        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for input in YuvToRGB");
565        return;
566    }
567    Script::setVar(0, in);
568}
569
570void ScriptIntrinsicYuvToRGB::forEach(sp<Allocation> out) {
571    if (!(out->getType()->getElement()->isCompatible(mElement))) {
572        mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for output in YuvToRGB");
573        return;
574    }
575
576    Script::forEach(0, NULL, out, NULL, 0);
577}
578