xref: /aosp_15_r20/frameworks/rs/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
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