1/* 2 * Copyright (c) 2020-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 "lite_win.h" 17 18#include "gfx_utils/graphic_log.h" 19#include "gfx_utils/pixel_format_utils.h" 20#include "graphic_locker.h" 21#include "graphic_performance.h" 22#include "hals/gfx_engines.h" 23#include "securec.h" 24 25#include "lite_wm.h" 26#ifdef ARM_NEON_OPT 27#include "graphic_neon_utils.h" 28#endif 29 30namespace OHOS { 31#define COLOR_BLEND_RGBA(r1, g1, b1, a1, r2, g2, b2, a2) \ 32 const float A1 = static_cast<float>(a1) / OPA_OPAQUE; \ 33 const float A2 = static_cast<float>(a2) / OPA_OPAQUE; \ 34 const float a = 1 - (1 - A1) * (1 - A2); \ 35 (r1) = (A2 * (r2) + (1 - A2) * A1 * (r1)) / a; \ 36 (g1) = (A2 * (g2) + (1 - A2) * A1 * (g1)) / a; \ 37 (b1) = (A2 * (b2) + (1 - A2) * A1 * (b1)) / a; \ 38 (a1) = a * OPA_OPAQUE; 39 40#define COLOR_BLEND_RGB(r1, g1, b1, r2, g2, b2, a2) \ 41 (r1) = (((r2) * (a2)) / OPA_OPAQUE) + (((r1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \ 42 (g1) = (((g2) * (a2)) / OPA_OPAQUE) + (((g1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); \ 43 (b1) = (((b2) * (a2)) / OPA_OPAQUE) + (((b1) * (OPA_OPAQUE - (a2))) / OPA_OPAQUE); 44 45namespace { 46 static const int16_t DEFAULT_QUEUE_SIZE = 2; 47} 48 49LiteWindow::LiteWindow(const LiteWinConfig& config) 50 : id_(INVALID_WINDOW_ID), pid_(INVALID_PID), isShow_(false), config_(config), surface_(nullptr), 51 backBuf_(nullptr), sid_({}), needUnregister_(false) 52{ 53 pthread_mutex_init(&backBufMutex_, nullptr); 54 id_ = LiteWM::GetInstance()->GetUniqueWinId(); 55} 56 57LiteWindow::~LiteWindow() 58{ 59 if (needUnregister_) { 60 GRAPHIC_LOGI("release svc cookie"); 61 if (sid_.cookie != 0) { 62 delete reinterpret_cast<IpcObjectStub*>(sid_.cookie); 63 sid_.cookie = 0; 64 } 65 } 66 if (surface_ != nullptr) { 67 if (backBuf_ != nullptr) { 68 surface_->CancelBuffer(backBuf_); 69 } 70 delete surface_; 71 surface_ = nullptr; 72 } 73 74 LiteWM::GetInstance()->RecycleWinId(id_); 75} 76 77bool LiteWindow::CreateSurface() 78{ 79 if (surface_ == nullptr) { 80 surface_ = Surface::CreateSurface(); 81 if (surface_ == nullptr) { 82 GRAPHIC_LOGE("CreateSurface failed!"); 83 return false; 84 } 85 surface_->SetWidthAndHeight(config_.rect.GetWidth(), config_.rect.GetHeight()); 86 surface_->SetQueueSize(DEFAULT_QUEUE_SIZE); 87 surface_->SetFormat(config_.pixelFormat); 88 surface_->SetUsage(BUFFER_CONSUMER_USAGE_HARDWARE); 89 90 if (backBuf_ == nullptr) { 91 backBuf_ = surface_->RequestBuffer(); 92 } 93 } 94 return true; 95} 96 97void LiteWindow::ReleaseSurface() 98{ 99} 100 101void LiteWindow::ResizeSurface(int16_t width, int16_t height) 102{ 103 if (surface_ == nullptr) { 104 return; 105 } 106 107 GraphicLocker lock(backBufMutex_); 108 if (backBuf_ != nullptr) { 109 surface_->CancelBuffer(backBuf_); 110 } 111 surface_->SetWidthAndHeight(width, height); 112 backBuf_ = surface_->RequestBuffer(); 113} 114 115void LiteWindow::Update(Rect rect) 116{ 117 LiteWM::GetInstance()->UpdateWindowRegion(this, rect); 118} 119 120void LiteWindow::UpdateBackBuf() 121{ 122 GraphicLocker lock(backBufMutex_); 123 if (surface_ == nullptr || backBuf_ == nullptr) { 124 return; 125 } 126 127 SurfaceBuffer* acquireBuffer = surface_->AcquireBuffer(); 128 if (acquireBuffer != nullptr) { 129 void* acquireBufVirAddr = acquireBuffer->GetVirAddr(); 130 void* backBufVirAddr = backBuf_->GetVirAddr(); 131 if (acquireBufVirAddr != nullptr && backBufVirAddr != nullptr) { 132 GRAPHIC_LOGI("memcpy, backBuf size=%d, acquireBuffer size=%d", 133 backBuf_->GetSize(), acquireBuffer->GetSize()); 134#ifdef ARM_NEON_OPT 135 { 136 DEBUG_PERFORMANCE_TRACE("UpdateBackBuf_neon"); 137 NeonMemcpy(backBufVirAddr, backBuf_->GetSize(), acquireBufVirAddr, acquireBuffer->GetSize()); 138 } 139#else 140 { 141 DEBUG_PERFORMANCE_TRACE("UpdateBackBuf"); 142 if (memcpy_s(backBufVirAddr, backBuf_->GetSize(), 143 acquireBufVirAddr, acquireBuffer->GetSize()) != EOK) { 144 GRAPHIC_LOGE("memcpy_s error!"); 145 } 146 } 147#endif 148 GRAPHIC_LOGI("memcpy end"); 149 } 150 surface_->ReleaseBuffer(acquireBuffer); 151 } 152} 153 154void LiteWindow::FlushWithModeCopy(const Rect& srcRect, const LiteSurfaceData* layerData, int16_t dx, int16_t dy) 155{ 156 int16_t x1 = srcRect.GetLeft(); 157 int16_t y1 = srcRect.GetTop(); 158 int16_t x2 = srcRect.GetRight(); 159 int16_t y2 = srcRect.GetBottom(); 160 161 uint32_t stride = surface_->GetStride(); 162 uint8_t* srcBuf = reinterpret_cast<uint8_t*>(backBuf_->GetVirAddr()) + y1 * stride + x1 * sizeof(ColorType); 163 uint8_t* dstBuf = layerData->virAddr + dy * layerData->stride + dx * sizeof(LayerColorType); 164 int32_t lineSize = static_cast<int32_t>(x2 - x1 + 1) * sizeof(LayerColorType); 165 for (int16_t y = y1; y <= y2; ++y) { 166#ifdef LAYER_PF_ARGB1555 167 ColorType* tmpSrc = reinterpret_cast<ColorType*>(srcBuf); 168 LayerColorType* tmpDst = reinterpret_cast<LayerColorType*>(dstBuf); 169 for (int16_t x = x1; x <= x2; ++x) { 170 *tmpDst++ = PixelFormatUtils::ARGB8888ToARGB1555((tmpSrc++)->full); 171 } 172#elif defined LAYER_PF_ARGB8888 173 if (memcpy_s(dstBuf, lineSize, srcBuf, lineSize) != EOK) { 174 GRAPHIC_LOGE("memcpy_s error!"); 175 } 176#endif 177 srcBuf += stride; 178 dstBuf += layerData->stride; 179 } 180} 181 182void LiteWindow::FlushWithModeBlend(const Rect& srcRect, const LiteSurfaceData* layerData, int16_t dx, int16_t dy) 183{ 184 int16_t x1 = srcRect.GetLeft(); 185 int16_t y1 = srcRect.GetTop(); 186 int16_t x2 = srcRect.GetRight(); 187 int16_t y2 = srcRect.GetBottom(); 188 189 uint32_t stride = surface_->GetStride(); 190 uint8_t* srcBuf = reinterpret_cast<uint8_t*>(backBuf_->GetVirAddr()) + y1 * stride + x1 * sizeof(ColorType); 191 uint8_t* dstBuf = layerData->virAddr + dy * layerData->stride + dx * sizeof(LayerColorType); 192 for (int16_t y = y1; y <= y2; ++y) { 193 ColorType* tmpSrc = reinterpret_cast<ColorType*>(srcBuf); 194 LayerColorType* tmpDst = reinterpret_cast<LayerColorType*>(dstBuf); 195 for (int16_t x = x1; x <= x2; ++x) { 196 uint8_t alpha = tmpSrc->alpha * config_.opacity / OPA_OPAQUE; 197#ifdef LAYER_PF_ARGB1555 198 PF_ARGB1555* dst = reinterpret_cast<PF_ARGB1555*>(tmpDst); 199 if (dst->alpha == 0) { 200 if (alpha) { 201 // ARGB8888 to ARGB1555, R/G/B should right shift 3 bits 202 dst->red = (tmpSrc->red * alpha / OPA_OPAQUE) >> 3; 203 dst->green = (tmpSrc->green * alpha / OPA_OPAQUE) >> 3; 204 dst->blue = (tmpSrc->blue * alpha / OPA_OPAQUE) >> 3; 205 dst->alpha = 1; 206 } 207 } else { 208 COLOR_BLEND_RGB(dst->red, dst->green, dst->blue, 209 (tmpSrc->red) >> 3, (tmpSrc->green) >> 3, (tmpSrc->blue) >> 3, alpha); 210 } 211#elif defined LAYER_PF_ARGB8888 212 if (alpha == OPA_OPAQUE) { 213 *tmpDst = tmpSrc->full; 214 } else { 215 Color32* dst = reinterpret_cast<Color32*>(tmpDst); 216 COLOR_BLEND_RGBA(dst->red, dst->green, dst->blue, dst->alpha, 217 tmpSrc->red, tmpSrc->green, tmpSrc->blue, alpha); 218 } 219#endif 220 ++tmpSrc; 221 ++tmpDst; 222 } 223 srcBuf += stride; 224 dstBuf += layerData->stride; 225 } 226} 227 228void LiteWindow::Flush(const Rect& srcRect, const LiteSurfaceData* layerData, int16_t dx, int16_t dy) 229{ 230 if (layerData == nullptr) { 231 return; 232 } 233 234 GraphicLocker lock(backBufMutex_); 235#if ENABLE_GFX_ENGINES 236 uintptr_t phyaddr = backBuf_->GetPhyAddr(); 237 if (IsCoverMode() && phyaddr) { 238 LiteSurfaceData srcData; 239 srcData.width = surface_->GetWidth(); 240 srcData.height = surface_->GetHeight(); 241 srcData.pixelFormat = (ImagePixelFormat)surface_->GetFormat(); 242 srcData.stride = surface_->GetStride(); 243 srcData.phyAddr = reinterpret_cast<uint8_t*>(phyaddr); 244 GRAPHIC_LOGD("Hardware composite, width=%d, height=%d, pixelFormat=%d, stride=%d", 245 srcData.width, srcData.height, srcData.pixelFormat, srcData.stride); 246 if (GfxEngines::GetInstance()->GfxBlit(srcData, srcRect, *layerData, dx, dy)) { 247 return; 248 } 249 } 250#endif 251 252 if (config_.compositeMode == LiteWinConfig::COPY) { 253 FlushWithModeCopy(srcRect, layerData, dx, dy); 254 } else if (config_.compositeMode == LiteWinConfig::BLEND) { 255 FlushWithModeBlend(srcRect, layerData, dx, dy); 256 } 257} 258 259Surface* LiteWindow::GetSurface() 260{ 261 return surface_; 262} 263 264void LiteWindow::MoveTo(int16_t x, int16_t y) 265{ 266 GRAPHIC_LOGI("{%d,%d}=>{%d,%d}", config_.rect.GetLeft(), config_.rect.GetTop(), x, y); 267 LiteWM* liteWM = LiteWM::GetInstance(); 268 liteWM->UpdateWindowRegion(this, config_.rect); 269 config_.rect.SetPosition(x, y); 270 liteWM->UpdateWindowRegion(this, config_.rect); 271} 272 273void LiteWindow::Resize(int16_t width, int16_t height) 274{ 275 GRAPHIC_LOGI("{%d,%d}=>{%d,%d}", config_.rect.GetWidth(), config_.rect.GetHeight(), width, height); 276 config_.rect.Resize(width, height); 277 ResizeSurface(width, height); 278} 279} 280