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
30 namespace 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
45 namespace {
46 static const int16_t DEFAULT_QUEUE_SIZE = 2;
47 }
48
LiteWindow(const LiteWinConfig & config)49 LiteWindow::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
~LiteWindow()57 LiteWindow::~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
CreateSurface()77 bool 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
ReleaseSurface()97 void LiteWindow::ReleaseSurface()
98 {
99 }
100
ResizeSurface(int16_t width,int16_t height)101 void 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
Update(Rect rect)115 void LiteWindow::Update(Rect rect)
116 {
117 LiteWM::GetInstance()->UpdateWindowRegion(this, rect);
118 }
119
UpdateBackBuf()120 void 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
FlushWithModeCopy(const Rect & srcRect,const LiteSurfaceData * layerData,int16_t dx,int16_t dy)154 void 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
FlushWithModeBlend(const Rect & srcRect,const LiteSurfaceData * layerData,int16_t dx,int16_t dy)182 void 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
Flush(const Rect & srcRect,const LiteSurfaceData * layerData,int16_t dx,int16_t dy)228 void 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
GetSurface()259 Surface* LiteWindow::GetSurface()
260 {
261 return surface_;
262 }
263
MoveTo(int16_t x,int16_t y)264 void 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
Resize(int16_t width,int16_t height)273 void 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