1ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams/*
2ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * Copyright (C) 2012 The Android Open Source Project
3ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams *
4ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * you may not use this file except in compliance with the License.
6ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * You may obtain a copy of the License at
7ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams *
8ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams *
10ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * Unless required by applicable law or agreed to in writing, software
11ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * See the License for the specific language governing permissions and
14ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams * limitations under the License.
15ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams */
16ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
17ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
18ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#include "rsdCore.h"
19ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#include "rsdIntrinsics.h"
20ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#include "rsdAllocation.h"
21ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
22ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#include "rsdIntrinsicInlines.h"
23ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
24ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsusing namespace android;
25ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsusing namespace android::renderscript;
26ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
27ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsstruct YuvParams {
28ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    ObjectBaseRef<Allocation> alloc;
29ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams};
30ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
31ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsstatic void YuvToRGB_Bind(const Context *dc, const Script *script,
32ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                             void * intrinsicData, uint32_t slot, Allocation *data) {
33ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    YuvParams *cp = (YuvParams *)intrinsicData;
34ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    rsAssert(slot == 0);
35ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    cp->alloc.set(data);
36ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
37ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
38ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
39ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
40ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsstatic uchar4 rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
41ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    short Y = ((short)y) - 16;
42ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    short U = ((short)u) - 128;
43ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    short V = ((short)v) - 128;
44ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
45ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    short4 p;
46ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    p.r = (Y * 298 + V * 409 + 128) >> 8;
47ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    p.g = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
48ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    p.b = (Y * 298 + U * 516 + 128) >> 8;
49ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    p.a = 255;
50ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(p.r < 0) {
51ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.r = 0;
52ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
53ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(p.r > 255) {
54ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.r = 255;
55ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
56ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(p.g < 0) {
57ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.g = 0;
58ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
59ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(p.g > 255) {
60ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.g = 255;
61ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
62ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(p.b < 0) {
63ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.b = 0;
64ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
65ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(p.b > 255) {
66ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.b = 255;
67ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
68ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
69ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    return (uchar4){p.r, p.g, p.b, p.a};
70ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
71ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
72ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
73ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsstatic short YuvCoeff[] = {
74ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    298, 409, -100, 516,   -208, 255, 0, 0,
75ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    16, 16, 16, 16,        16, 16, 16, 16,
76ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    128, 128, 128, 128, 128, 128, 128, 128,
77ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    298, 298, 298, 298, 298, 298, 298, 298,
78ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    255, 255, 255, 255, 255, 255, 255, 255
79ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
80ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
81ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams};
82ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
83ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsextern "C" void rsdIntrinsicYuv_K(void *dst, const uchar *Y, const uchar *uv, uint32_t count, const short *param);
84ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
85ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsstatic void YuvToRGB_uchar4(const RsForEachStubParamStruct *p,
86ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                    uint32_t xstart, uint32_t xend,
87ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                    uint32_t instep, uint32_t outstep) {
88ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    YuvParams *cp = (YuvParams *)p->usr;
89ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    DrvAllocation *din = (DrvAllocation *)cp->alloc->mHal.drv;
90ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    const uchar *pin = (const uchar *)din->lod[0].mallocPtr;
91ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
92ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    const uchar *Y = pin + (p->y * p->dimX);
93ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    const uchar *uv = pin + (p->dimX * p->dimY);
94ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    uv += (p->y>>1) * p->dimX;
95ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
96ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    uchar4 *out = (uchar4 *)p->out;
97ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    uint32_t x1 = xstart;
98ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    uint32_t x2 = xend;
99ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
100ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if(x2 > x1) {
101ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#if defined(ARCH_ARM_HAVE_NEON)
102ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        int32_t len = (x2 - x1 - 1) >> 3;
103ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        if(len > 0) {
104ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            rsdIntrinsicYuv_K(out, Y, uv, len, YuvCoeff);
105ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            x1 += len << 3;
106ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            out += len << 3;
107ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
108ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#endif
109ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
110ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams       // ALOGE("y %i  %i  %i", p->y, x1, x2);
111ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        while(x1 < x2) {
112ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            uchar u = uv[(x1 & 0xffffe) + 1];
113ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            uchar v = uv[(x1 & 0xffffe) + 0];
114ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
115ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            out++;
116ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            x1++;
117ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
118ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            out++;
119ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            x1++;
120ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        }
121ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
122ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
123ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
124ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsvoid * rsdIntrinsic_InitYuvToRGB(const android::renderscript::Context *dc,
125ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                 android::renderscript::Script *script,
126ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                 RsdIntriniscFuncs_t *funcs) {
127ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
128ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    script->mHal.info.exportedVariableCount = 1;
129ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    funcs->bind = YuvToRGB_Bind;
130ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    funcs->root = YuvToRGB_uchar4;
131ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    YuvParams *cp = (YuvParams *)calloc(1, sizeof(YuvParams));
132ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    return cp;
133ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
134ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
135ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
136