• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "soft_blit.h"
17 #include <string>
18 #include <unordered_map>
19 #include <algorithm>
20 #include "display_test.h"
21 
22 #define R_PIX_OFFSET 0
23 #define G_PIX_OFFSET 8
24 #define B_PIX_OFFSET 16
25 #define A_PIX_OFFSET 24
26 
27 namespace {
28 const int MAX_FLOAT_TO_INT32 = 2147483520;
29 const int MIN_FLOAT_TO_INT32 = -2147483520;
30 
31 using BlendFunction = void (*)(ColorRGBAf &src, ColorRGBAf &dst);
32 
RgbaGetR(uint32_t color)33 static inline uint32_t RgbaGetR(uint32_t color)
34 {
35     return ((color >> 0) & 0xFF);
36 }
37 
RgbaGetG(uint32_t color)38 static inline uint32_t RgbaGetG(uint32_t color)
39 {
40     const uint32_t shift = 8;
41     const uint32_t mask = 0xFF;
42     return ((color >> shift) & mask);
43 }
44 
RgbaGetB(uint32_t color)45 static inline uint32_t RgbaGetB(uint32_t color)
46 {
47     const uint32_t shift = 16;
48     const uint32_t mask = 0xFF;
49     return ((color >> shift) & mask);
50 }
51 
RgbaGetA(uint32_t color)52 static inline uint32_t RgbaGetA(uint32_t color)
53 {
54     const uint32_t shift = 24;
55     const uint32_t mask = 0xFF;
56     return ((color >> shift) & mask);
57 }
58 
ColorSetARGB(uint8_t r,uint8_t g,uint8_t b,uint8_t a)59 static constexpr inline uint32_t ColorSetARGB(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
60 {
61     return (r << R_PIX_OFFSET) | (g << G_PIX_OFFSET) | (b << B_PIX_OFFSET) | (a << A_PIX_OFFSET);
62 }
63 
64 // blend none
65 /*
66 fs: sa      fd: 1.0-sa
67 pixel = (foreground x fs + background x fd)
68 */
BlendNone(const ColorRGBAf & src,ColorRGBAf & dst)69 static inline void BlendNone(const ColorRGBAf &src, ColorRGBAf &dst)
70 {
71     dst.mR = src.mR * src.mA + dst.mR * (1 - src.mA);
72     dst.mG = src.mG * src.mA + dst.mG * (1 - src.mA);
73     dst.mB = src.mB * src.mA + dst.mB * (1 - src.mA);
74     dst.mA = src.mA * src.mA + dst.mA * (1 - src.mA);
75 }
76 
77 // blend clear
BlendClear(ColorRGBAf & src,ColorRGBAf & dst)78 static inline void BlendClear(ColorRGBAf &src, ColorRGBAf &dst)
79 {
80     (void)src;
81     dst.mA = 0;
82     dst.mR = 0;
83     dst.mG = 0;
84     dst.mB = 0;
85 }
86 
87 // blend src
BlendSrc(const ColorRGBAf & src,ColorRGBAf & dst)88 static inline void BlendSrc(const ColorRGBAf &src, ColorRGBAf &dst)
89 {
90     dst = src;
91 }
92 
93 // blend src over
BlendSrcOver(ColorRGBAf & src,ColorRGBAf & dst)94 static inline void BlendSrcOver(ColorRGBAf &src, ColorRGBAf &dst)
95 {
96     // the display_gfx has Premultiplied
97     src.mR *= src.mA;
98     src.mG *= src.mA;
99     src.mB *= src.mA;
100 
101     dst.mR = src.mR + (1 - src.mA) * dst.mR;
102     dst.mG = src.mG + (1 - src.mA) * dst.mG;
103     dst.mB = src.mB + (1 - src.mA) * dst.mB;
104     dst.mA = src.mA + (1 - src.mA) * dst.mA;
105 }
106 
107 // blend src in
BlendSrcIn(const ColorRGBAf & src,ColorRGBAf & dst)108 static inline void BlendSrcIn(const ColorRGBAf &src, ColorRGBAf &dst)
109 {
110     dst.mR = src.mR * dst.mA;
111     dst.mG = src.mG * dst.mA;
112     dst.mB = src.mB * dst.mA;
113     dst.mA = src.mA * dst.mA;
114 }
115 
116 // blend src out
BlendSrcOut(const ColorRGBAf & src,ColorRGBAf & dst)117 static inline void BlendSrcOut(const ColorRGBAf &src, ColorRGBAf &dst)
118 {
119     dst.mR = (1 - dst.mA) * src.mR;
120     dst.mG = (1 - dst.mA) * src.mG;
121     dst.mB = (1 - dst.mA) * src.mB;
122     dst.mA = (1 - dst.mA) * src.mA;
123 }
124 
125 // blend src Atop
BlendAtop(const ColorRGBAf & src,ColorRGBAf & dst)126 static inline void BlendAtop(const ColorRGBAf &src, ColorRGBAf &dst)
127 {
128     dst.mR = dst.mA * src.mR + (1 - src.mA) * dst.mR;
129     dst.mG = dst.mA * src.mG + (1 - src.mA) * dst.mG;
130     dst.mB = dst.mA * src.mB + (1 - src.mA) * dst.mB;
131     dst.mA = dst.mA;
132 }
133 
134 // blend dst
BlendDst(ColorRGBAf & src,ColorRGBAf & dst)135 static inline void BlendDst(ColorRGBAf &src, ColorRGBAf &dst)
136 {
137     (void)src;
138     (void)dst;
139 }
140 
141 // blend dst atop
BlendDstAtop(const ColorRGBAf & src,ColorRGBAf & dst)142 static inline void BlendDstAtop(const ColorRGBAf &src, ColorRGBAf &dst)
143 {
144     dst.mR = src.mA * dst.mR + (1 - dst.mA) * src.mR;
145     dst.mG = src.mA * dst.mG + (1 - dst.mA) * src.mG;
146     dst.mB = src.mA * dst.mB + (1 - dst.mA) * src.mB;
147     dst.mA = src.mA;
148 }
149 
150 // blend dst in
BlendDstIn(const ColorRGBAf & src,ColorRGBAf & dst)151 static inline void BlendDstIn(const ColorRGBAf &src, ColorRGBAf &dst)
152 {
153     dst.mR = dst.mR * src.mA;
154     dst.mG = dst.mG * src.mA;
155     dst.mB = dst.mB * src.mA;
156     dst.mA = src.mA * dst.mA;
157 }
158 
159 // blend dst out
BlendDstOut(const ColorRGBAf & src,ColorRGBAf & dst)160 static inline void BlendDstOut(const ColorRGBAf &src, ColorRGBAf &dst)
161 {
162     dst.mR = (1 - src.mA) * dst.mR;
163     dst.mG = (1 - src.mA) * dst.mG;
164     dst.mB = (1 - src.mA) * dst.mB;
165     dst.mA = (1 - src.mA) * dst.mA;
166 }
167 
168 // blend dst over
BlendDstOver(const ColorRGBAf & src,ColorRGBAf & dst)169 static inline void BlendDstOver(const ColorRGBAf &src, ColorRGBAf &dst)
170 {
171     // the display_gfx has Premultiplied
172     dst.mR *= dst.mA;
173     dst.mG *= dst.mA;
174     dst.mB *= dst.mA;
175 
176     dst.mR = dst.mR + (1 - dst.mA) * src.mR;
177     dst.mG = dst.mG + (1 - dst.mA) * src.mG;
178     dst.mB = dst.mB + (1 - dst.mA) * src.mB;
179     dst.mA = dst.mA + (1 - dst.mA) * src.mA;
180 }
181 
182 // blend xor
BlendXor(const ColorRGBAf & src,ColorRGBAf & dst)183 static inline void BlendXor(const ColorRGBAf &src, ColorRGBAf &dst)
184 {
185     dst.mR = (1 - dst.mA) * src.mR + (1 - src.mA) * dst.mR;
186     dst.mG = (1 - dst.mA) * src.mG + (1 - src.mA) * dst.mG;
187     dst.mB = (1 - dst.mA) * src.mB + (1 - src.mA) * dst.mB;
188     dst.mA = (1 - dst.mA) * src.mA + (1 - src.mA) * dst.mA;
189 }
190 
191 // blend add
BlendAdd(const ColorRGBAf & src,ColorRGBAf & dst)192 static inline void BlendAdd(const ColorRGBAf &src, ColorRGBAf &dst)
193 {
194     dst.mR = std::max(0.0f, std::min(src.mR + dst.mR, 1.0f));
195     dst.mG = std::max(0.0f, std::min(src.mG + dst.mG, 1.0f));
196     dst.mB = std::max(0.0f, std::min(src.mB + dst.mB, 1.0f));
197     dst.mA = std::max(0.0f, std::min(src.mA + dst.mA, 1.0f));
198 }
199 
GetBlendFunc(BlendType type)200 static BlendFunction GetBlendFunc(BlendType type)
201 {
202     std::unordered_map<BlendType, BlendFunction> maps = {
203         { BLEND_CLEAR, BlendClear },     { BLEND_SRC, BlendSrc },         { BLEND_DST, BlendDst },
204         { BLEND_SRCOVER, BlendSrcOver }, { BLEND_SRCIN, BlendSrcIn },     { BLEND_SRCOUT, BlendSrcOut },
205         { BLEND_SRCATOP, BlendAtop },    { BLEND_DSTIN, BlendDstIn },     { BLEND_DSTOUT, BlendDstOut },
206         { BLEND_DSTATOP, BlendDstAtop }, { BLEND_DSTOVER, BlendDstOver }, { BLEND_XOR, BlendXor },
207         { BLEND_ADD, BlendAdd },         { BLEND_NONE, BlendNone },
208     };
209     if (maps.find(type) != maps.end()) {
210         return maps[type];
211     } else {
212         DISPLAY_TEST_LOGE("has no function for blend type %d maps.size() %zd", type, maps.size());
213         return nullptr;
214     }
215 }
216 
ConvertFloatToint(float f)217 static inline int32_t ConvertFloatToint(float f)
218 {
219     if (f > MAX_FLOAT_TO_INT32) {
220         return MAX_FLOAT_TO_INT32;
221     }
222     if (f < MIN_FLOAT_TO_INT32) {
223         return MIN_FLOAT_TO_INT32;
224     }
225     return static_cast<int32_t>(f);
226 }
227 
GetPixelFormatBpp(PixelFormat format)228 static int32_t GetPixelFormatBpp(PixelFormat format)
229 {
230     const int32_t bppRgba8888 = 32;
231     switch (format) {
232         case PIXEL_FMT_RGBA_8888:
233             return bppRgba8888;
234         default:
235             return -1;
236     }
237 }
238 
GetPixelRGBA32(const BufferHandle & handle,int x,int y)239 static uint32_t GetPixelRGBA32(const BufferHandle &handle, int x, int y)
240 {
241     const int32_t pixelBytes = 4;
242     int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format);
243     DISPLAY_TEST_CHK_RETURN((bpp <= 0), 0, DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format));
244     DISPLAY_TEST_CHK_RETURN((handle.virAddr == nullptr), 0,
245         DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it"));
246     DISPLAY_TEST_CHK_RETURN((x < 0 || x >= handle.width), 0,
247         DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width));
248     DISPLAY_TEST_CHK_RETURN((y < 0 || y >= handle.height), 0,
249         DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height));
250 
251     int32_t position = y * handle.width + x;
252     if ((position * pixelBytes) > handle.size) {
253         DISPLAY_TEST_LOGE("the pixel position outside\n");
254     }
255     uint32_t *pixel = reinterpret_cast<uint32_t *>(handle.virAddr) + position;
256     return *pixel;
257 }
258 
ColorRGBAf(uint32_t r,uint32_t g,uint32_t b,uint32_t a)259 ColorRGBAf::ColorRGBAf(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
260 {
261     const float inv = 1.0f / 255.0f;
262     mA = a * inv;
263     mR = r * inv;
264     mG = g * inv;
265     mB = b * inv;
266 }
267 
Compare(ColorRGBA32 & other)268 bool ColorRGBA32::Compare(ColorRGBA32 &other)
269 {
270     const int endure = 1;
271     if ((std::abs(other.mA - mA) > endure) || (std::abs(other.mR - mR) > endure) ||
272         (std::abs(other.mG - mG) > endure) || (std::abs(other.mB - mB) > endure)) {
273         DISPLAY_TEST_LOGE("compare failed mC %x other.mC %x ", mC, other.mC);
274         return false;
275     }
276     return true;
277 }
278 
ColorRGBA32(uint32_t pixel)279 ColorRGBA32::ColorRGBA32(uint32_t pixel)
280 {
281     mA = RgbaGetA(pixel);
282     mR = RgbaGetR(pixel);
283     mG = RgbaGetG(pixel);
284     mB = RgbaGetB(pixel);
285     mC = pixel;
286 }
287 
ColorRGBA32(ColorRGBAf colorF)288 ColorRGBA32::ColorRGBA32(ColorRGBAf colorF)
289 {
290     const uint8_t rgbMax = 255;
291     const float round = 0.5;
292     mA = static_cast<uint8_t>(ConvertFloatToint(colorF.mA * rgbMax + round));
293     mR = static_cast<uint8_t>(ConvertFloatToint(colorF.mR * rgbMax + round));
294     mG = static_cast<uint8_t>(ConvertFloatToint(colorF.mG * rgbMax + round));
295     mB = static_cast<uint8_t>(ConvertFloatToint(colorF.mB * rgbMax + round));
296     mC = ColorSetARGB(mR, mG, mB, mA);
297 }
298 }
299 
RunAndCheck(const BufferHandle & exBuffer)300 bool SoftBlit::RunAndCheck(const BufferHandle &exBuffer)
301 {
302     BlendFunction blendFunc = GetBlendFunc(mType);
303     if (blendFunc == nullptr) {
304         return false;
305     }
306     DISPLAY_TEST_LOGD("blend RunAndCheck begin");
307     for (int x = mSrcRect.x; x < mSrcRect.w; x++) {
308         for (int y = mSrcRect.y; y < mSrcRect.h; y++) {
309             uint32_t srcPixel = GetPixelRGBA32(mSrcBuffer, x, y);
310             uint32_t dstPixel = GetPixelRGBA32(mDstBuffer, x, y);
311             uint32_t exPixel = GetPixelRGBA32(exBuffer, x, y);
312             ColorRGBAf srcColorF =
313                 ColorRGBAf(RgbaGetR(srcPixel), RgbaGetG(srcPixel), RgbaGetB(srcPixel), RgbaGetA(srcPixel));
314             ColorRGBAf dstColorF =
315                 ColorRGBAf(RgbaGetR(dstPixel), RgbaGetG(dstPixel), RgbaGetB(dstPixel), RgbaGetA(dstPixel));
316             blendFunc(srcColorF, dstColorF);
317             ColorRGBA32 dstColrRGBA = ColorRGBA32(dstColorF);
318             ColorRGBA32 exRGBA = ColorRGBA32(exPixel);
319             if (!dstColrRGBA.Compare(exRGBA)) {
320                 DISPLAY_TEST_LOGE(
321                     "blend check failed x %d, y %d, srcPixel %x, dstPixel %x , exPixel %x, blendResult %x blendtype %d",
322                     x, y, srcPixel, dstPixel, exPixel, dstColrRGBA.mC, mType);
323                 return false;
324             }
325         }
326     }
327     DISPLAY_TEST_LOGD("blend RunAndCheck end");
328     return true;
329 }
330 
SoftBlit(const BufferHandle & srcBuffer,const IRect & srcRect,const BufferHandle & dstBuffer,const IRect & dstRect,const BlendType type)331 SoftBlit::SoftBlit(const BufferHandle &srcBuffer, const IRect &srcRect, const BufferHandle &dstBuffer,
332     const IRect &dstRect, const BlendType type)
333     : mSrcRect(srcRect),
334     mDstRect(dstRect),
335     mSrcBuffer(srcBuffer),
336     mDstBuffer(dstBuffer),
337     mType(type)
338 {}
339