blob: d36729bf271e7f21e86ca3efb0fc418a2493bd01 [file] [log] [blame]
Jason Sams709a0972012-11-15 18:18:04 -08001/*
Jason Samsbc0ca6b2013-02-15 18:13:43 -08002 * Copyright (C) 2013 The Android Open Source Project
Jason Sams709a0972012-11-15 18:18:04 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#include "rsCpuIntrinsic.h"
19#include "rsCpuIntrinsicInlines.h"
20
Tim Murrayaa782372013-08-29 18:42:54 -070021#ifdef RS_COMPATIBILITY_LIB
22#include "rsCompatibilityLib.h"
23#endif
24
Jason Sams6b589092013-04-19 14:32:31 -070025#ifndef RS_COMPATIBILITY_LIB
26#include "hardware/gralloc.h"
27#endif
28
Jason Sams709a0972012-11-15 18:18:04 -080029using namespace android;
30using namespace android::renderscript;
31
32namespace android {
33namespace renderscript {
34
35
36class RsdCpuScriptIntrinsicYuvToRGB : public RsdCpuScriptIntrinsic {
37public:
38 virtual void populateScript(Script *);
39 virtual void invokeFreeChildren();
40
41 virtual void setGlobalObj(uint32_t slot, ObjectBase *data);
42
43 virtual ~RsdCpuScriptIntrinsicYuvToRGB();
Jason Samsc905efd2012-11-26 15:20:18 -080044 RsdCpuScriptIntrinsicYuvToRGB(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e);
Jason Sams709a0972012-11-15 18:18:04 -080045
46protected:
47 ObjectBaseRef<Allocation> alloc;
48
49 static void kernel(const RsForEachStubParamStruct *p,
50 uint32_t xstart, uint32_t xend,
51 uint32_t instep, uint32_t outstep);
52};
53
54}
55}
56
57
58void RsdCpuScriptIntrinsicYuvToRGB::setGlobalObj(uint32_t slot, ObjectBase *data) {
59 rsAssert(slot == 0);
60 alloc.set(static_cast<Allocation *>(data));
61}
62
63
64
65
66static uchar4 rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
67 short Y = ((short)y) - 16;
68 short U = ((short)u) - 128;
69 short V = ((short)v) - 128;
70
71 short4 p;
Tim Murray0b575de2013-03-15 15:56:43 -070072 p.x = (Y * 298 + V * 409 + 128) >> 8;
73 p.y = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
74 p.z = (Y * 298 + U * 516 + 128) >> 8;
75 p.w = 255;
76 if(p.x < 0) {
77 p.x = 0;
Jason Sams709a0972012-11-15 18:18:04 -080078 }
Tim Murray0b575de2013-03-15 15:56:43 -070079 if(p.x > 255) {
80 p.x = 255;
Jason Sams709a0972012-11-15 18:18:04 -080081 }
Tim Murray0b575de2013-03-15 15:56:43 -070082 if(p.y < 0) {
83 p.y = 0;
Jason Sams709a0972012-11-15 18:18:04 -080084 }
Tim Murray0b575de2013-03-15 15:56:43 -070085 if(p.y > 255) {
86 p.y = 255;
Jason Sams709a0972012-11-15 18:18:04 -080087 }
Tim Murray0b575de2013-03-15 15:56:43 -070088 if(p.z < 0) {
89 p.z = 0;
Jason Sams709a0972012-11-15 18:18:04 -080090 }
Tim Murray0b575de2013-03-15 15:56:43 -070091 if(p.z > 255) {
92 p.z = 255;
Jason Sams709a0972012-11-15 18:18:04 -080093 }
94
Tim Murray0b575de2013-03-15 15:56:43 -070095 return (uchar4){p.x, p.y, p.z, p.w};
Jason Sams709a0972012-11-15 18:18:04 -080096}
97
98
99static short YuvCoeff[] = {
100 298, 409, -100, 516, -208, 255, 0, 0,
101 16, 16, 16, 16, 16, 16, 16, 16,
102 128, 128, 128, 128, 128, 128, 128, 128,
103 298, 298, 298, 298, 298, 298, 298, 298,
104 255, 255, 255, 255, 255, 255, 255, 255
105
106
107};
108
109extern "C" void rsdIntrinsicYuv_K(void *dst, const uchar *Y, const uchar *uv, uint32_t count, const short *param);
Jason Sams61656a72013-09-03 16:21:18 -0700110extern "C" void rsdIntrinsicYuvR_K(void *dst, const uchar *Y, const uchar *uv, uint32_t count, const short *param);
Jason Sams6b589092013-04-19 14:32:31 -0700111extern "C" void rsdIntrinsicYuv2_K(void *dst, const uchar *Y, const uchar *u, const uchar *v, uint32_t count, const short *param);
Jason Sams709a0972012-11-15 18:18:04 -0800112
113void RsdCpuScriptIntrinsicYuvToRGB::kernel(const RsForEachStubParamStruct *p,
114 uint32_t xstart, uint32_t xend,
115 uint32_t instep, uint32_t outstep) {
116 RsdCpuScriptIntrinsicYuvToRGB *cp = (RsdCpuScriptIntrinsicYuvToRGB *)p->usr;
117 if (!cp->alloc.get()) {
118 ALOGE("YuvToRGB executed without input, skipping");
119 return;
120 }
Jason Samsbc0ca6b2013-02-15 18:13:43 -0800121 const uchar *pinY = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
Jason Samse99f3e22013-09-11 18:18:54 -0700122 if (pinY == NULL) {
123 ALOGE("YuvToRGB executed without data, skipping");
124 return;
125 }
Tim Murray606e5002013-06-13 12:33:49 -0700126
127 size_t strideY = cp->alloc->mHal.drvState.lod[0].stride;
128
129 // calculate correct stride in legacy case
130 if (cp->alloc->mHal.drvState.lod[0].dimY == 0) {
131 strideY = p->dimX;
132 }
Jason Samsbc0ca6b2013-02-15 18:13:43 -0800133 const uchar *Y = pinY + (p->y * strideY);
Jason Sams709a0972012-11-15 18:18:04 -0800134
Tim Murray606e5002013-06-13 12:33:49 -0700135 // ALOGE("pinY, %p, Y, %p, p->y, %d, strideY, %d", pinY, Y, p->y, strideY);
136 // ALOGE("dimX, %d, dimY, %d", cp->alloc->mHal.drvState.lod[0].dimX, cp->alloc->mHal.drvState.lod[0].dimY);
137 // ALOGE("p->dimX, %d, p->dimY, %d", p->dimX, p->dimY);
138
Jason Sams709a0972012-11-15 18:18:04 -0800139 uchar4 *out = (uchar4 *)p->out;
140 uint32_t x1 = xstart;
141 uint32_t x2 = xend;
142
Jason Sams61656a72013-09-03 16:21:18 -0700143 const size_t cstep = cp->alloc->mHal.drvState.yuv.step;
Jason Sams709a0972012-11-15 18:18:04 -0800144
Jason Sams61656a72013-09-03 16:21:18 -0700145 const uchar *pinU = (const uchar *)cp->alloc->mHal.drvState.lod[1].mallocPtr;
146 const size_t strideU = cp->alloc->mHal.drvState.lod[1].stride;
147 const uchar *u = pinU + ((p->y >> 1) * strideU);
Jason Sams06bd91e2013-06-11 18:38:11 -0700148
Jason Sams61656a72013-09-03 16:21:18 -0700149 const uchar *pinV = (const uchar *)cp->alloc->mHal.drvState.lod[2].mallocPtr;
150 const size_t strideV = cp->alloc->mHal.drvState.lod[2].stride;
151 const uchar *v = pinV + ((p->y >> 1) * strideV);
152
153 if (pinU == NULL) {
154 // Legacy yuv support didn't fill in uv
155 v = ((uint8_t *)cp->alloc->mHal.drvState.lod[0].mallocPtr) +
156 (strideY * p->dimY) +
157 ((p->y >> 1) * strideY);
158 u = v + 1;
159 }
160
161#if defined(ARCH_ARM_HAVE_VFP)
162 if((x2 > x1) && gArchUseSIMD) {
163 int32_t len = (x2 - x1 - 1) >> 3;
164 if(len > 0) {
165 if (cstep == 1) {
166 rsdIntrinsicYuv2_K(out, Y, u, v, len, YuvCoeff);
167 x1 += len << 3;
168 out += len << 3;
169 } else if (cstep == 2) {
170 // Check for proper interleave
171 intptr_t ipu = (intptr_t)u;
172 intptr_t ipv = (intptr_t)v;
173
174 if (ipu == (ipv + 1)) {
175 rsdIntrinsicYuv_K(out, Y, v, len, YuvCoeff);
176 x1 += len << 3;
177 out += len << 3;
178 } else if (ipu == (ipv - 1)) {
179 rsdIntrinsicYuvR_K(out, Y, u, len, YuvCoeff);
180 x1 += len << 3;
181 out += len << 3;
Jason Sams6b589092013-04-19 14:32:31 -0700182 }
Jason Sams6b589092013-04-19 14:32:31 -0700183
Jason Sams6b589092013-04-19 14:32:31 -0700184 }
Jason Sams709a0972012-11-15 18:18:04 -0800185 }
Jason Sams61656a72013-09-03 16:21:18 -0700186 }
Jason Sams6b589092013-04-19 14:32:31 -0700187#endif
Jason Sams61656a72013-09-03 16:21:18 -0700188
189 if(x2 > x1) {
190 // ALOGE("y %i %i %i", p->y, x1, x2);
191 while(x1 < x2) {
192 int cx = (x1 >> 1) * cstep;
193 *out = rsYuvToRGBA_uchar4(Y[x1], u[cx], v[cx]);
194 out++;
195 x1++;
196 *out = rsYuvToRGBA_uchar4(Y[x1], u[cx], v[cx]);
197 out++;
198 x1++;
199 }
Jason Sams709a0972012-11-15 18:18:04 -0800200 }
Jason Sams6b589092013-04-19 14:32:31 -0700201
Jason Sams709a0972012-11-15 18:18:04 -0800202}
203
204RsdCpuScriptIntrinsicYuvToRGB::RsdCpuScriptIntrinsicYuvToRGB(
Jason Samsc905efd2012-11-26 15:20:18 -0800205 RsdCpuReferenceImpl *ctx, const Script *s, const Element *e)
206 : RsdCpuScriptIntrinsic(ctx, s, e, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB) {
Jason Sams709a0972012-11-15 18:18:04 -0800207
208 mRootPtr = &kernel;
209}
210
211RsdCpuScriptIntrinsicYuvToRGB::~RsdCpuScriptIntrinsicYuvToRGB() {
212}
213
214void RsdCpuScriptIntrinsicYuvToRGB::populateScript(Script *s) {
215 s->mHal.info.exportedVariableCount = 1;
216}
217
218void RsdCpuScriptIntrinsicYuvToRGB::invokeFreeChildren() {
219 alloc.clear();
220}
221
222
Jason Samsc905efd2012-11-26 15:20:18 -0800223RsdCpuScriptImpl * rsdIntrinsic_YuvToRGB(RsdCpuReferenceImpl *ctx,
224 const Script *s, const Element *e) {
225 return new RsdCpuScriptIntrinsicYuvToRGB(ctx, s, e);
Jason Sams709a0972012-11-15 18:18:04 -0800226}
227
228