Home | History | Annotate | Download | only in cpp
      1 /*
      2  * Copyright (C) 2008-2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <malloc.h>
     18 
     19 #include "RenderScript.h"
     20 #include "rsCppInternal.h"
     21 
     22 using namespace android;
     23 using namespace RSC;
     24 
     25 ScriptIntrinsic::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 
     31 ScriptIntrinsic::~ScriptIntrinsic() {
     32 
     33 }
     34 
     35 sp<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 
     43 ScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e)
     44     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_3DLUT, e) {
     45 
     46 }
     47 void 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 }
     55 void 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 
     69 sp<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 
     77 ScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e)
     78     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLEND, e) {
     79 }
     80 
     81 void 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 
     89 void 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 
     97 void 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 
    105 void 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 
    113 void 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 
    121 void 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 
    129 void 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 
    137 void 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 
    145 void 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 
    153 void 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 
    161 void 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 
    169 void 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
    178 void 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
    187 void 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 
    195 void 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 
    206 sp<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 
    215 ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e)
    216     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLUR, e) {
    217 
    218 }
    219 
    220 void 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 
    228 void 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 
    236 void 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 
    246 sp<ScriptIntrinsicColorMatrix> ScriptIntrinsicColorMatrix::create(sp<RS> rs) {
    247     return new ScriptIntrinsicColorMatrix(rs, Element::RGBA_8888(rs));
    248 }
    249 
    250 ScriptIntrinsicColorMatrix::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 
    257 void 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 
    285 void ScriptIntrinsicColorMatrix::setAdd(float* add) {
    286     Script::setVar(1, (void*)add, sizeof(float) * 4);
    287 }
    288 
    289 void 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 
    315 void ScriptIntrinsicColorMatrix::setColorMatrix4(float* m) {
    316     Script::setVar(0, (void*)m, sizeof(float) * 16);
    317 }
    318 
    319 
    320 void 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 
    326 void 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 
    332 void 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 
    339 sp<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 
    355 ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e)
    356     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) {
    357 
    358 }
    359 
    360 void 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 
    368 void 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 
    376 void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) {
    377     Script::setVar(0, (void*)v, sizeof(float) * 9);
    378 }
    379 
    380 sp<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 
    396 ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e)
    397     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) {
    398 
    399 }
    400 
    401 void 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 
    409 void 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 
    418 void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) {
    419     Script::setVar(0, (void*)v, sizeof(float) * 25);
    420 }
    421 
    422 sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs) {
    423     return new ScriptIntrinsicHistogram(rs, NULL);
    424 }
    425 
    426 ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e)
    427     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) {
    428 
    429 }
    430 
    431 void 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 
    454 void 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 
    471 void 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 
    490 void 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 
    507 sp<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 
    515 ScriptIntrinsicLUT::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 
    527 void 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 
    541 void 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 
    552 void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned int length, unsigned char* lutValues) {
    553     setTable(0, base, length, lutValues);
    554 }
    555 
    556 void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned int length, unsigned char* lutValues) {
    557     setTable(256, base, length, lutValues);
    558 }
    559 
    560 void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned int length, unsigned char* lutValues) {
    561     setTable(512, base, length, lutValues);
    562 }
    563 
    564 void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned int length, unsigned char* lutValues) {
    565     setTable(768, base, length, lutValues);
    566 }
    567 
    568 ScriptIntrinsicLUT::~ScriptIntrinsicLUT() {
    569 
    570 }
    571 
    572 sp<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 
    580 ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e)
    581     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) {
    582 
    583 }
    584 
    585 void 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 
    593 void 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