rsCpuIntrinsicYuvToRGB.cpp revision c905efd76fdcc1b8846b229bf7d991d185a7b4b7
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
18709a0978ae141198018ca9769f8d96292a8928e6Jason Sams#include "rsCpuIntrinsic.h"
19709a0978ae141198018ca9769f8d96292a8928e6Jason Sams#include "rsCpuIntrinsicInlines.h"
2001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
2101f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsusing namespace android;
2201f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsusing namespace android::renderscript;
2301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
24709a0978ae141198018ca9769f8d96292a8928e6Jason Samsnamespace android {
25709a0978ae141198018ca9769f8d96292a8928e6Jason Samsnamespace renderscript {
26709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
27709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
28709a0978ae141198018ca9769f8d96292a8928e6Jason Samsclass RsdCpuScriptIntrinsicYuvToRGB : public RsdCpuScriptIntrinsic {
29709a0978ae141198018ca9769f8d96292a8928e6Jason Samspublic:
30709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    virtual void populateScript(Script *);
31709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    virtual void invokeFreeChildren();
32709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
33709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    virtual void setGlobalObj(uint32_t slot, ObjectBase *data);
34709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
35709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    virtual ~RsdCpuScriptIntrinsicYuvToRGB();
36c905efd76fdcc1b8846b229bf7d991d185a7b4b7Jason Sams    RsdCpuScriptIntrinsicYuvToRGB(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e);
37709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
38709a0978ae141198018ca9769f8d96292a8928e6Jason Samsprotected:
3901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    ObjectBaseRef<Allocation> alloc;
40709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
41709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    static void kernel(const RsForEachStubParamStruct *p,
42709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                       uint32_t xstart, uint32_t xend,
43709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                       uint32_t instep, uint32_t outstep);
4401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams};
4501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
46709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
47709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
48709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
49709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
50709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptIntrinsicYuvToRGB::setGlobalObj(uint32_t slot, ObjectBase *data) {
5101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    rsAssert(slot == 0);
52709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    alloc.set(static_cast<Allocation *>(data));
5301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
5401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
5501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
5601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
57709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
5801f03a04da629b9a3e3ff33287dd277b12c54148Jason Samsstatic uchar4 rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
5901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short Y = ((short)y) - 16;
6001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short U = ((short)u) - 128;
6101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short V = ((short)v) - 128;
6201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
6301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    short4 p;
6401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.r = (Y * 298 + V * 409 + 128) >> 8;
6501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.g = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
6601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.b = (Y * 298 + U * 516 + 128) >> 8;
6701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    p.a = 255;
6801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.r < 0) {
6901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.r = 0;
7001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
7101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.r > 255) {
7201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.r = 255;
7301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
7401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.g < 0) {
7501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.g = 0;
7601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
7701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.g > 255) {
7801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.g = 255;
7901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
8001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.b < 0) {
8101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.b = 0;
8201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
8301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(p.b > 255) {
8401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        p.b = 255;
8501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
8601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
8701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    return (uchar4){p.r, p.g, p.b, p.a};
8801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
8901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
90915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
91915aa964a1a312f5e06c115112a3aea14fd31b33Jason Samsstatic short YuvCoeff[] = {
92915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    298, 409, -100, 516,   -208, 255, 0, 0,
93915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    16, 16, 16, 16,        16, 16, 16, 16,
94915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    128, 128, 128, 128, 128, 128, 128, 128,
95915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    298, 298, 298, 298, 298, 298, 298, 298,
96915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams    255, 255, 255, 255, 255, 255, 255, 255
97915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
98915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
99915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams};
100915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams
101915aa964a1a312f5e06c115112a3aea14fd31b33Jason Samsextern "C" void rsdIntrinsicYuv_K(void *dst, const uchar *Y, const uchar *uv, uint32_t count, const short *param);
10201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
103709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptIntrinsicYuvToRGB::kernel(const RsForEachStubParamStruct *p,
104709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                           uint32_t xstart, uint32_t xend,
105709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                           uint32_t instep, uint32_t outstep) {
106709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    RsdCpuScriptIntrinsicYuvToRGB *cp = (RsdCpuScriptIntrinsicYuvToRGB *)p->usr;
107b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams    if (!cp->alloc.get()) {
108b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams        ALOGE("YuvToRGB executed without input, skipping");
109b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams        return;
110b801b949e286275b5d19a33135235ba68d3a19a9Jason Sams    }
111709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
112709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
11301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
11401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    const uchar *Y = pin + (p->y * p->dimX);
11501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    const uchar *uv = pin + (p->dimX * p->dimY);
11601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uv += (p->y>>1) * p->dimX;
11701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
11801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uchar4 *out = (uchar4 *)p->out;
11901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uint32_t x1 = xstart;
12001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    uint32_t x2 = xend;
12101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
12201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    if(x2 > x1) {
123915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams#if defined(ARCH_ARM_HAVE_NEON)
124915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams        int32_t len = (x2 - x1 - 1) >> 3;
12501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        if(len > 0) {
126915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams            rsdIntrinsicYuv_K(out, Y, uv, len, YuvCoeff);
127915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams            x1 += len << 3;
128915aa964a1a312f5e06c115112a3aea14fd31b33Jason Sams            out += len << 3;
12901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        }
13001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams#endif
13101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
13201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams       // ALOGE("y %i  %i  %i", p->y, x1, x2);
13301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        while(x1 < x2) {
13401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            uchar u = uv[(x1 & 0xffffe) + 1];
13501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            uchar v = uv[(x1 & 0xffffe) + 0];
13601f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
13701f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            out++;
13801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            x1++;
13901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
14001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            out++;
14101f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams            x1++;
14201f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams        }
14301f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams    }
14401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
14501f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
146709a0978ae141198018ca9769f8d96292a8928e6Jason SamsRsdCpuScriptIntrinsicYuvToRGB::RsdCpuScriptIntrinsicYuvToRGB(
147c905efd76fdcc1b8846b229bf7d991d185a7b4b7Jason Sams            RsdCpuReferenceImpl *ctx, const Script *s, const Element *e)
148c905efd76fdcc1b8846b229bf7d991d185a7b4b7Jason Sams            : RsdCpuScriptIntrinsic(ctx, s, e, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB) {
149709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
150709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mRootPtr = &kernel;
151709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
152709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
153709a0978ae141198018ca9769f8d96292a8928e6Jason SamsRsdCpuScriptIntrinsicYuvToRGB::~RsdCpuScriptIntrinsicYuvToRGB() {
154709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
155709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
156709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptIntrinsicYuvToRGB::populateScript(Script *s) {
157709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    s->mHal.info.exportedVariableCount = 1;
158709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
159709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
160709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptIntrinsicYuvToRGB::invokeFreeChildren() {
161709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    alloc.clear();
162709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
163709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
16401f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
165c905efd76fdcc1b8846b229bf7d991d185a7b4b7Jason SamsRsdCpuScriptImpl * rsdIntrinsic_YuvToRGB(RsdCpuReferenceImpl *ctx,
166c905efd76fdcc1b8846b229bf7d991d185a7b4b7Jason Sams                                         const Script *s, const Element *e) {
167c905efd76fdcc1b8846b229bf7d991d185a7b4b7Jason Sams    return new RsdCpuScriptIntrinsicYuvToRGB(ctx, s, e);
16801f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams}
16901f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
17001f03a04da629b9a3e3ff33287dd277b12c54148Jason Sams
171