1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker * Copyright (C) 2013 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker *
4*e1eccf28SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker *
8*e1eccf28SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker *
10*e1eccf28SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker */
16*e1eccf28SAndroid Build Coastguard Worker
17*e1eccf28SAndroid Build Coastguard Worker
18*e1eccf28SAndroid Build Coastguard Worker #include "rsCpuIntrinsic.h"
19*e1eccf28SAndroid Build Coastguard Worker #include "rsCpuIntrinsicInlines.h"
20*e1eccf28SAndroid Build Coastguard Worker
21*e1eccf28SAndroid Build Coastguard Worker #ifdef RS_COMPATIBILITY_LIB
22*e1eccf28SAndroid Build Coastguard Worker #include "rsCompatibilityLib.h"
23*e1eccf28SAndroid Build Coastguard Worker #endif
24*e1eccf28SAndroid Build Coastguard Worker
25*e1eccf28SAndroid Build Coastguard Worker #ifndef RS_COMPATIBILITY_LIB
26*e1eccf28SAndroid Build Coastguard Worker #include "hardware/gralloc.h"
27*e1eccf28SAndroid Build Coastguard Worker #endif
28*e1eccf28SAndroid Build Coastguard Worker
29*e1eccf28SAndroid Build Coastguard Worker namespace android {
30*e1eccf28SAndroid Build Coastguard Worker namespace renderscript {
31*e1eccf28SAndroid Build Coastguard Worker
32*e1eccf28SAndroid Build Coastguard Worker
33*e1eccf28SAndroid Build Coastguard Worker class RsdCpuScriptIntrinsicYuvToRGB : public RsdCpuScriptIntrinsic {
34*e1eccf28SAndroid Build Coastguard Worker public:
35*e1eccf28SAndroid Build Coastguard Worker void populateScript(Script *) override;
36*e1eccf28SAndroid Build Coastguard Worker void invokeFreeChildren() override;
37*e1eccf28SAndroid Build Coastguard Worker
38*e1eccf28SAndroid Build Coastguard Worker void setGlobalObj(uint32_t slot, ObjectBase *data) override;
39*e1eccf28SAndroid Build Coastguard Worker
40*e1eccf28SAndroid Build Coastguard Worker ~RsdCpuScriptIntrinsicYuvToRGB() override;
41*e1eccf28SAndroid Build Coastguard Worker RsdCpuScriptIntrinsicYuvToRGB(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e);
42*e1eccf28SAndroid Build Coastguard Worker
43*e1eccf28SAndroid Build Coastguard Worker protected:
44*e1eccf28SAndroid Build Coastguard Worker ObjectBaseRef<Allocation> alloc;
45*e1eccf28SAndroid Build Coastguard Worker
46*e1eccf28SAndroid Build Coastguard Worker static void kernel(const RsExpandKernelDriverInfo *info,
47*e1eccf28SAndroid Build Coastguard Worker uint32_t xstart, uint32_t xend,
48*e1eccf28SAndroid Build Coastguard Worker uint32_t outstep);
49*e1eccf28SAndroid Build Coastguard Worker };
50*e1eccf28SAndroid Build Coastguard Worker
51*e1eccf28SAndroid Build Coastguard Worker
setGlobalObj(uint32_t slot,ObjectBase * data)52*e1eccf28SAndroid Build Coastguard Worker void RsdCpuScriptIntrinsicYuvToRGB::setGlobalObj(uint32_t slot, ObjectBase *data) {
53*e1eccf28SAndroid Build Coastguard Worker rsAssert(slot == 0);
54*e1eccf28SAndroid Build Coastguard Worker alloc.set(static_cast<Allocation *>(data));
55*e1eccf28SAndroid Build Coastguard Worker }
56*e1eccf28SAndroid Build Coastguard Worker
57*e1eccf28SAndroid Build Coastguard Worker
58*e1eccf28SAndroid Build Coastguard Worker
59*e1eccf28SAndroid Build Coastguard Worker
rsYuvToRGBA_uchar4(uchar y,uchar u,uchar v)60*e1eccf28SAndroid Build Coastguard Worker static uchar4 rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
61*e1eccf28SAndroid Build Coastguard Worker int16_t Y = ((int16_t)y) - 16;
62*e1eccf28SAndroid Build Coastguard Worker int16_t U = ((int16_t)u) - 128;
63*e1eccf28SAndroid Build Coastguard Worker int16_t V = ((int16_t)v) - 128;
64*e1eccf28SAndroid Build Coastguard Worker
65*e1eccf28SAndroid Build Coastguard Worker short4 p;
66*e1eccf28SAndroid Build Coastguard Worker p.x = (Y * 298 + V * 409 + 128) >> 8;
67*e1eccf28SAndroid Build Coastguard Worker p.y = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
68*e1eccf28SAndroid Build Coastguard Worker p.z = (Y * 298 + U * 516 + 128) >> 8;
69*e1eccf28SAndroid Build Coastguard Worker p.w = 255;
70*e1eccf28SAndroid Build Coastguard Worker if(p.x < 0) {
71*e1eccf28SAndroid Build Coastguard Worker p.x = 0;
72*e1eccf28SAndroid Build Coastguard Worker }
73*e1eccf28SAndroid Build Coastguard Worker if(p.x > 255) {
74*e1eccf28SAndroid Build Coastguard Worker p.x = 255;
75*e1eccf28SAndroid Build Coastguard Worker }
76*e1eccf28SAndroid Build Coastguard Worker if(p.y < 0) {
77*e1eccf28SAndroid Build Coastguard Worker p.y = 0;
78*e1eccf28SAndroid Build Coastguard Worker }
79*e1eccf28SAndroid Build Coastguard Worker if(p.y > 255) {
80*e1eccf28SAndroid Build Coastguard Worker p.y = 255;
81*e1eccf28SAndroid Build Coastguard Worker }
82*e1eccf28SAndroid Build Coastguard Worker if(p.z < 0) {
83*e1eccf28SAndroid Build Coastguard Worker p.z = 0;
84*e1eccf28SAndroid Build Coastguard Worker }
85*e1eccf28SAndroid Build Coastguard Worker if(p.z > 255) {
86*e1eccf28SAndroid Build Coastguard Worker p.z = 255;
87*e1eccf28SAndroid Build Coastguard Worker }
88*e1eccf28SAndroid Build Coastguard Worker
89*e1eccf28SAndroid Build Coastguard Worker return (uchar4){static_cast<uchar>(p.x), static_cast<uchar>(p.y),
90*e1eccf28SAndroid Build Coastguard Worker static_cast<uchar>(p.z), static_cast<uchar>(p.w)};
91*e1eccf28SAndroid Build Coastguard Worker }
92*e1eccf28SAndroid Build Coastguard Worker
93*e1eccf28SAndroid Build Coastguard Worker
94*e1eccf28SAndroid Build Coastguard Worker extern "C" void rsdIntrinsicYuv_K(void *dst, const uchar *Y, const uchar *uv, uint32_t xstart, size_t xend);
95*e1eccf28SAndroid Build Coastguard Worker extern "C" void rsdIntrinsicYuvR_K(void *dst, const uchar *Y, const uchar *uv, uint32_t xstart, size_t xend);
96*e1eccf28SAndroid Build Coastguard Worker extern "C" void rsdIntrinsicYuv2_K(void *dst, const uchar *Y, const uchar *u, const uchar *v, size_t xstart, size_t xend);
97*e1eccf28SAndroid Build Coastguard Worker
kernel(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)98*e1eccf28SAndroid Build Coastguard Worker void RsdCpuScriptIntrinsicYuvToRGB::kernel(const RsExpandKernelDriverInfo *info,
99*e1eccf28SAndroid Build Coastguard Worker uint32_t xstart, uint32_t xend,
100*e1eccf28SAndroid Build Coastguard Worker uint32_t outstep) {
101*e1eccf28SAndroid Build Coastguard Worker RsdCpuScriptIntrinsicYuvToRGB *cp = (RsdCpuScriptIntrinsicYuvToRGB *)info->usr;
102*e1eccf28SAndroid Build Coastguard Worker if (!cp->alloc.get()) {
103*e1eccf28SAndroid Build Coastguard Worker ALOGE("YuvToRGB executed without input, skipping");
104*e1eccf28SAndroid Build Coastguard Worker return;
105*e1eccf28SAndroid Build Coastguard Worker }
106*e1eccf28SAndroid Build Coastguard Worker const uchar *pinY = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
107*e1eccf28SAndroid Build Coastguard Worker if (pinY == nullptr) {
108*e1eccf28SAndroid Build Coastguard Worker ALOGE("YuvToRGB executed without data, skipping");
109*e1eccf28SAndroid Build Coastguard Worker return;
110*e1eccf28SAndroid Build Coastguard Worker }
111*e1eccf28SAndroid Build Coastguard Worker
112*e1eccf28SAndroid Build Coastguard Worker size_t strideY = cp->alloc->mHal.drvState.lod[0].stride;
113*e1eccf28SAndroid Build Coastguard Worker
114*e1eccf28SAndroid Build Coastguard Worker // calculate correct stride in legacy case
115*e1eccf28SAndroid Build Coastguard Worker if (cp->alloc->mHal.drvState.lod[0].dimY == 0) {
116*e1eccf28SAndroid Build Coastguard Worker strideY = info->dim.x;
117*e1eccf28SAndroid Build Coastguard Worker }
118*e1eccf28SAndroid Build Coastguard Worker const uchar *Y = pinY + (info->current.y * strideY);
119*e1eccf28SAndroid Build Coastguard Worker
120*e1eccf28SAndroid Build Coastguard Worker uchar4 *out = (uchar4 *)info->outPtr[0] + xstart;
121*e1eccf28SAndroid Build Coastguard Worker uint32_t x1 = xstart;
122*e1eccf28SAndroid Build Coastguard Worker uint32_t x2 = xend;
123*e1eccf28SAndroid Build Coastguard Worker
124*e1eccf28SAndroid Build Coastguard Worker size_t cstep = cp->alloc->mHal.drvState.yuv.step;
125*e1eccf28SAndroid Build Coastguard Worker
126*e1eccf28SAndroid Build Coastguard Worker const uchar *pinU = (const uchar *)cp->alloc->mHal.drvState.lod[1].mallocPtr;
127*e1eccf28SAndroid Build Coastguard Worker const size_t strideU = cp->alloc->mHal.drvState.lod[1].stride;
128*e1eccf28SAndroid Build Coastguard Worker const uchar *u = pinU + ((info->current.y >> 1) * strideU);
129*e1eccf28SAndroid Build Coastguard Worker
130*e1eccf28SAndroid Build Coastguard Worker const uchar *pinV = (const uchar *)cp->alloc->mHal.drvState.lod[2].mallocPtr;
131*e1eccf28SAndroid Build Coastguard Worker const size_t strideV = cp->alloc->mHal.drvState.lod[2].stride;
132*e1eccf28SAndroid Build Coastguard Worker const uchar *v = pinV + ((info->current.y >> 1) * strideV);
133*e1eccf28SAndroid Build Coastguard Worker
134*e1eccf28SAndroid Build Coastguard Worker //ALOGE("pinY, %p, Y, %p, info->current.y, %d, strideY, %d", pinY, Y, info->current.y, strideY);
135*e1eccf28SAndroid Build Coastguard Worker //ALOGE("pinU, %p, U, %p, info->current.y, %d, strideU, %d", pinU, u, info->current.y, strideU);
136*e1eccf28SAndroid Build Coastguard Worker //ALOGE("pinV, %p, V, %p, info->current.y, %d, strideV, %d", pinV, v, info->current.y, strideV);
137*e1eccf28SAndroid Build Coastguard Worker //ALOGE("dimX, %d, dimY, %d", cp->alloc->mHal.drvState.lod[0].dimX, cp->alloc->mHal.drvState.lod[0].dimY);
138*e1eccf28SAndroid Build Coastguard Worker //ALOGE("info->dim.x, %d, info->dim.y, %d", info->dim.x, info->dim.y);
139*e1eccf28SAndroid Build Coastguard Worker
140*e1eccf28SAndroid Build Coastguard Worker if (pinU == nullptr) {
141*e1eccf28SAndroid Build Coastguard Worker // Legacy yuv support didn't fill in uv
142*e1eccf28SAndroid Build Coastguard Worker v = ((uint8_t *)cp->alloc->mHal.drvState.lod[0].mallocPtr) +
143*e1eccf28SAndroid Build Coastguard Worker (strideY * info->dim.y) +
144*e1eccf28SAndroid Build Coastguard Worker ((info->current.y >> 1) * strideY);
145*e1eccf28SAndroid Build Coastguard Worker u = v + 1;
146*e1eccf28SAndroid Build Coastguard Worker cstep = 2;
147*e1eccf28SAndroid Build Coastguard Worker }
148*e1eccf28SAndroid Build Coastguard Worker
149*e1eccf28SAndroid Build Coastguard Worker /* If we start on an odd pixel then deal with it here and bump things along
150*e1eccf28SAndroid Build Coastguard Worker * so that subsequent code can carry on with even-odd pairing assumptions.
151*e1eccf28SAndroid Build Coastguard Worker */
152*e1eccf28SAndroid Build Coastguard Worker if((x1 & 1) && (x2 > x1)) {
153*e1eccf28SAndroid Build Coastguard Worker int cx = (x1 >> 1) * cstep;
154*e1eccf28SAndroid Build Coastguard Worker *out = rsYuvToRGBA_uchar4(Y[x1], u[cx], v[cx]);
155*e1eccf28SAndroid Build Coastguard Worker out++;
156*e1eccf28SAndroid Build Coastguard Worker x1++;
157*e1eccf28SAndroid Build Coastguard Worker }
158*e1eccf28SAndroid Build Coastguard Worker
159*e1eccf28SAndroid Build Coastguard Worker #if defined(ARCH_ARM_USE_INTRINSICS)
160*e1eccf28SAndroid Build Coastguard Worker if((x2 > x1) && gArchUseSIMD) {
161*e1eccf28SAndroid Build Coastguard Worker int32_t len = x2 - x1;
162*e1eccf28SAndroid Build Coastguard Worker if (cstep == 1) {
163*e1eccf28SAndroid Build Coastguard Worker rsdIntrinsicYuv2_K(info->outPtr[0], Y, u, v, x1, x2);
164*e1eccf28SAndroid Build Coastguard Worker x1 += len;
165*e1eccf28SAndroid Build Coastguard Worker out += len;
166*e1eccf28SAndroid Build Coastguard Worker } else if (cstep == 2) {
167*e1eccf28SAndroid Build Coastguard Worker // Check for proper interleave
168*e1eccf28SAndroid Build Coastguard Worker intptr_t ipu = (intptr_t)u;
169*e1eccf28SAndroid Build Coastguard Worker intptr_t ipv = (intptr_t)v;
170*e1eccf28SAndroid Build Coastguard Worker
171*e1eccf28SAndroid Build Coastguard Worker if (ipu == (ipv + 1)) {
172*e1eccf28SAndroid Build Coastguard Worker rsdIntrinsicYuv_K(info->outPtr[0], Y, v, x1, x2);
173*e1eccf28SAndroid Build Coastguard Worker x1 += len;
174*e1eccf28SAndroid Build Coastguard Worker out += len;
175*e1eccf28SAndroid Build Coastguard Worker } else if (ipu == (ipv - 1)) {
176*e1eccf28SAndroid Build Coastguard Worker rsdIntrinsicYuvR_K(info->outPtr[0], Y, u, x1, x2);
177*e1eccf28SAndroid Build Coastguard Worker x1 += len;
178*e1eccf28SAndroid Build Coastguard Worker out += len;
179*e1eccf28SAndroid Build Coastguard Worker }
180*e1eccf28SAndroid Build Coastguard Worker }
181*e1eccf28SAndroid Build Coastguard Worker }
182*e1eccf28SAndroid Build Coastguard Worker #endif
183*e1eccf28SAndroid Build Coastguard Worker
184*e1eccf28SAndroid Build Coastguard Worker if(x2 > x1) {
185*e1eccf28SAndroid Build Coastguard Worker // ALOGE("y %i %i %i", info->current.y, x1, x2);
186*e1eccf28SAndroid Build Coastguard Worker while(x1 < x2) {
187*e1eccf28SAndroid Build Coastguard Worker int cx = (x1 >> 1) * cstep;
188*e1eccf28SAndroid Build Coastguard Worker *out = rsYuvToRGBA_uchar4(Y[x1], u[cx], v[cx]);
189*e1eccf28SAndroid Build Coastguard Worker out++;
190*e1eccf28SAndroid Build Coastguard Worker x1++;
191*e1eccf28SAndroid Build Coastguard Worker *out = rsYuvToRGBA_uchar4(Y[x1], u[cx], v[cx]);
192*e1eccf28SAndroid Build Coastguard Worker out++;
193*e1eccf28SAndroid Build Coastguard Worker x1++;
194*e1eccf28SAndroid Build Coastguard Worker }
195*e1eccf28SAndroid Build Coastguard Worker }
196*e1eccf28SAndroid Build Coastguard Worker
197*e1eccf28SAndroid Build Coastguard Worker }
198*e1eccf28SAndroid Build Coastguard Worker
RsdCpuScriptIntrinsicYuvToRGB(RsdCpuReferenceImpl * ctx,const Script * s,const Element * e)199*e1eccf28SAndroid Build Coastguard Worker RsdCpuScriptIntrinsicYuvToRGB::RsdCpuScriptIntrinsicYuvToRGB(
200*e1eccf28SAndroid Build Coastguard Worker RsdCpuReferenceImpl *ctx, const Script *s, const Element *e)
201*e1eccf28SAndroid Build Coastguard Worker : RsdCpuScriptIntrinsic(ctx, s, e, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB) {
202*e1eccf28SAndroid Build Coastguard Worker
203*e1eccf28SAndroid Build Coastguard Worker mRootPtr = &kernel;
204*e1eccf28SAndroid Build Coastguard Worker }
205*e1eccf28SAndroid Build Coastguard Worker
~RsdCpuScriptIntrinsicYuvToRGB()206*e1eccf28SAndroid Build Coastguard Worker RsdCpuScriptIntrinsicYuvToRGB::~RsdCpuScriptIntrinsicYuvToRGB() {
207*e1eccf28SAndroid Build Coastguard Worker }
208*e1eccf28SAndroid Build Coastguard Worker
populateScript(Script * s)209*e1eccf28SAndroid Build Coastguard Worker void RsdCpuScriptIntrinsicYuvToRGB::populateScript(Script *s) {
210*e1eccf28SAndroid Build Coastguard Worker s->mHal.info.exportedVariableCount = 1;
211*e1eccf28SAndroid Build Coastguard Worker }
212*e1eccf28SAndroid Build Coastguard Worker
invokeFreeChildren()213*e1eccf28SAndroid Build Coastguard Worker void RsdCpuScriptIntrinsicYuvToRGB::invokeFreeChildren() {
214*e1eccf28SAndroid Build Coastguard Worker alloc.clear();
215*e1eccf28SAndroid Build Coastguard Worker }
216*e1eccf28SAndroid Build Coastguard Worker
rsdIntrinsic_YuvToRGB(RsdCpuReferenceImpl * ctx,const Script * s,const Element * e)217*e1eccf28SAndroid Build Coastguard Worker RsdCpuScriptImpl * rsdIntrinsic_YuvToRGB(RsdCpuReferenceImpl *ctx,
218*e1eccf28SAndroid Build Coastguard Worker const Script *s, const Element *e) {
219*e1eccf28SAndroid Build Coastguard Worker return new RsdCpuScriptIntrinsicYuvToRGB(ctx, s, e);
220*e1eccf28SAndroid Build Coastguard Worker }
221*e1eccf28SAndroid Build Coastguard Worker
222*e1eccf28SAndroid Build Coastguard Worker } // namespace renderscript
223*e1eccf28SAndroid Build Coastguard Worker } // namespace android
224