1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker * Copyright (C) 2012 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 #include <cstdint>
18*e1eccf28SAndroid Build Coastguard Worker
19*e1eccf28SAndroid Build Coastguard Worker #include "RenderScriptToolkit.h"
20*e1eccf28SAndroid Build Coastguard Worker #include "TaskProcessor.h"
21*e1eccf28SAndroid Build Coastguard Worker #include "Utils.h"
22*e1eccf28SAndroid Build Coastguard Worker
23*e1eccf28SAndroid Build Coastguard Worker namespace android {
24*e1eccf28SAndroid Build Coastguard Worker namespace renderscript {
25*e1eccf28SAndroid Build Coastguard Worker
26*e1eccf28SAndroid Build Coastguard Worker #define LOG_TAG "renderscript.toolkit.Lut3d"
27*e1eccf28SAndroid Build Coastguard Worker
28*e1eccf28SAndroid Build Coastguard Worker /**
29*e1eccf28SAndroid Build Coastguard Worker * Converts a RGBA buffer using a 3D cube.
30*e1eccf28SAndroid Build Coastguard Worker */
31*e1eccf28SAndroid Build Coastguard Worker class Lut3dTask : public Task {
32*e1eccf28SAndroid Build Coastguard Worker // The input array we're transforming.
33*e1eccf28SAndroid Build Coastguard Worker const uchar4* mIn;
34*e1eccf28SAndroid Build Coastguard Worker // Where we'll store the transformed result.
35*e1eccf28SAndroid Build Coastguard Worker uchar4* mOut;
36*e1eccf28SAndroid Build Coastguard Worker // The size of each of the three cube dimensions. We don't make use of the last value.
37*e1eccf28SAndroid Build Coastguard Worker int4 mCubeDimension;
38*e1eccf28SAndroid Build Coastguard Worker // The translation cube, in row major format.
39*e1eccf28SAndroid Build Coastguard Worker const uchar* mCubeTable;
40*e1eccf28SAndroid Build Coastguard Worker
41*e1eccf28SAndroid Build Coastguard Worker /**
42*e1eccf28SAndroid Build Coastguard Worker * Converts a subset of a line of the 2D buffer.
43*e1eccf28SAndroid Build Coastguard Worker *
44*e1eccf28SAndroid Build Coastguard Worker * @param in The start of the data to transform.
45*e1eccf28SAndroid Build Coastguard Worker * @param out Where to store the result.
46*e1eccf28SAndroid Build Coastguard Worker * @param length The number of 4-byte vectors to transform.
47*e1eccf28SAndroid Build Coastguard Worker */
48*e1eccf28SAndroid Build Coastguard Worker void kernel(const uchar4* in, uchar4* out, uint32_t length);
49*e1eccf28SAndroid Build Coastguard Worker
50*e1eccf28SAndroid Build Coastguard Worker // Process a 2D tile of the overall work. threadIndex identifies which thread does the work.
51*e1eccf28SAndroid Build Coastguard Worker virtual void processData(int threadIndex, size_t startX, size_t startY, size_t endX,
52*e1eccf28SAndroid Build Coastguard Worker size_t endY) override;
53*e1eccf28SAndroid Build Coastguard Worker
54*e1eccf28SAndroid Build Coastguard Worker public:
Lut3dTask(const uint8_t * input,uint8_t * output,size_t sizeX,size_t sizeY,const uint8_t * cube,int cubeSizeX,int cubeSizeY,int cubeSizeZ,const Restriction * restriction)55*e1eccf28SAndroid Build Coastguard Worker Lut3dTask(const uint8_t* input, uint8_t* output, size_t sizeX, size_t sizeY,
56*e1eccf28SAndroid Build Coastguard Worker const uint8_t* cube, int cubeSizeX, int cubeSizeY, int cubeSizeZ,
57*e1eccf28SAndroid Build Coastguard Worker const Restriction* restriction)
58*e1eccf28SAndroid Build Coastguard Worker : Task{sizeX, sizeY, 4, true, restriction},
59*e1eccf28SAndroid Build Coastguard Worker mIn{reinterpret_cast<const uchar4*>(input)},
60*e1eccf28SAndroid Build Coastguard Worker mOut{reinterpret_cast<uchar4*>(output)},
61*e1eccf28SAndroid Build Coastguard Worker mCubeDimension{cubeSizeX, cubeSizeY, cubeSizeZ, 0},
62*e1eccf28SAndroid Build Coastguard Worker mCubeTable{cube} {}
63*e1eccf28SAndroid Build Coastguard Worker };
64*e1eccf28SAndroid Build Coastguard Worker
65*e1eccf28SAndroid Build Coastguard Worker extern "C" void rsdIntrinsic3DLUT_K(void* dst, void const* in, size_t count, void const* lut,
66*e1eccf28SAndroid Build Coastguard Worker int32_t pitchy, int32_t pitchz, int dimx, int dimy, int dimz);
67*e1eccf28SAndroid Build Coastguard Worker
kernel(const uchar4 * in,uchar4 * out,uint32_t length)68*e1eccf28SAndroid Build Coastguard Worker void Lut3dTask::kernel(const uchar4* in, uchar4* out, uint32_t length) {
69*e1eccf28SAndroid Build Coastguard Worker uint32_t x1 = 0;
70*e1eccf28SAndroid Build Coastguard Worker uint32_t x2 = length;
71*e1eccf28SAndroid Build Coastguard Worker
72*e1eccf28SAndroid Build Coastguard Worker const uchar* bp = mCubeTable;
73*e1eccf28SAndroid Build Coastguard Worker
74*e1eccf28SAndroid Build Coastguard Worker int4 dims = mCubeDimension - 1;
75*e1eccf28SAndroid Build Coastguard Worker
76*e1eccf28SAndroid Build Coastguard Worker const float4 m = (float4)(1.f / 255.f) * convert<float4>(dims);
77*e1eccf28SAndroid Build Coastguard Worker const int4 coordMul = convert<int4>(m * (float4)0x8000);
78*e1eccf28SAndroid Build Coastguard Worker const size_t stride_y = mCubeDimension.x * 4;
79*e1eccf28SAndroid Build Coastguard Worker const size_t stride_z = stride_y * mCubeDimension.y;
80*e1eccf28SAndroid Build Coastguard Worker
81*e1eccf28SAndroid Build Coastguard Worker // ALOGE("strides %zu %zu", stride_y, stride_z);
82*e1eccf28SAndroid Build Coastguard Worker
83*e1eccf28SAndroid Build Coastguard Worker #if defined(ARCH_ARM_USE_INTRINSICS)
84*e1eccf28SAndroid Build Coastguard Worker if (mUsesSimd) {
85*e1eccf28SAndroid Build Coastguard Worker int32_t len = x2 - x1;
86*e1eccf28SAndroid Build Coastguard Worker if (len > 0) {
87*e1eccf28SAndroid Build Coastguard Worker rsdIntrinsic3DLUT_K(out, in, len, bp, stride_y, stride_z, dims.x, dims.y, dims.z);
88*e1eccf28SAndroid Build Coastguard Worker x1 += len;
89*e1eccf28SAndroid Build Coastguard Worker out += len;
90*e1eccf28SAndroid Build Coastguard Worker in += len;
91*e1eccf28SAndroid Build Coastguard Worker }
92*e1eccf28SAndroid Build Coastguard Worker }
93*e1eccf28SAndroid Build Coastguard Worker #endif
94*e1eccf28SAndroid Build Coastguard Worker
95*e1eccf28SAndroid Build Coastguard Worker while (x1 < x2) {
96*e1eccf28SAndroid Build Coastguard Worker int4 baseCoord = convert<int4>(*in) * coordMul;
97*e1eccf28SAndroid Build Coastguard Worker int4 coord1 = baseCoord >> (int4)15;
98*e1eccf28SAndroid Build Coastguard Worker // int4 coord2 = min(coord1 + 1, gDims - 1);
99*e1eccf28SAndroid Build Coastguard Worker
100*e1eccf28SAndroid Build Coastguard Worker int4 weight2 = baseCoord & 0x7fff;
101*e1eccf28SAndroid Build Coastguard Worker int4 weight1 = (int4)0x8000 - weight2;
102*e1eccf28SAndroid Build Coastguard Worker
103*e1eccf28SAndroid Build Coastguard Worker // ALOGE("coord1 %08x %08x %08x %08x", coord1.x, coord1.y, coord1.z, coord1.w);
104*e1eccf28SAndroid Build Coastguard Worker const uchar* bp2 = bp + (coord1.x * 4) + (coord1.y * stride_y) + (coord1.z * stride_z);
105*e1eccf28SAndroid Build Coastguard Worker const uchar4* pt_00 = (const uchar4*)&bp2[0];
106*e1eccf28SAndroid Build Coastguard Worker const uchar4* pt_10 = (const uchar4*)&bp2[stride_y];
107*e1eccf28SAndroid Build Coastguard Worker const uchar4* pt_01 = (const uchar4*)&bp2[stride_z];
108*e1eccf28SAndroid Build Coastguard Worker const uchar4* pt_11 = (const uchar4*)&bp2[stride_y + stride_z];
109*e1eccf28SAndroid Build Coastguard Worker
110*e1eccf28SAndroid Build Coastguard Worker uint4 v000 = convert<uint4>(pt_00[0]);
111*e1eccf28SAndroid Build Coastguard Worker uint4 v100 = convert<uint4>(pt_00[1]);
112*e1eccf28SAndroid Build Coastguard Worker uint4 v010 = convert<uint4>(pt_10[0]);
113*e1eccf28SAndroid Build Coastguard Worker uint4 v110 = convert<uint4>(pt_10[1]);
114*e1eccf28SAndroid Build Coastguard Worker uint4 v001 = convert<uint4>(pt_01[0]);
115*e1eccf28SAndroid Build Coastguard Worker uint4 v101 = convert<uint4>(pt_01[1]);
116*e1eccf28SAndroid Build Coastguard Worker uint4 v011 = convert<uint4>(pt_11[0]);
117*e1eccf28SAndroid Build Coastguard Worker uint4 v111 = convert<uint4>(pt_11[1]);
118*e1eccf28SAndroid Build Coastguard Worker
119*e1eccf28SAndroid Build Coastguard Worker uint4 yz00 = ((v000 * weight1.x) + (v100 * weight2.x)) >> (int4)7;
120*e1eccf28SAndroid Build Coastguard Worker uint4 yz10 = ((v010 * weight1.x) + (v110 * weight2.x)) >> (int4)7;
121*e1eccf28SAndroid Build Coastguard Worker uint4 yz01 = ((v001 * weight1.x) + (v101 * weight2.x)) >> (int4)7;
122*e1eccf28SAndroid Build Coastguard Worker uint4 yz11 = ((v011 * weight1.x) + (v111 * weight2.x)) >> (int4)7;
123*e1eccf28SAndroid Build Coastguard Worker
124*e1eccf28SAndroid Build Coastguard Worker uint4 z0 = ((yz00 * weight1.y) + (yz10 * weight2.y)) >> (int4)15;
125*e1eccf28SAndroid Build Coastguard Worker uint4 z1 = ((yz01 * weight1.y) + (yz11 * weight2.y)) >> (int4)15;
126*e1eccf28SAndroid Build Coastguard Worker
127*e1eccf28SAndroid Build Coastguard Worker uint4 v = ((z0 * weight1.z) + (z1 * weight2.z)) >> (int4)15;
128*e1eccf28SAndroid Build Coastguard Worker uint4 v2 = (v + 0x7f) >> (int4)8;
129*e1eccf28SAndroid Build Coastguard Worker
130*e1eccf28SAndroid Build Coastguard Worker uchar4 ret = convert<uchar4>(v2);
131*e1eccf28SAndroid Build Coastguard Worker ret.w = in->w;
132*e1eccf28SAndroid Build Coastguard Worker
133*e1eccf28SAndroid Build Coastguard Worker #if 0
134*e1eccf28SAndroid Build Coastguard Worker if (!x1) {
135*e1eccf28SAndroid Build Coastguard Worker ALOGE("in %08x %08x %08x %08x", in->r, in->g, in->b, in->a);
136*e1eccf28SAndroid Build Coastguard Worker ALOGE("baseCoord %08x %08x %08x %08x", baseCoord.x, baseCoord.y, baseCoord.z,
137*e1eccf28SAndroid Build Coastguard Worker baseCoord.w);
138*e1eccf28SAndroid Build Coastguard Worker ALOGE("coord1 %08x %08x %08x %08x", coord1.x, coord1.y, coord1.z, coord1.w);
139*e1eccf28SAndroid Build Coastguard Worker ALOGE("weight1 %08x %08x %08x %08x", weight1.x, weight1.y, weight1.z, weight1.w);
140*e1eccf28SAndroid Build Coastguard Worker ALOGE("weight2 %08x %08x %08x %08x", weight2.x, weight2.y, weight2.z, weight2.w);
141*e1eccf28SAndroid Build Coastguard Worker
142*e1eccf28SAndroid Build Coastguard Worker ALOGE("v000 %08x %08x %08x %08x", v000.x, v000.y, v000.z, v000.w);
143*e1eccf28SAndroid Build Coastguard Worker ALOGE("v100 %08x %08x %08x %08x", v100.x, v100.y, v100.z, v100.w);
144*e1eccf28SAndroid Build Coastguard Worker ALOGE("yz00 %08x %08x %08x %08x", yz00.x, yz00.y, yz00.z, yz00.w);
145*e1eccf28SAndroid Build Coastguard Worker ALOGE("z0 %08x %08x %08x %08x", z0.x, z0.y, z0.z, z0.w);
146*e1eccf28SAndroid Build Coastguard Worker
147*e1eccf28SAndroid Build Coastguard Worker ALOGE("v %08x %08x %08x %08x", v.x, v.y, v.z, v.w);
148*e1eccf28SAndroid Build Coastguard Worker ALOGE("v2 %08x %08x %08x %08x", v2.x, v2.y, v2.z, v2.w);
149*e1eccf28SAndroid Build Coastguard Worker }
150*e1eccf28SAndroid Build Coastguard Worker #endif
151*e1eccf28SAndroid Build Coastguard Worker *out = ret;
152*e1eccf28SAndroid Build Coastguard Worker
153*e1eccf28SAndroid Build Coastguard Worker in++;
154*e1eccf28SAndroid Build Coastguard Worker out++;
155*e1eccf28SAndroid Build Coastguard Worker x1++;
156*e1eccf28SAndroid Build Coastguard Worker }
157*e1eccf28SAndroid Build Coastguard Worker }
158*e1eccf28SAndroid Build Coastguard Worker
processData(int,size_t startX,size_t startY,size_t endX,size_t endY)159*e1eccf28SAndroid Build Coastguard Worker void Lut3dTask::processData(int /* threadIndex */, size_t startX, size_t startY, size_t endX,
160*e1eccf28SAndroid Build Coastguard Worker size_t endY) {
161*e1eccf28SAndroid Build Coastguard Worker for (size_t y = startY; y < endY; y++) {
162*e1eccf28SAndroid Build Coastguard Worker size_t offset = mSizeX * y + startX;
163*e1eccf28SAndroid Build Coastguard Worker kernel(mIn + offset, mOut + offset, endX - startX);
164*e1eccf28SAndroid Build Coastguard Worker }
165*e1eccf28SAndroid Build Coastguard Worker }
166*e1eccf28SAndroid Build Coastguard Worker
lut3d(const uint8_t * input,uint8_t * output,size_t sizeX,size_t sizeY,const uint8_t * cube,size_t cubeSizeX,size_t cubeSizeY,size_t cubeSizeZ,const Restriction * restriction)167*e1eccf28SAndroid Build Coastguard Worker void RenderScriptToolkit::lut3d(const uint8_t* input, uint8_t* output, size_t sizeX, size_t sizeY,
168*e1eccf28SAndroid Build Coastguard Worker const uint8_t* cube, size_t cubeSizeX, size_t cubeSizeY,
169*e1eccf28SAndroid Build Coastguard Worker size_t cubeSizeZ, const Restriction* restriction) {
170*e1eccf28SAndroid Build Coastguard Worker #ifdef ANDROID_RENDERSCRIPT_TOOLKIT_VALIDATE
171*e1eccf28SAndroid Build Coastguard Worker if (!validRestriction(LOG_TAG, sizeX, sizeY, restriction)) {
172*e1eccf28SAndroid Build Coastguard Worker return;
173*e1eccf28SAndroid Build Coastguard Worker }
174*e1eccf28SAndroid Build Coastguard Worker #endif
175*e1eccf28SAndroid Build Coastguard Worker
176*e1eccf28SAndroid Build Coastguard Worker Lut3dTask task(input, output, sizeX, sizeY, cube, cubeSizeX, cubeSizeY, cubeSizeZ, restriction);
177*e1eccf28SAndroid Build Coastguard Worker processor->doTask(&task);
178*e1eccf28SAndroid Build Coastguard Worker }
179*e1eccf28SAndroid Build Coastguard Worker
180*e1eccf28SAndroid Build Coastguard Worker } // namespace renderscript
181*e1eccf28SAndroid Build Coastguard Worker } // namespace android
182