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