101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams/*
201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * Copyright (C) 2012 The Android Open Source Project
301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams *
401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * you may not use this file except in compliance with the License.
601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * You may obtain a copy of the License at
701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams *
801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams *
1001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * Unless required by applicable law or agreed to in writing, software
1101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
1201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * See the License for the specific language governing permissions and
1401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams * limitations under the License.
1501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams */
1601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
1701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
1801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams#include "rsdCore.h"
1901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams#include "rsdIntrinsics.h"
2001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams#include "rsdAllocation.h"
2101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
2201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams#include "rsdIntrinsicInlines.h"
2301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
2401f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsusing namespace android;
2501f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsusing namespace android::renderscript;
2601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
2701f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsstruct YuvParams {
2801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    ObjectBaseRef<Allocation> alloc;
2901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams};
3001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
3101f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsstatic void YuvToRGB_Bind(const Context *dc, const Script *script,
3201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams                             void * intrinsicData, uint32_t slot, Allocation *data) {
3301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    YuvParams *cp = (YuvParams *)intrinsicData;
3401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    rsAssert(slot == 0);
3501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    cp->alloc.set(data);
3601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
3701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
3801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
3901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
4001f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsstatic uchar4 rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
4101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short Y = ((short)y) - 16;
4201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short U = ((short)u) - 128;
4301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short V = ((short)v) - 128;
4401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
4501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short4 p;
4601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.r = (Y * 298 + V * 409 + 128) >> 8;
4701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.g = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
4801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.b = (Y * 298 + U * 516 + 128) >> 8;
4901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.a = 255;
5001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.r < 0) {
5101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.r = 0;
5201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
5301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.r > 255) {
5401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.r = 255;
5501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
5601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.g < 0) {
5701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.g = 0;
5801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
5901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.g > 255) {
6001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.g = 255;
6101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
6201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.b < 0) {
6301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.b = 0;
6401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
6501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.b > 255) {
6601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.b = 255;
6701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
6801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
6901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    return (uchar4){p.r, p.g, p.b, p.a};
7001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
7101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
72915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
73915aa964a1a312f5e06c115112a3aea14fd31b33Jason Samsstatic short YuvCoeff[] = {
74915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    298, 409, -100, 516,   -208, 255, 0, 0,
75915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    16, 16, 16, 16,        16, 16, 16, 16,
76915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    128, 128, 128, 128, 128, 128, 128, 128,
77915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    298, 298, 298, 298, 298, 298, 298, 298,
78915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    255, 255, 255, 255, 255, 255, 255, 255
79915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
80915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
81915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams};
82915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
83915aa964a1a312f5e06c115112a3aea14fd31b33Jason Samsextern "C" void rsdIntrinsicYuv_K(void *dst, const uchar *Y, const uchar *uv, uint32_t count, const short *param);
8401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
8501f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsstatic void YuvToRGB_uchar4(const RsForEachStubParamStruct *p,
8601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams                                    uint32_t xstart, uint32_t xend,
8701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams                                    uint32_t instep, uint32_t outstep) {
8801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    YuvParams *cp = (YuvParams *)p->usr;
89b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams    if (!cp->alloc.get()) {
90b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams        ALOGE("YuvToRGB executed without input, skipping");
91b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams        return;
92b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams    }
9301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    DrvAllocation *din = (DrvAllocation *)cp->alloc->mHal.drv;
9401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    const uchar *pin = (const uchar *)din->lod[0].mallocPtr;
9501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
9601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    const uchar *Y = pin + (p->y * p->dimX);
9701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    const uchar *uv = pin + (p->dimX * p->dimY);
9801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uv += (p->y>>1) * p->dimX;
9901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
10001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uchar4 *out = (uchar4 *)p->out;
10101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uint32_t x1 = xstart;
10201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uint32_t x2 = xend;
10301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
10401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(x2 > x1) {
105915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams#if defined(ARCH_ARM_HAVE_NEON)
106915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams        int32_t len = (x2 - x1 - 1) >> 3;
10701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        if(len > 0) {
108915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams            rsdIntrinsicYuv_K(out, Y, uv, len, YuvCoeff);
109915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams            x1 += len << 3;
110915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams            out += len << 3;
11101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        }
11201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams#endif
11301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
11401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams       // ALOGE("y %i  %i  %i", p->y, x1, x2);
11501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        while(x1 < x2) {
11601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            uchar u = uv[(x1 & 0xffffe) + 1];
11701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            uchar v = uv[(x1 & 0xffffe) + 0];
11801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
11901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            out++;
12001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            x1++;
12101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
12201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            out++;
12301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            x1++;
12401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        }
12501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
12601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
12701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
12801f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsvoid * rsdIntrinsic_InitYuvToRGB(const android::renderscript::Context *dc,
12901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams                                 android::renderscript::Script *script,
13001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams                                 RsdIntriniscFuncs_t *funcs) {
13101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
13201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    script->mHal.info.exportedVariableCount = 1;
13378b050ea1e13108110ce3b8ead63252e5ebe2468Jason Sams    funcs->setVarObj = YuvToRGB_Bind;
13401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    funcs->root = YuvToRGB_uchar4;
13501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    YuvParams *cp = (YuvParams *)calloc(1, sizeof(YuvParams));
13601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    return cp;
13701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
13801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
13901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
140