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