1 /*
2 * Copyright (c) 2022 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 #ifndef GRAPHIC_LITE_RENDER_PIXFMT_RGBA_BLEND_H
17 #define GRAPHIC_LITE_RENDER_PIXFMT_RGBA_BLEND_H
18 
19 #include "draw/draw_utils.h"
20 #include "engines/gfx/gfx_engine_manager.h"
21 #include "gfx_utils/heap_base.h"
22 #include "gfx_utils/graphic_log.h"
23 #include "render/render_buffer.h"
24 
25 #ifdef ARM_NEON_OPT
26 #include "graphic_neon_pipeline.h"
27 #endif
28 namespace OHOS {
29 const uint8_t NUM_COMPONENTS = 4;
30 const uint8_t PIX_STEP = 4;
31 
32 struct RgbaBlender {
33 #ifdef ARM_NEON_OPT
34     /**
35      * @brief Mix the pixels with the color component.
36      * @param color color,red,green,blue,alpha Color Component,cover Coverage.
37      * @since 1.0
38      * @version 1.0
39      */
NeonBlendPixRgbaBlender40     static inline void NeonBlendPix(
41         uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha, uint8_t* covers)
42     {
43         DrawUtils::GetInstance()->BlendLerpPix(color, red, green, blue, alpha, covers);
44     }
45 
46     /**
47      * @brief Mix the pixels with the color component.
48      * @param color color,red,green,blue,alpha Color Component,cover Coverage.
49      * @since 1.0
50      * @version 1.0
51      */
NeonBlendPixRgbaBlender52     static inline void NeonBlendPix(
53         uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha, uint8_t cover)
54     {
55         DrawUtils::GetInstance()->BlendLerpPix(color, red, green, blue, alpha, cover);
56     }
57 
58     /**
59      * @brief Mix the pixels with the color component.
60      * @param color color,red,green,blue,alpha Color Component
61      * @since 1.0
62      * @version 1.0
63      */
NeonBlendPixRgbaBlender64     static inline void NeonBlendPix(
65         uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
66     {
67         DrawUtils::GetInstance()->BlendLerpPix(color, red, green, blue, alpha);
68     }
69 
NeonBlendPixRgbaBlender70     static inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t srcCover)
71     {
72         DrawUtils::GetInstance()->BlendLerpPix(dstColors, srcColors, srcCover);
73     }
74 
NeonBlendPixRgbaBlender75     static inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t* srcCovers)
76     {
77         DrawUtils::GetInstance()->BlendLerpPix(dstColors, srcColors, srcCovers);
78     }
79 #endif
80     /**
81      * @brief Mix the pixels with the color component.
82      * @param color color,red,green,blue,alpha Color Component,cover Coverage.
83      * @since 1.0
84      * @version 1.0
85      */
BlendPixRgbaBlender86     static inline void BlendPix(
87         uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha, uint8_t cover)
88     {
89         BlendPix(color, red, green, blue, Rgba8T::MultCover(alpha, cover));
90     }
91 
92     /**
93      * @brief Mix the pixels with the color component.
94      * @param color color,red,green,blue,alpha Color Component
95      * @since 1.0
96      * @version 1.0
97      */
BlendPixRgbaBlender98     static inline void BlendPix(
99         uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
100     {
101         color[OrderBgra::RED] = Rgba8T::Lerp(color[OrderBgra::RED], red, alpha);
102         color[OrderBgra::GREEN] = Rgba8T::Lerp(color[OrderBgra::GREEN], green, alpha);
103         color[OrderBgra::BLUE] = Rgba8T::Lerp(color[OrderBgra::BLUE], blue, alpha);
104         color[OrderBgra::ALPHA] = Rgba8T::Prelerp(color[OrderBgra::ALPHA], alpha, alpha);
105     }
106 };
107 
108 struct PixelColorType {
109     uint8_t colors[NUM_COMPONENTS];
110 
111     /**
112      * @brief Set Colors.
113      * @param r,g,b,a Color Component.
114      * @since 1.0
115      * @version 1.0
116      */
SetPixelColorPixelColorType117     void SetPixelColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
118     {
119         colors[OrderBgra::RED] = red;
120         colors[OrderBgra::GREEN] = green;
121         colors[OrderBgra::BLUE] = blue;
122         colors[OrderBgra::ALPHA] = alpha;
123     }
124 
125     /**
126      * @brief Set Colors.
127      * @param color Colors.
128      * @since 1.0
129      * @version 1.0
130      */
SetPixelColorPixelColorType131     void SetPixelColor(const Rgba8T& color)
132     {
133         SetPixelColor(color.red, color.green, color.blue, color.alpha);
134     }
135 
136     /**
137      * @brief Get Colors.
138      * @param r,g,b,a Color Component.
139      * @since 1.0
140      * @version 1.0
141      */
GetPixelColorPixelColorType142     void GetPixelColor(uint8_t& red, uint8_t& green, uint8_t& blue, uint8_t& alpha) const
143     {
144         red = colors[OrderBgra::RED];
145         green = colors[OrderBgra::GREEN];
146         blue = colors[OrderBgra::BLUE];
147         alpha = colors[OrderBgra::ALPHA];
148     }
149 
150     /**
151      * @brief Get Colors.
152      * @return Colors
153      * @since 1.0
154      * @version 1.0
155      */
GetPixelColorPixelColorType156     Rgba8T GetPixelColor() const
157     {
158         return Rgba8T(colors[OrderBgra::RED], colors[OrderBgra::GREEN],
159                       colors[OrderBgra::BLUE], colors[OrderBgra::ALPHA]);
160     }
161 
162     /**
163     * @brief Gets the color component of the next pixel.
164     *
165     * @since 1.0
166     * @version 1.0
167     */
NextPixelColorType168     PixelColorType* Next()
169     {
170         return reinterpret_cast<PixelColorType*>((colors + PIX_STEP));
171     }
172 
173     /**
174     * @brief Gets the first address of the color component of the next pixel.
175     *
176     * @since 1.0
177     * @version 1.0
178     */
NextPixelColorType179     const PixelColorType* Next() const
180     {
181         return reinterpret_cast<const PixelColorType*>(colors + PIX_STEP);
182     }
183 
184     /**
185     * @brief Gets the first address of the color component of the nth pixe.
186     * @param pixelIndex pixel offset
187     * @since 1.0
188     * @version 1.0
189     */
AdvancePixelColorType190     PixelColorType* Advance(int32_t pixelIndex)
191     {
192         return reinterpret_cast<PixelColorType*>(colors + pixelIndex * PIX_STEP);
193     }
194 
195     /**
196     * @brief Gets the first address of the color component of the nth pixe.
197     * @param pixelIndex pixel offset
198     * @since 1.0
199     * @version 1.0
200     */
AdvancePixelColorType201     const PixelColorType* Advance(int32_t pixelIndex) const
202     {
203         return reinterpret_cast<const PixelColorType*>(colors + pixelIndex * PIX_STEP);
204     }
205 };
206 
207 class RenderPixfmtRgbaBlend : public HeapBase {
208 public:
209     const uint8_t PIX_WIDTH = sizeof(uint8_t) * PIX_STEP;
RenderPixfmtRgbaBlend()210     RenderPixfmtRgbaBlend() : rBuf_(0) {}
RenderPixfmtRgbaBlend(RenderBuffer & rBuf)211     explicit RenderPixfmtRgbaBlend(RenderBuffer& rBuf) :  rBuf_(&rBuf) {}
212 
213     /**
214     * @brief Attach pixels to the drawing area.
215     *
216     * @since 1.0
217     * @version 1.0
218     */
Attach(RenderBuffer & rBuf)219     virtual void Attach(RenderBuffer& rBuf)
220     {
221         rBuf_ = &rBuf;
222     }
223 
224     bool Attach(RenderPixfmtRgbaBlend& pixf, int32_t x1, int32_t y1, int32_t x2, int32_t y2);
225 
226     /**
227     * @brief Get the size of each screen (draw buffer).
228     *
229     * @since 1.0
230     * @version 1.0
231     */
GetWidth()232     virtual inline uint32_t GetWidth() const
233     {
234         return rBuf_->GetWidth();
235     }
236 
GetHeight()237     virtual inline uint32_t GetHeight() const
238     {
239         return rBuf_->GetHeight();
240     }
241 
242     /**
243       * @brief Returns the number of bytes in a row of the window.
244       *
245       * @since 1.0
246       * @version 1.0
247       */
GetStride()248     virtual inline int32_t GetStride() const
249     {
250         return rBuf_->GetStride();
251     }
252 
253     /**
254       * @brief Returns the row address of a window row.
255       *
256       * @since 1.0
257       * @version 1.0
258       */
GetRowPtr(int32_t y)259     virtual inline uint8_t* GetRowPtr(int32_t y)
260     {
261         return rBuf_->GetRowPtr(y);
262     }
263 
264     /**
265       * @brief Returns the row address of a window row.
266       *
267       * @since 1.0
268       * @version 1.0
269       */
GetRowPtr(int32_t y)270     virtual inline const uint8_t* GetRowPtr(int32_t y) const
271     {
272         return rBuf_->GetRowPtr(y);
273     }
274 
275     /**
276       * @brief Returns the row data of one row of the window.
277       *
278       * @since 1.0
279       * @version 1.0
280       */
GetRow(int32_t y)281     virtual inline RowData GetRow(int32_t y) const
282     {
283         return rBuf_->GetRow(y);
284     }
285 
PixPtr(int32_t x,int32_t y)286     virtual inline uint8_t* PixPtr(int32_t x, int32_t y)
287     {
288         return rBuf_->GetRowPtr(y) + sizeof(uint8_t) * (x * PIX_STEP);
289     }
290 
PixPtr(int32_t x,int32_t y)291     virtual inline const uint8_t* PixPtr(int32_t x, int32_t y) const
292     {
293         return rBuf_->GetRowPtr(y) + sizeof(uint8_t) * (x * PIX_STEP);
294     }
295 
296     /**
297      * @brief Pointer to pixel type pointer.
298      *
299      * @since 1.0
300      * @version 1.0
301      */
PixValuePtr(int32_t x,int32_t y)302     virtual inline PixelColorType* PixValuePtr(int32_t x, int32_t y)
303     {
304         return reinterpret_cast<PixelColorType*>(rBuf_->GetRowPtr(y) + sizeof(uint8_t) * (x * PIX_STEP));
305     }
306 
307     /**
308      * @brief Gets the pixel address of the specified left.
309      *
310      * @since 1.0
311      * @version 1.0.
312      */
PixValuePtr(int32_t x,int32_t y)313     virtual inline const PixelColorType* PixValuePtr(int32_t x, int32_t y) const
314     {
315         uint8_t* pixelPtr = rBuf_->GetRowPtr(y);
316         return pixelPtr ? reinterpret_cast<PixelColorType*>(pixelPtr + sizeof(uint8_t) * (x * PIX_STEP)) : nullptr;
317     }
318 
319     /**
320      * @brief Pointer to pixel type pointer.
321      *
322      * @since 1.0
323      * @version 1.0
324      */
PixValuePtr(void * pixelPtr)325     inline static PixelColorType* PixValuePtr(void* pixelPtr)
326     {
327         return static_cast<PixelColorType*>(pixelPtr);
328     }
329 
330     /**
331      * @brief Pointer to pixel type pointer.
332      *
333      * @since 1.0
334      * @version 1.0
335      */
PixValuePtr(const void * pixelPtr)336     inline static const PixelColorType* PixValuePtr(const void* pixelPtr)
337     {
338         return static_cast<const PixelColorType*>(pixelPtr);
339     }
340 
341     /**
342      * @brief Gets the color of a pixel.
343      *
344      * @since 1.0
345      * @version 1.0
346      */
Pixel(int32_t x,int32_t y)347     virtual inline Rgba8T Pixel(int32_t x, int32_t y) const
348     {
349         const PixelColorType* pixelPtr = PixValuePtr(x, y);
350         if (pixelPtr != nullptr) {
351             return pixelPtr->GetPixelColor();
352         }
353         return Rgba8T::NoColor();
354     }
355 
356     /**
357      * @brief Copy color to pixel.
358      *
359      * @since 1.0
360      * @version 1.0
361      */
CopyPixel(int32_t x,int32_t y,const Rgba8T & color)362     virtual inline void CopyPixel(int32_t x, int32_t y, const Rgba8T& color)
363     {
364         PixValuePtr(x, y)->SetPixelColor(color);
365     }
366 
367     /**
368     * @brief Mix pixels (x, y) with the transparency of cover (coverage = transparency) with color color.
369     *
370     * @since 1.0
371     * @version 1.0
372     */
BlendPixel(int32_t x,int32_t y,const Rgba8T & color,uint8_t cover)373     virtual inline void BlendPixel(int32_t x, int32_t y, const Rgba8T& color, uint8_t cover)
374     {
375         CopyOrBlendPix(PixValuePtr(x, y), color, cover);
376     }
377 
378     /**
379      * @brief Set the pixels of len length in horizontal order starting from (x, y).
380      *
381      * @since 1.0
382      * @version 1.0
383      */
384     virtual void CopyHLine(int32_t x, int32_t y,
385                            uint32_t len,
386                            const Rgba8T& color);
387 
388     /**
389      * @brief Pixels of len length are mixed horizontally from (x, y).
390      *
391      * @since 1.0
392      * @version 1.0
393      */
394     virtual void BlendHLine(int32_t x, int32_t y,
395                             uint32_t len,
396                             const Rgba8T& color,
397                             uint8_t cover);
398 
399     /**
400      * @brief Mix a series of colors of len length in horizontal order starting from (x, y).
401      *
402      * @since 1.0
403      * @version 1.0
404      */
405     virtual void BlendSolidHSpan(int32_t x, int32_t y,
406                                  uint32_t len,
407                                  const Rgba8T& color,
408                                  const uint8_t* covers);
409 
410     /**
411      * @brief Mix a series of colors of len length in vertical order starting from (x, y).
412      *
413      * @since 1.0
414      * @version 1.0
415      */
416     virtual void BlendSolidVSpan(int32_t x, int32_t y,
417                                  uint32_t len,
418                                  const Rgba8T& color,
419                                  const uint8_t* covers);
420 
421     /**
422      * @brief Set the color of len length in horizontal order starting from (x, y).
423      *
424      * @since 1.0
425      * @version 1.0
426      */
427     virtual void CopyColorHSpan(int32_t x, int32_t y,
428                                 uint32_t len,
429                                 const Rgba8T* colors);
430 
431     /**
432      * @brief Set the color of len length in vertical order starting from (x, y).
433      *
434      * @since 1.0
435      * @version 1.0
436      */
437     virtual void CopyColorVSpan(int32_t x, int32_t y,
438                                 uint32_t len,
439                                 const Rgba8T* colors);
440 
441     /**
442      * @brief Mix a series of colors of len length in horizontal order starting from (x, y).
443      * @param x         x coordinate.
444      * @param y         x coordinate
445      * @param len       length of line
446      * @param colors    colors array
447      * @param covers    transition value
448      * @param cover     cover value
449      * @since 1.0
450      * @version 1.0
451      */
452     void BlendColorHSpan(int32_t x, int32_t y,
453                          uint32_t len,
454                          const Rgba8T* colors,
455                          const uint8_t* covers,
456                          uint8_t cover);
457 
458 protected:
459 #ifdef ARM_NEON_OPT
NeonBlendPix(PixelColorType * pixelColors,const Rgba8T & color)460     virtual inline void NeonBlendPix(PixelColorType* pixelColors, const Rgba8T& color)
461     {
462         blender_.NeonBlendPix(pixelColors->colors, color.red, color.green,
463                               color.blue, color.alpha);
464     }
465 
NeonBlendPix(PixelColorType * pixelColors,const Rgba8T & color,uint8_t cover)466     virtual inline void NeonBlendPix(PixelColorType* pixelColors, const Rgba8T& color, uint8_t cover)
467     {
468         blender_.NeonBlendPix(pixelColors->colors, color.red, color.green,
469                               color.blue, color.alpha, cover);
470     }
471 
NeonBlendPix(uint8_t * dstColors,uint8_t * srcColors,uint8_t srcCover)472     virtual inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t srcCover)
473     {
474         blender_.NeonBlendPix(dstColors, srcColors, srcCover);
475     }
476 
NeonBlendPix(uint8_t * dstColors,uint8_t * srcColors,uint8_t * srcCovers)477     virtual inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t* srcCovers)
478     {
479         blender_.NeonBlendPix(dstColors, srcColors, srcCovers);
480     }
481 
NeonBlendPix(uint8_t * dstColors,const Rgba8T & srcColors,uint8_t * srcCovers)482     virtual inline void NeonBlendPix(uint8_t* dstColors, const Rgba8T& srcColors, uint8_t* srcCovers)
483     {
484         blender_.NeonBlendPix(dstColors, srcColors.red, srcColors.green, srcColors.blue,
485                               srcColors.alpha, srcCovers);
486     }
487 #endif
488 
489     /**
490      * @brief Blend color and coverage to specified pixels.
491      *
492      * @since 1.0
493      * @version 1.0
494      */
BlendPix(PixelColorType * pixelPtr,const Rgba8T & color,uint32_t cover)495     virtual inline void BlendPix(PixelColorType* pixelPtr, const Rgba8T& color, uint32_t cover)
496     {
497         blender_.BlendPix(pixelPtr->colors, color.red, color.green, color.blue, color.alpha, cover);
498     }
499 
500     /**
501      * @brief Blend colors to specified pixels.
502      *
503      * @since 1.0
504      * @version 1.0
505      */
BlendPix(PixelColorType * pixelPtr,const Rgba8T & color)506     virtual inline void BlendPix(PixelColorType* pixelPtr, const Rgba8T& color)
507     {
508         blender_.BlendPix(pixelPtr->colors, color.red, color.green, color.blue, color.alpha);
509     }
510 
511     /**
512      * @brief Set or blend to specified pixels with color and coverage.
513      *
514      * @since 1.0
515      * @version 1.0
516      */
CopyOrBlendPix(PixelColorType * pixelPtr,const Rgba8T & color,uint32_t cover)517     virtual inline void CopyOrBlendPix(PixelColorType* pixelPtr, const Rgba8T& color, uint32_t cover)
518     {
519         if (!color.IsTransparent()) {
520             if (color.IsOpaque() && cover == COVER_MASK) {
521                 pixelPtr->SetPixelColor(color.red, color.green, color.blue, color.alpha);
522             } else {
523                 blender_.BlendPix(pixelPtr->colors, color.red, color.green,
524                                   color.blue, color.alpha, cover);
525             }
526         }
527     }
528 
529     /**
530      * @brief Sets or blends the color to the specified pixel.
531      *
532      * @since 1.0
533      * @version 1.0.
534      */
CopyOrBlendPix(PixelColorType * pixelPtr,const Rgba8T & color)535     virtual inline void CopyOrBlendPix(PixelColorType* pixelPtr, const Rgba8T& color)
536     {
537         if (!color.IsTransparent()) {
538             if (color.IsOpaque()) {
539                 pixelPtr->SetPixelColor(color);
540             } else {
541                 blender_.BlendPix(pixelPtr->colors, color.red, color.green,
542                                   color.blue, color.alpha);
543             }
544         }
545     }
546 
547     RenderBuffer* rBuf_;
548     RgbaBlender blender_;
549 };
550 } // namespace OHOS
551 #endif
552