1*32afb93cSXin Li /*
2*32afb93cSXin Li  * Copyright (C) 2012 The Android Open Source Project
3*32afb93cSXin Li  *
4*32afb93cSXin Li  * Licensed under the Apache License, Version 2.0 (the "License");
5*32afb93cSXin Li  * you may not use this file except in compliance with the License.
6*32afb93cSXin Li  * You may obtain a copy of the License at
7*32afb93cSXin Li  *
8*32afb93cSXin Li  *      http://www.apache.org/licenses/LICENSE-2.0
9*32afb93cSXin Li  *
10*32afb93cSXin Li  * Unless required by applicable law or agreed to in writing, software
11*32afb93cSXin Li  * distributed under the License is distributed on an "AS IS" BASIS,
12*32afb93cSXin Li  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*32afb93cSXin Li  * See the License for the specific language governing permissions and
14*32afb93cSXin Li  * limitations under the License.
15*32afb93cSXin Li  */
16*32afb93cSXin Li 
17*32afb93cSXin Li #include <cassert>
18*32afb93cSXin Li #include <cstdint>
19*32afb93cSXin Li 
20*32afb93cSXin Li #include "RenderScriptToolkit.h"
21*32afb93cSXin Li #include "TaskProcessor.h"
22*32afb93cSXin Li #include "Utils.h"
23*32afb93cSXin Li 
24*32afb93cSXin Li namespace renderscript {
25*32afb93cSXin Li 
26*32afb93cSXin Li #define LOG_TAG "renderscript.toolkit.Blend"
27*32afb93cSXin Li 
28*32afb93cSXin Li /**
29*32afb93cSXin Li  * Blends a source into a destination, based on the mode.
30*32afb93cSXin Li  */
31*32afb93cSXin Li class BlendTask : public Task {
32*32afb93cSXin Li     // The type of blending to do.
33*32afb93cSXin Li     RenderScriptToolkit::BlendingMode mMode;
34*32afb93cSXin Li     // The input we're blending.
35*32afb93cSXin Li     const uchar4* mIn;
36*32afb93cSXin Li     // The destination, used both for input and output.
37*32afb93cSXin Li     uchar4* mOut;
38*32afb93cSXin Li 
39*32afb93cSXin Li     void blend(RenderScriptToolkit::BlendingMode mode, const uchar4* in, uchar4* out,
40*32afb93cSXin Li                uint32_t length);
41*32afb93cSXin Li     // Process a 2D tile of the overall work. threadIndex identifies which thread does the work.
42*32afb93cSXin Li     void processData(int threadIndex, size_t startX, size_t startY, size_t endX,
43*32afb93cSXin Li                      size_t endY) override;
44*32afb93cSXin Li 
45*32afb93cSXin Li    public:
BlendTask(RenderScriptToolkit::BlendingMode mode,const uint8_t * in,uint8_t * out,size_t sizeX,size_t sizeY,const Restriction * restriction)46*32afb93cSXin Li     BlendTask(RenderScriptToolkit::BlendingMode mode, const uint8_t* in, uint8_t* out, size_t sizeX,
47*32afb93cSXin Li               size_t sizeY, const Restriction* restriction)
48*32afb93cSXin Li         : Task{sizeX, sizeY, 4, true, restriction},
49*32afb93cSXin Li           mMode{mode},
50*32afb93cSXin Li           mIn{reinterpret_cast<const uchar4*>(in)},
51*32afb93cSXin Li           mOut{reinterpret_cast<uchar4*>(out)} {}
52*32afb93cSXin Li };
53*32afb93cSXin Li 
54*32afb93cSXin Li #if defined(ARCH_ARM_USE_INTRINSICS)
55*32afb93cSXin Li extern "C" int rsdIntrinsicBlend_K(uchar4 *out, uchar4 const *in, int slot,
56*32afb93cSXin Li                     uint32_t xstart, uint32_t xend);
57*32afb93cSXin Li #endif
58*32afb93cSXin Li 
59*32afb93cSXin Li #if defined(ARCH_X86_HAVE_SSSE3)
60*32afb93cSXin Li extern void rsdIntrinsicBlendSrcOver_K(void *dst, const void *src, uint32_t count8);
61*32afb93cSXin Li extern void rsdIntrinsicBlendDstOver_K(void *dst, const void *src, uint32_t count8);
62*32afb93cSXin Li extern void rsdIntrinsicBlendSrcIn_K(void *dst, const void *src, uint32_t count8);
63*32afb93cSXin Li extern void rsdIntrinsicBlendDstIn_K(void *dst, const void *src, uint32_t count8);
64*32afb93cSXin Li extern void rsdIntrinsicBlendSrcOut_K(void *dst, const void *src, uint32_t count8);
65*32afb93cSXin Li extern void rsdIntrinsicBlendDstOut_K(void *dst, const void *src, uint32_t count8);
66*32afb93cSXin Li extern void rsdIntrinsicBlendSrcAtop_K(void *dst, const void *src, uint32_t count8);
67*32afb93cSXin Li extern void rsdIntrinsicBlendDstAtop_K(void *dst, const void *src, uint32_t count8);
68*32afb93cSXin Li extern void rsdIntrinsicBlendXor_K(void *dst, const void *src, uint32_t count8);
69*32afb93cSXin Li extern void rsdIntrinsicBlendMultiply_K(void *dst, const void *src, uint32_t count8);
70*32afb93cSXin Li extern void rsdIntrinsicBlendAdd_K(void *dst, const void *src, uint32_t count8);
71*32afb93cSXin Li extern void rsdIntrinsicBlendSub_K(void *dst, const void *src, uint32_t count8);
72*32afb93cSXin Li #endif
73*32afb93cSXin Li 
74*32afb93cSXin Li // Convert vector to uchar4, clipping each value to 255.
75*32afb93cSXin Li template <typename TI>
convertClipped(TI amount)76*32afb93cSXin Li static inline uchar4 convertClipped(TI amount) {
77*32afb93cSXin Li     return uchar4 { static_cast<uchar>(amount.x > 255 ? 255 : amount.x),
78*32afb93cSXin Li                     static_cast<uchar>(amount.y > 255 ? 255 : amount.y),
79*32afb93cSXin Li                     static_cast<uchar>(amount.z > 255 ? 255 : amount.z),
80*32afb93cSXin Li                     static_cast<uchar>(amount.w > 255 ? 255 : amount.w)};
81*32afb93cSXin Li }
82*32afb93cSXin Li 
blend(RenderScriptToolkit::BlendingMode mode,const uchar4 * in,uchar4 * out,uint32_t length)83*32afb93cSXin Li void BlendTask::blend(RenderScriptToolkit::BlendingMode mode, const uchar4* in, uchar4* out,
84*32afb93cSXin Li                       uint32_t length) {
85*32afb93cSXin Li     uint32_t x1 = 0;
86*32afb93cSXin Li     uint32_t x2 = length;
87*32afb93cSXin Li 
88*32afb93cSXin Li #if defined(ARCH_ARM_USE_INTRINSICS)
89*32afb93cSXin Li     if (mUsesSimd) {
90*32afb93cSXin Li         if (rsdIntrinsicBlend_K(out, in, (int) mode, x1, x2) >= 0) {
91*32afb93cSXin Li             return;
92*32afb93cSXin Li         } else {
93*32afb93cSXin Li             ALOGW("Intrinsic Blend failed to use SIMD for %d", mode);
94*32afb93cSXin Li         }
95*32afb93cSXin Li     }
96*32afb93cSXin Li #endif
97*32afb93cSXin Li     switch (mode) {
98*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::CLEAR:
99*32afb93cSXin Li         for (;x1 < x2; x1++, out++) {
100*32afb93cSXin Li             *out = 0;
101*32afb93cSXin Li         }
102*32afb93cSXin Li         break;
103*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::SRC:
104*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
105*32afb93cSXin Li           *out = *in;
106*32afb93cSXin Li         }
107*32afb93cSXin Li         break;
108*32afb93cSXin Li     //RenderScriptToolkit::BlendingMode::DST is a NOP
109*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::DST:
110*32afb93cSXin Li         break;
111*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::SRC_OVER:
112*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
113*32afb93cSXin Li         if (mUsesSimd) {
114*32afb93cSXin Li             if ((x1 + 8) < x2) {
115*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
116*32afb93cSXin Li                 rsdIntrinsicBlendSrcOver_K(out, in, len);
117*32afb93cSXin Li                 x1 += len << 3;
118*32afb93cSXin Li                 out += len << 3;
119*32afb93cSXin Li                 in += len << 3;
120*32afb93cSXin Li             }
121*32afb93cSXin Li         }
122*32afb93cSXin Li     #endif
123*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
124*32afb93cSXin Li             ushort4 in_s = convert<ushort4>(*in);
125*32afb93cSXin Li             ushort4 out_s = convert<ushort4>(*out);
126*32afb93cSXin Li             in_s = in_s + ((out_s * (ushort4)(255 - in_s.w)) >> (ushort4)8);
127*32afb93cSXin Li             *out = convertClipped(in_s);
128*32afb93cSXin Li         }
129*32afb93cSXin Li         break;
130*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::DST_OVER:
131*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
132*32afb93cSXin Li         if (mUsesSimd) {
133*32afb93cSXin Li             if ((x1 + 8) < x2) {
134*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
135*32afb93cSXin Li                 rsdIntrinsicBlendDstOver_K(out, in, len);
136*32afb93cSXin Li                 x1 += len << 3;
137*32afb93cSXin Li                 out += len << 3;
138*32afb93cSXin Li                 in += len << 3;
139*32afb93cSXin Li             }
140*32afb93cSXin Li         }
141*32afb93cSXin Li      #endif
142*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
143*32afb93cSXin Li             ushort4 in_s = convert<ushort4>(*in);
144*32afb93cSXin Li             ushort4 out_s = convert<ushort4>(*out);
145*32afb93cSXin Li             in_s = out_s + ((in_s * (ushort4)(255 - out_s.w)) >> (ushort4)8);
146*32afb93cSXin Li             *out = convertClipped(in_s);
147*32afb93cSXin Li         }
148*32afb93cSXin Li         break;
149*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::SRC_IN:
150*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
151*32afb93cSXin Li         if (mUsesSimd) {
152*32afb93cSXin Li             if ((x1 + 8) < x2) {
153*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
154*32afb93cSXin Li                 rsdIntrinsicBlendSrcIn_K(out, in, len);
155*32afb93cSXin Li                 x1 += len << 3;
156*32afb93cSXin Li                 out += len << 3;
157*32afb93cSXin Li                 in += len << 3;
158*32afb93cSXin Li             }
159*32afb93cSXin Li         }
160*32afb93cSXin Li #endif
161*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
162*32afb93cSXin Li             ushort4 in_s = convert<ushort4>(*in);
163*32afb93cSXin Li             in_s = (in_s * out->w) >> (ushort4)8;
164*32afb93cSXin Li             *out = convert<uchar4>(in_s);
165*32afb93cSXin Li         }
166*32afb93cSXin Li         break;
167*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::DST_IN:
168*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
169*32afb93cSXin Li         if (mUsesSimd) {
170*32afb93cSXin Li             if ((x1 + 8) < x2) {
171*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
172*32afb93cSXin Li                 rsdIntrinsicBlendDstIn_K(out, in, len);
173*32afb93cSXin Li                 x1 += len << 3;
174*32afb93cSXin Li                 out += len << 3;
175*32afb93cSXin Li                 in += len << 3;
176*32afb93cSXin Li             }
177*32afb93cSXin Li         }
178*32afb93cSXin Li      #endif
179*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
180*32afb93cSXin Li             ushort4 out_s = convert<ushort4>(*out);
181*32afb93cSXin Li             out_s = (out_s * in->w) >> (ushort4)8;
182*32afb93cSXin Li             *out = convert<uchar4>(out_s);
183*32afb93cSXin Li         }
184*32afb93cSXin Li         break;
185*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::SRC_OUT:
186*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
187*32afb93cSXin Li         if (mUsesSimd) {
188*32afb93cSXin Li             if ((x1 + 8) < x2) {
189*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
190*32afb93cSXin Li                 rsdIntrinsicBlendSrcOut_K(out, in, len);
191*32afb93cSXin Li                 x1 += len << 3;
192*32afb93cSXin Li                 out += len << 3;
193*32afb93cSXin Li                 in += len << 3;
194*32afb93cSXin Li             }
195*32afb93cSXin Li         }
196*32afb93cSXin Li     #endif
197*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
198*32afb93cSXin Li             ushort4 in_s = convert<ushort4>(*in);
199*32afb93cSXin Li             in_s = (in_s * (ushort4)(255 - out->w)) >> (ushort4)8;
200*32afb93cSXin Li             *out = convert<uchar4>(in_s);
201*32afb93cSXin Li         }
202*32afb93cSXin Li         break;
203*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::DST_OUT:
204*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
205*32afb93cSXin Li         if (mUsesSimd) {
206*32afb93cSXin Li             if ((x1 + 8) < x2) {
207*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
208*32afb93cSXin Li                 rsdIntrinsicBlendDstOut_K(out, in, len);
209*32afb93cSXin Li                 x1 += len << 3;
210*32afb93cSXin Li                 out += len << 3;
211*32afb93cSXin Li                 in += len << 3;
212*32afb93cSXin Li             }
213*32afb93cSXin Li         }
214*32afb93cSXin Li     #endif
215*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
216*32afb93cSXin Li             ushort4 out_s = convert<ushort4>(*out);
217*32afb93cSXin Li             out_s = (out_s * (ushort4)(255 - in->w)) >> (ushort4)8;
218*32afb93cSXin Li             *out = convert<uchar4>(out_s);
219*32afb93cSXin Li         }
220*32afb93cSXin Li         break;
221*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::SRC_ATOP:
222*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
223*32afb93cSXin Li         if (mUsesSimd) {
224*32afb93cSXin Li             if ((x1 + 8) < x2) {
225*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
226*32afb93cSXin Li                 rsdIntrinsicBlendSrcAtop_K(out, in, len);
227*32afb93cSXin Li                 x1 += len << 3;
228*32afb93cSXin Li                 out += len << 3;
229*32afb93cSXin Li                 in += len << 3;
230*32afb93cSXin Li             }
231*32afb93cSXin Li         }
232*32afb93cSXin Li     #endif
233*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
234*32afb93cSXin Li             // The max value the operation could produce before the shift
235*32afb93cSXin Li             // is 255 * 255 + 255 * (255 - 0) = 130050, or 0x1FC02.
236*32afb93cSXin Li             // That value does not fit in a ushort, so we use uint.
237*32afb93cSXin Li             uint4 in_s = convert<uint4>(*in);
238*32afb93cSXin Li             uint4 out_s = convert<uint4>(*out);
239*32afb93cSXin Li             out_s.xyz = ((in_s.xyz * out_s.w) +
240*32afb93cSXin Li               (out_s.xyz * ((uint3)255 - (uint3)in_s.w))) >> (uint3)8;
241*32afb93cSXin Li             *out = convertClipped(out_s);
242*32afb93cSXin Li         }
243*32afb93cSXin Li         break;
244*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::DST_ATOP:
245*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
246*32afb93cSXin Li         if (mUsesSimd) {
247*32afb93cSXin Li             if ((x1 + 8) < x2) {
248*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
249*32afb93cSXin Li                 rsdIntrinsicBlendDstAtop_K(out, in, len);
250*32afb93cSXin Li                 x1 += len << 3;
251*32afb93cSXin Li                 out += len << 3;
252*32afb93cSXin Li                 in += len << 3;
253*32afb93cSXin Li             }
254*32afb93cSXin Li         }
255*32afb93cSXin Li      #endif
256*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
257*32afb93cSXin Li             uint4 in_s = convert<uint4>(*in);
258*32afb93cSXin Li             uint4 out_s = convert<uint4>(*out);
259*32afb93cSXin Li             out_s.xyz = ((out_s.xyz * in_s.w) +
260*32afb93cSXin Li               (in_s.xyz * ((uint3)255 - (uint3)out_s.w))) >> (uint3)8;
261*32afb93cSXin Li             out_s.w = in_s.w;
262*32afb93cSXin Li             *out = convertClipped(out_s);
263*32afb93cSXin Li         }
264*32afb93cSXin Li         break;
265*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::XOR:
266*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
267*32afb93cSXin Li         if (mUsesSimd) {
268*32afb93cSXin Li             if ((x1 + 8) < x2) {
269*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
270*32afb93cSXin Li                 rsdIntrinsicBlendXor_K(out, in, len);
271*32afb93cSXin Li                 x1 += len << 3;
272*32afb93cSXin Li                 out += len << 3;
273*32afb93cSXin Li                 in += len << 3;
274*32afb93cSXin Li             }
275*32afb93cSXin Li         }
276*32afb93cSXin Li     #endif
277*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
278*32afb93cSXin Li             *out = *in ^ *out;
279*32afb93cSXin Li         }
280*32afb93cSXin Li         break;
281*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::MULTIPLY:
282*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
283*32afb93cSXin Li         if (mUsesSimd) {
284*32afb93cSXin Li             if ((x1 + 8) < x2) {
285*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
286*32afb93cSXin Li                 rsdIntrinsicBlendMultiply_K(out, in, len);
287*32afb93cSXin Li                 x1 += len << 3;
288*32afb93cSXin Li                 out += len << 3;
289*32afb93cSXin Li                 in += len << 3;
290*32afb93cSXin Li             }
291*32afb93cSXin Li         }
292*32afb93cSXin Li     #endif
293*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
294*32afb93cSXin Li           *out = convert<uchar4>((convert<ushort4>(*in) * convert<ushort4>(*out))
295*32afb93cSXin Li                                 >> (ushort4)8);
296*32afb93cSXin Li         }
297*32afb93cSXin Li         break;
298*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::ADD:
299*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
300*32afb93cSXin Li         if (mUsesSimd) {
301*32afb93cSXin Li             if((x1 + 8) < x2) {
302*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
303*32afb93cSXin Li                 rsdIntrinsicBlendAdd_K(out, in, len);
304*32afb93cSXin Li                 x1 += len << 3;
305*32afb93cSXin Li                 out += len << 3;
306*32afb93cSXin Li                 in += len << 3;
307*32afb93cSXin Li             }
308*32afb93cSXin Li         }
309*32afb93cSXin Li     #endif
310*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
311*32afb93cSXin Li             uint32_t iR = in->x, iG = in->y, iB = in->z, iA = in->w,
312*32afb93cSXin Li                 oR = out->x, oG = out->y, oB = out->z, oA = out->w;
313*32afb93cSXin Li             out->x = (oR + iR) > 255 ? 255 : oR + iR;
314*32afb93cSXin Li             out->y = (oG + iG) > 255 ? 255 : oG + iG;
315*32afb93cSXin Li             out->z = (oB + iB) > 255 ? 255 : oB + iB;
316*32afb93cSXin Li             out->w = (oA + iA) > 255 ? 255 : oA + iA;
317*32afb93cSXin Li         }
318*32afb93cSXin Li         break;
319*32afb93cSXin Li     case RenderScriptToolkit::BlendingMode::SUBTRACT:
320*32afb93cSXin Li     #if defined(ARCH_X86_HAVE_SSSE3)
321*32afb93cSXin Li         if (mUsesSimd) {
322*32afb93cSXin Li             if((x1 + 8) < x2) {
323*32afb93cSXin Li                 uint32_t len = (x2 - x1) >> 3;
324*32afb93cSXin Li                 rsdIntrinsicBlendSub_K(out, in, len);
325*32afb93cSXin Li                 x1 += len << 3;
326*32afb93cSXin Li                 out += len << 3;
327*32afb93cSXin Li                 in += len << 3;
328*32afb93cSXin Li             }
329*32afb93cSXin Li         }
330*32afb93cSXin Li     #endif
331*32afb93cSXin Li         for (;x1 < x2; x1++, out++, in++) {
332*32afb93cSXin Li             int32_t iR = in->x, iG = in->y, iB = in->z, iA = in->w,
333*32afb93cSXin Li                 oR = out->x, oG = out->y, oB = out->z, oA = out->w;
334*32afb93cSXin Li             out->x = (oR - iR) < 0 ? 0 : oR - iR;
335*32afb93cSXin Li             out->y = (oG - iG) < 0 ? 0 : oG - iG;
336*32afb93cSXin Li             out->z = (oB - iB) < 0 ? 0 : oB - iB;
337*32afb93cSXin Li             out->w = (oA - iA) < 0 ? 0 : oA - iA;
338*32afb93cSXin Li         }
339*32afb93cSXin Li         break;
340*32afb93cSXin Li 
341*32afb93cSXin Li     default:
342*32afb93cSXin Li         ALOGE("Called unimplemented value %d", mode);
343*32afb93cSXin Li         assert(false);
344*32afb93cSXin Li     }
345*32afb93cSXin Li }
346*32afb93cSXin Li 
processData(int,size_t startX,size_t startY,size_t endX,size_t endY)347*32afb93cSXin Li void BlendTask::processData(int /* threadIndex */, size_t startX, size_t startY, size_t endX,
348*32afb93cSXin Li                             size_t endY) {
349*32afb93cSXin Li     for (size_t y = startY; y < endY; y++) {
350*32afb93cSXin Li         size_t offset = y * mSizeX + startX;
351*32afb93cSXin Li         blend(mMode, mIn + offset, mOut + offset, endX - startX);
352*32afb93cSXin Li     }
353*32afb93cSXin Li }
354*32afb93cSXin Li 
blend(BlendingMode mode,const uint8_t * in,uint8_t * out,size_t sizeX,size_t sizeY,const Restriction * restriction)355*32afb93cSXin Li void RenderScriptToolkit::blend(BlendingMode mode, const uint8_t* in, uint8_t* out, size_t sizeX,
356*32afb93cSXin Li                                 size_t sizeY, const Restriction* restriction) {
357*32afb93cSXin Li #ifdef ANDROID_RENDERSCRIPT_TOOLKIT_VALIDATE
358*32afb93cSXin Li     if (!validRestriction(LOG_TAG, sizeX, sizeY, restriction)) {
359*32afb93cSXin Li         return;
360*32afb93cSXin Li     }
361*32afb93cSXin Li #endif
362*32afb93cSXin Li 
363*32afb93cSXin Li     BlendTask task(mode, in, out, sizeX, sizeY, restriction);
364*32afb93cSXin Li     processor->doTask(&task);
365*32afb93cSXin Li }
366*32afb93cSXin Li 
367*32afb93cSXin Li }  // namespace google::android::renderscript
368