/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef GRAPHIC_LITE_RENDER_PIXFMT_RGBA_BLEND_H #define GRAPHIC_LITE_RENDER_PIXFMT_RGBA_BLEND_H #include "draw/draw_utils.h" #include "engines/gfx/gfx_engine_manager.h" #include "gfx_utils/heap_base.h" #include "gfx_utils/graphic_log.h" #include "render/render_buffer.h" #ifdef ARM_NEON_OPT #include "graphic_neon_pipeline.h" #endif namespace OHOS { const uint8_t NUM_COMPONENTS = 4; const uint8_t PIX_STEP = 4; struct RgbaBlender { #ifdef ARM_NEON_OPT /** * @brief Mix the pixels with the color component. * @param color color,red,green,blue,alpha Color Component,cover Coverage. * @since 1.0 * @version 1.0 */ static inline void NeonBlendPix( uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha, uint8_t* covers) { DrawUtils::GetInstance()->BlendLerpPix(color, red, green, blue, alpha, covers); } /** * @brief Mix the pixels with the color component. * @param color color,red,green,blue,alpha Color Component,cover Coverage. * @since 1.0 * @version 1.0 */ static inline void NeonBlendPix( uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha, uint8_t cover) { DrawUtils::GetInstance()->BlendLerpPix(color, red, green, blue, alpha, cover); } /** * @brief Mix the pixels with the color component. * @param color color,red,green,blue,alpha Color Component * @since 1.0 * @version 1.0 */ static inline void NeonBlendPix( uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) { DrawUtils::GetInstance()->BlendLerpPix(color, red, green, blue, alpha); } static inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t srcCover) { DrawUtils::GetInstance()->BlendLerpPix(dstColors, srcColors, srcCover); } static inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t* srcCovers) { DrawUtils::GetInstance()->BlendLerpPix(dstColors, srcColors, srcCovers); } #endif /** * @brief Mix the pixels with the color component. * @param color color,red,green,blue,alpha Color Component,cover Coverage. * @since 1.0 * @version 1.0 */ static inline void BlendPix( uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha, uint8_t cover) { BlendPix(color, red, green, blue, Rgba8T::MultCover(alpha, cover)); } /** * @brief Mix the pixels with the color component. * @param color color,red,green,blue,alpha Color Component * @since 1.0 * @version 1.0 */ static inline void BlendPix( uint8_t* color, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) { color[OrderBgra::RED] = Rgba8T::Lerp(color[OrderBgra::RED], red, alpha); color[OrderBgra::GREEN] = Rgba8T::Lerp(color[OrderBgra::GREEN], green, alpha); color[OrderBgra::BLUE] = Rgba8T::Lerp(color[OrderBgra::BLUE], blue, alpha); color[OrderBgra::ALPHA] = Rgba8T::Prelerp(color[OrderBgra::ALPHA], alpha, alpha); } }; struct PixelColorType { uint8_t colors[NUM_COMPONENTS]; /** * @brief Set Colors. * @param r,g,b,a Color Component. * @since 1.0 * @version 1.0 */ void SetPixelColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) { colors[OrderBgra::RED] = red; colors[OrderBgra::GREEN] = green; colors[OrderBgra::BLUE] = blue; colors[OrderBgra::ALPHA] = alpha; } /** * @brief Set Colors. * @param color Colors. * @since 1.0 * @version 1.0 */ void SetPixelColor(const Rgba8T& color) { SetPixelColor(color.red, color.green, color.blue, color.alpha); } /** * @brief Get Colors. * @param r,g,b,a Color Component. * @since 1.0 * @version 1.0 */ void GetPixelColor(uint8_t& red, uint8_t& green, uint8_t& blue, uint8_t& alpha) const { red = colors[OrderBgra::RED]; green = colors[OrderBgra::GREEN]; blue = colors[OrderBgra::BLUE]; alpha = colors[OrderBgra::ALPHA]; } /** * @brief Get Colors. * @return Colors * @since 1.0 * @version 1.0 */ Rgba8T GetPixelColor() const { return Rgba8T(colors[OrderBgra::RED], colors[OrderBgra::GREEN], colors[OrderBgra::BLUE], colors[OrderBgra::ALPHA]); } /** * @brief Gets the color component of the next pixel. * * @since 1.0 * @version 1.0 */ PixelColorType* Next() { return reinterpret_cast((colors + PIX_STEP)); } /** * @brief Gets the first address of the color component of the next pixel. * * @since 1.0 * @version 1.0 */ const PixelColorType* Next() const { return reinterpret_cast(colors + PIX_STEP); } /** * @brief Gets the first address of the color component of the nth pixe. * @param pixelIndex pixel offset * @since 1.0 * @version 1.0 */ PixelColorType* Advance(int32_t pixelIndex) { return reinterpret_cast(colors + pixelIndex * PIX_STEP); } /** * @brief Gets the first address of the color component of the nth pixe. * @param pixelIndex pixel offset * @since 1.0 * @version 1.0 */ const PixelColorType* Advance(int32_t pixelIndex) const { return reinterpret_cast(colors + pixelIndex * PIX_STEP); } }; class RenderPixfmtRgbaBlend : public HeapBase { public: const uint8_t PIX_WIDTH = sizeof(uint8_t) * PIX_STEP; RenderPixfmtRgbaBlend() : rBuf_(0) {} explicit RenderPixfmtRgbaBlend(RenderBuffer& rBuf) : rBuf_(&rBuf) {} /** * @brief Attach pixels to the drawing area. * * @since 1.0 * @version 1.0 */ virtual void Attach(RenderBuffer& rBuf) { rBuf_ = &rBuf; } bool Attach(RenderPixfmtRgbaBlend& pixf, int32_t x1, int32_t y1, int32_t x2, int32_t y2); /** * @brief Get the size of each screen (draw buffer). * * @since 1.0 * @version 1.0 */ virtual inline uint32_t GetWidth() const { return rBuf_->GetWidth(); } virtual inline uint32_t GetHeight() const { return rBuf_->GetHeight(); } /** * @brief Returns the number of bytes in a row of the window. * * @since 1.0 * @version 1.0 */ virtual inline int32_t GetStride() const { return rBuf_->GetStride(); } /** * @brief Returns the row address of a window row. * * @since 1.0 * @version 1.0 */ virtual inline uint8_t* GetRowPtr(int32_t y) { return rBuf_->GetRowPtr(y); } /** * @brief Returns the row address of a window row. * * @since 1.0 * @version 1.0 */ virtual inline const uint8_t* GetRowPtr(int32_t y) const { return rBuf_->GetRowPtr(y); } /** * @brief Returns the row data of one row of the window. * * @since 1.0 * @version 1.0 */ virtual inline RowData GetRow(int32_t y) const { return rBuf_->GetRow(y); } virtual inline uint8_t* PixPtr(int32_t x, int32_t y) { return rBuf_->GetRowPtr(y) + sizeof(uint8_t) * (x * PIX_STEP); } virtual inline const uint8_t* PixPtr(int32_t x, int32_t y) const { return rBuf_->GetRowPtr(y) + sizeof(uint8_t) * (x * PIX_STEP); } /** * @brief Pointer to pixel type pointer. * * @since 1.0 * @version 1.0 */ virtual inline PixelColorType* PixValuePtr(int32_t x, int32_t y) { return reinterpret_cast(rBuf_->GetRowPtr(y) + sizeof(uint8_t) * (x * PIX_STEP)); } /** * @brief Gets the pixel address of the specified left. * * @since 1.0 * @version 1.0. */ virtual inline const PixelColorType* PixValuePtr(int32_t x, int32_t y) const { uint8_t* pixelPtr = rBuf_->GetRowPtr(y); return pixelPtr ? reinterpret_cast(pixelPtr + sizeof(uint8_t) * (x * PIX_STEP)) : nullptr; } /** * @brief Pointer to pixel type pointer. * * @since 1.0 * @version 1.0 */ inline static PixelColorType* PixValuePtr(void* pixelPtr) { return static_cast(pixelPtr); } /** * @brief Pointer to pixel type pointer. * * @since 1.0 * @version 1.0 */ inline static const PixelColorType* PixValuePtr(const void* pixelPtr) { return static_cast(pixelPtr); } /** * @brief Gets the color of a pixel. * * @since 1.0 * @version 1.0 */ virtual inline Rgba8T Pixel(int32_t x, int32_t y) const { const PixelColorType* pixelPtr = PixValuePtr(x, y); if (pixelPtr != nullptr) { return pixelPtr->GetPixelColor(); } return Rgba8T::NoColor(); } /** * @brief Copy color to pixel. * * @since 1.0 * @version 1.0 */ virtual inline void CopyPixel(int32_t x, int32_t y, const Rgba8T& color) { PixValuePtr(x, y)->SetPixelColor(color); } /** * @brief Mix pixels (x, y) with the transparency of cover (coverage = transparency) with color color. * * @since 1.0 * @version 1.0 */ virtual inline void BlendPixel(int32_t x, int32_t y, const Rgba8T& color, uint8_t cover) { CopyOrBlendPix(PixValuePtr(x, y), color, cover); } /** * @brief Set the pixels of len length in horizontal order starting from (x, y). * * @since 1.0 * @version 1.0 */ virtual void CopyHLine(int32_t x, int32_t y, uint32_t len, const Rgba8T& color); /** * @brief Pixels of len length are mixed horizontally from (x, y). * * @since 1.0 * @version 1.0 */ virtual void BlendHLine(int32_t x, int32_t y, uint32_t len, const Rgba8T& color, uint8_t cover); /** * @brief Mix a series of colors of len length in horizontal order starting from (x, y). * * @since 1.0 * @version 1.0 */ virtual void BlendSolidHSpan(int32_t x, int32_t y, uint32_t len, const Rgba8T& color, const uint8_t* covers); /** * @brief Mix a series of colors of len length in vertical order starting from (x, y). * * @since 1.0 * @version 1.0 */ virtual void BlendSolidVSpan(int32_t x, int32_t y, uint32_t len, const Rgba8T& color, const uint8_t* covers); /** * @brief Set the color of len length in horizontal order starting from (x, y). * * @since 1.0 * @version 1.0 */ virtual void CopyColorHSpan(int32_t x, int32_t y, uint32_t len, const Rgba8T* colors); /** * @brief Set the color of len length in vertical order starting from (x, y). * * @since 1.0 * @version 1.0 */ virtual void CopyColorVSpan(int32_t x, int32_t y, uint32_t len, const Rgba8T* colors); /** * @brief Mix a series of colors of len length in horizontal order starting from (x, y). * @param x x coordinate. * @param y x coordinate * @param len length of line * @param colors colors array * @param covers transition value * @param cover cover value * @since 1.0 * @version 1.0 */ void BlendColorHSpan(int32_t x, int32_t y, uint32_t len, const Rgba8T* colors, const uint8_t* covers, uint8_t cover); protected: #ifdef ARM_NEON_OPT virtual inline void NeonBlendPix(PixelColorType* pixelColors, const Rgba8T& color) { blender_.NeonBlendPix(pixelColors->colors, color.red, color.green, color.blue, color.alpha); } virtual inline void NeonBlendPix(PixelColorType* pixelColors, const Rgba8T& color, uint8_t cover) { blender_.NeonBlendPix(pixelColors->colors, color.red, color.green, color.blue, color.alpha, cover); } virtual inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t srcCover) { blender_.NeonBlendPix(dstColors, srcColors, srcCover); } virtual inline void NeonBlendPix(uint8_t* dstColors, uint8_t* srcColors, uint8_t* srcCovers) { blender_.NeonBlendPix(dstColors, srcColors, srcCovers); } virtual inline void NeonBlendPix(uint8_t* dstColors, const Rgba8T& srcColors, uint8_t* srcCovers) { blender_.NeonBlendPix(dstColors, srcColors.red, srcColors.green, srcColors.blue, srcColors.alpha, srcCovers); } #endif /** * @brief Blend color and coverage to specified pixels. * * @since 1.0 * @version 1.0 */ virtual inline void BlendPix(PixelColorType* pixelPtr, const Rgba8T& color, uint32_t cover) { blender_.BlendPix(pixelPtr->colors, color.red, color.green, color.blue, color.alpha, cover); } /** * @brief Blend colors to specified pixels. * * @since 1.0 * @version 1.0 */ virtual inline void BlendPix(PixelColorType* pixelPtr, const Rgba8T& color) { blender_.BlendPix(pixelPtr->colors, color.red, color.green, color.blue, color.alpha); } /** * @brief Set or blend to specified pixels with color and coverage. * * @since 1.0 * @version 1.0 */ virtual inline void CopyOrBlendPix(PixelColorType* pixelPtr, const Rgba8T& color, uint32_t cover) { if (!color.IsTransparent()) { if (color.IsOpaque() && cover == COVER_MASK) { pixelPtr->SetPixelColor(color.red, color.green, color.blue, color.alpha); } else { blender_.BlendPix(pixelPtr->colors, color.red, color.green, color.blue, color.alpha, cover); } } } /** * @brief Sets or blends the color to the specified pixel. * * @since 1.0 * @version 1.0. */ virtual inline void CopyOrBlendPix(PixelColorType* pixelPtr, const Rgba8T& color) { if (!color.IsTransparent()) { if (color.IsOpaque()) { pixelPtr->SetPixelColor(color); } else { blender_.BlendPix(pixelPtr->colors, color.red, color.green, color.blue, color.alpha); } } } RenderBuffer* rBuf_; RgbaBlender blender_; }; } // namespace OHOS #endif