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 "components/root_view.h"
17
18 #include "common/screen.h"
19 #include "core/render_manager.h"
20 #include "draw/draw_utils.h"
21 #include "gfx_utils/graphic_log.h"
22 #if defined(ENABLE_WINDOW) && ENABLE_WINDOW
23 #include "window/window_impl.h"
24 #endif
25 #include "securec.h"
26 namespace OHOS {
27 namespace {
28 #if defined(LOCAL_RENDER) && LOCAL_RENDER
29 const constexpr uint8_t MAX_SPLIT_NUM = 32; // split at most 32 parts
30 // view along with its parents and siblings are at most 128
31 const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH * 2;
32 #else
33 const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH;
34 const constexpr uint8_t MAX_INVALIDATE_SIZE = 24;
35 #endif
36 static Rect g_maskStack[COMPONENT_NESTING_DEPTH];
37 static UIView* g_viewStack[VIEW_STACK_DEPTH];
38 } // namespace
RootView()39 RootView::RootView()
40 {
41 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
42 pthread_mutex_init(&lock_, nullptr);
43 #endif
44 InitDrawContext();
45 }
46
GetInstance()47 RootView* RootView::GetInstance()
48 {
49 static RootView instance;
50 return &instance;
51 }
52
~RootView()53 RootView::~RootView()
54 {
55 DestroyDrawContext();
56 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
57 pthread_mutex_destroy(&lock_);
58 #endif
59 }
60 #if defined(ENABLE_WINDOW) && ENABLE_WINDOW
GetBoundWindow() const61 Window* RootView::GetBoundWindow() const
62 {
63 return boundWindow_;
64 }
65 #endif
66
GetScreenRect()67 Rect RootView::GetScreenRect()
68 {
69 #if defined(ENABLE_WINDOW) && ENABLE_WINDOW
70 Rect screenRect = GetRect();
71 #else
72 Rect screenRect(0, 0, Screen::GetInstance().GetWidth() - 1, Screen::GetInstance().GetHeight() - 1);
73 #endif
74 return screenRect;
75 }
76
77 #if defined(LOCAL_RENDER) && LOCAL_RENDER
78 using namespace Graphic;
DivideInvalidateRect(const Rect & originRect,Rect & leftoverRect,Vector<Rect> & splitRects)79 static void DivideInvalidateRect(const Rect& originRect, Rect& leftoverRect, Vector<Rect>& splitRects)
80 {
81 Rect mask;
82 if (!mask.Intersect(originRect, leftoverRect)) {
83 splitRects.PushBack(leftoverRect);
84 return;
85 }
86
87 /*
88 * +---+---+---+
89 * | | A | | originRect :A+B
90 * | +---+ | leftoverRect :A->0
91 * | B | mask :A
92 * +-----------+
93 */
94 if (originRect.IsContains(leftoverRect)) {
95 return;
96 }
97
98 int16_t reserveCnt = MAX_SPLIT_NUM - splitRects.Size();
99 if (reserveCnt <= 0) {
100 splitRects.PushBack(leftoverRect);
101 return;
102 }
103
104 if (mask.GetWidth() == leftoverRect.GetWidth()) {
105 /*
106 * +---+
107 * | A | originRect :B+C
108 * +-----------+ leftoverRect :A+B->A
109 * | | B | | mask :B
110 * | +---+ |
111 * | C |
112 * +-----------+
113 */
114 if (mask.GetBottom() == leftoverRect.GetBottom()) {
115 leftoverRect.SetBottom(mask.GetTop() - 1);
116 } else if (mask.GetTop() == leftoverRect.GetTop()) {
117 leftoverRect.SetTop(mask.GetBottom() + 1);
118 } else {
119 splitRects.PushBack(leftoverRect);
120 splitRects.Back().SetBottom(mask.GetTop() - 1);
121 leftoverRect.SetTop(mask.GetBottom() + 1);
122 }
123 splitRects.PushBack(leftoverRect);
124 return;
125 }
126 if (mask.GetHeight() == leftoverRect.GetHeight()) {
127 /*
128 * +---------+ originRect :B+C
129 * +-------+ | leftoverRect :A+B->A
130 * | A | B | C | mask :B
131 * +-------+ |
132 * +---------+
133 */
134 if (mask.GetLeft() == leftoverRect.GetLeft()) {
135 leftoverRect.SetLeft(mask.GetRight() + 1);
136 } else if (mask.GetRight() == leftoverRect.GetRight()) {
137 leftoverRect.SetRight(mask.GetLeft() - 1);
138 } else {
139 splitRects.PushBack(leftoverRect);
140 splitRects.Back().SetRight(mask.GetLeft() - 1);
141 leftoverRect.SetLeft(mask.GetRight() + 1);
142 }
143 splitRects.PushBack(leftoverRect);
144 return;
145 }
146
147 Vector<Rect> copyRect(splitRects);
148 if (mask.GetLeft() != leftoverRect.GetLeft()) {
149 /*
150 * |
151 * +-------+
152 * | +---+ mask :A
153 * | B | A | leftoverRect :A+B
154 * | +---+
155 * +-------+
156 * |
157 */
158 if (reserveCnt-- <= 0) {
159 splitRects.Swap(copyRect);
160 splitRects.PushBack(leftoverRect);
161 return;
162 }
163 splitRects.PushBack(leftoverRect);
164 splitRects.Back().SetRight(mask.GetLeft() - 1);
165 leftoverRect.SetLeft(mask.GetLeft());
166 }
167
168 if (mask.GetTop() != leftoverRect.GetTop()) {
169 /*
170 * +-------+
171 * | B | mask :A
172 * ---+---+--- leftoverRect :A+B
173 * | | A | |
174 * +-+---+-+
175 */
176 if (reserveCnt-- <= 0) {
177 splitRects.Swap(copyRect);
178 splitRects.PushBack(leftoverRect);
179 return;
180 }
181 splitRects.PushBack(leftoverRect);
182 splitRects.Back().SetBottom(mask.GetTop() - 1);
183 leftoverRect.SetTop(mask.GetTop());
184 }
185
186 if (mask.GetRight() != leftoverRect.GetRight()) {
187 /*
188 * |
189 * +-------+
190 * +---+ | mask :A
191 * | A | B | leftoverRect :A+B
192 * +---+ |
193 * +-------+
194 * |
195 */
196 if (reserveCnt-- <= 0) {
197 splitRects.Swap(copyRect);
198 splitRects.PushBack(leftoverRect);
199 return;
200 }
201 splitRects.PushBack(leftoverRect);
202 splitRects.Back().SetLeft(mask.GetRight() + 1);
203 leftoverRect.SetRight(mask.GetRight());
204 }
205
206 if (mask.GetBottom() != leftoverRect.GetBottom()) {
207 /*
208 * +-+---+-+
209 * | | A | | mask :A
210 * ---+---+--- leftoverRect :A+B
211 * | B |
212 * +-------+
213 */
214 if (reserveCnt-- <= 0) {
215 splitRects.Swap(copyRect);
216 splitRects.PushBack(leftoverRect);
217 return;
218 }
219 splitRects.PushBack(leftoverRect);
220 splitRects.Back().SetTop(mask.GetBottom() + 1);
221 leftoverRect.SetBottom(mask.GetBottom());
222 }
223 return;
224 }
225
AddRenderedRects(Rect & rect,List<Rect> & renderedRects,ListNode<Rect> * iter)226 static void AddRenderedRects(Rect& rect, List<Rect>& renderedRects, ListNode<Rect>* iter)
227 {
228 /* Elements at front have larger area and more relevance */
229 for (; iter != renderedRects.End(); iter = iter->next_) {
230 Rect& curRect = iter->data_;
231 if (!curRect.IsIntersect(rect)) {
232 continue;
233 }
234
235 if (curRect.IsContains(rect)) {
236 return;
237 }
238
239 /* Merge two rects */
240 if (rect.IsContains(curRect)) {
241 } else if (((curRect.GetLeft() == rect.GetLeft()) && (curRect.GetRight() == rect.GetRight())) ||
242 ((curRect.GetTop() == rect.GetTop()) && (curRect.GetBottom() == rect.GetBottom()))) {
243 rect.Join(curRect, rect);
244 } else {
245 continue;
246 }
247 iter = renderedRects.Remove(iter)->prev_;
248 break;
249 }
250 if (iter == renderedRects.End()) { // No merge rises
251 if (renderedRects.Size() == 128) { // record 128 rendered rects at most
252 renderedRects.PopBack();
253 }
254 renderedRects.PushFront(rect);
255 } else { // merge rises, go over the rest nodes
256 AddRenderedRects(rect, renderedRects, iter);
257 }
258 }
259
RemoveViewFromInvalidMap(UIView * view)260 void RootView::RemoveViewFromInvalidMap(UIView* view)
261 {
262 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
263 pthread_mutex_lock(&lock_);
264 #endif
265
266 int16_t stackCount = 0;
267 do {
268 while (view != nullptr) {
269 /* delete node itself */
270 auto entry = invalidateMap_.find(view);
271 if (entry != invalidateMap_.end()) {
272 invalidateMap_.erase(entry);
273 }
274 /* delete node's children */
275 if (view->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
276 g_viewStack[stackCount++] = view;
277 view = static_cast<UIViewGroup*>(view)->GetChildrenRenderHead();
278 continue;
279 }
280 /* only go to child's render sibling */
281 view = view->GetNextRenderSibling();
282 }
283 if (--stackCount >= 0) {
284 view = g_viewStack[stackCount]->GetNextRenderSibling();
285 }
286 } while (stackCount >= 0);
287
288 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
289 pthread_mutex_unlock(&lock_);
290 #endif
291 }
292
OptimizeInvalidView(UIView * curview,UIView * background,List<Rect> & renderedRects)293 void RootView::OptimizeInvalidView(UIView* curview, UIView* background, List<Rect>& renderedRects)
294 {
295 if (curview == nullptr) {
296 return;
297 }
298 auto mapEntry = invalidateMap_.find(curview);
299 if (mapEntry == invalidateMap_.end()) {
300 return;
301 }
302
303 Rect& invalidRect = mapEntry->second.Front();
304 /* Transparent views should draw from background */
305 if (((curview->GetStyleConst().bgOpa_ != OPA_OPAQUE) || (curview->GetOpaScale() != OPA_OPAQUE) ||
306 (!curview->IsTransInvalid())) &&
307 (curview != this)) {
308 AddInvalidateRect(invalidRect, background);
309 invalidateMap_.erase(mapEntry);
310 return;
311 }
312
313 /* Remove the rendered parts and split the origin rect into splitInvalidRects
314 * For performance reason, split numbers are strictly restrained.
315 */
316 Vector<Rect> splitInvalidRects(MAX_SPLIT_NUM << 1);
317 Rect invalidRectCopy(invalidRect);
318 /* Using forward order because entries at the front are closer to the current view and have larger Size */
319 for (auto iter = renderedRects.Begin(); iter != renderedRects.End(); iter = iter->next_) {
320 for (int8_t i = 0; i < mapEntry->second.Size(); i++) {
321 DivideInvalidateRect(iter->data_, mapEntry->second[i], splitInvalidRects);
322 }
323 mapEntry->second.Swap(splitInvalidRects);
324 splitInvalidRects.Clear();
325 }
326
327 /* Add new opaque rects */
328 Rect preDrawRect(invalidRectCopy);
329 if (!curview->OnPreDraw(preDrawRect)) {
330 AddInvalidateRect(invalidRectCopy, background);
331 }
332 AddRenderedRects(preDrawRect, renderedRects, renderedRects.Begin());
333 }
334
OptimizeInvalidMap()335 void RootView::OptimizeInvalidMap()
336 {
337 UIView* curview = this;
338 int16_t stackCount = 0;
339 int16_t opaStackCount = 0;
340 UIView* background[VIEW_STACK_DEPTH];
341 bool flags[VIEW_STACK_DEPTH]; // indicate whether stack go back from child
342 List<Rect> renderedRects; // Record rendered areas to avoid rerendering
343
344 do {
345 /* push stack */
346 if (curview != nullptr) {
347 if (stackCount >= VIEW_STACK_DEPTH) {
348 return;
349 }
350 g_viewStack[stackCount] = curview;
351 flags[stackCount++] = false;
352 curview = curview->GetNextRenderSibling();
353 continue;
354 }
355
356 curview = g_viewStack[--stackCount];
357 Rect rect;
358 if (!curview->IsVisible() || !rect.Intersect(curview->GetRect(), GetScreenRect())) {
359 curview = nullptr;
360 continue;
361 }
362 if (!flags[stackCount]) { // Back from sibling
363 if (curview->IsViewGroup()) {
364 /* Set background/topview */
365 if (((curview->GetStyleConst().bgOpa_ == OPA_OPAQUE) && (curview->GetOpaScale() == OPA_OPAQUE) &&
366 curview->IsTransInvalid()) ||
367 (curview == this)) {
368 background[opaStackCount] = curview;
369 } else {
370 background[opaStackCount] = background[opaStackCount - 1];
371 }
372 ++opaStackCount;
373 if (opaStackCount >= VIEW_STACK_DEPTH) {
374 return;
375 }
376 flags[stackCount++] = true;
377 curview = static_cast<UIViewGroup*>(curview)->GetChildrenRenderHead();
378 continue;
379 }
380 } else { // Back from child
381 opaStackCount--;
382 }
383 OptimizeInvalidView(curview, background[opaStackCount - 1], renderedRects);
384 curview = nullptr;
385 } while (stackCount > 0);
386 renderedRects.Clear();
387 }
388
DrawInvalidMap(const Rect & buffRect)389 void RootView::DrawInvalidMap(const Rect& buffRect)
390 {
391 OptimizeInvalidMap();
392 Rect rect;
393 for (auto& viewEntry : invalidateMap_) {
394 Vector<Rect>& viewRenderRect = viewEntry.second;
395 for (uint16_t i = 0; i < viewRenderRect.Size(); i++) {
396 rect.Intersect(viewRenderRect[i], buffRect);
397 DrawTop(viewEntry.first, rect);
398 }
399 }
400 }
401 #else
OptimizeAddRect(Rect & rect)402 void RootView::OptimizeAddRect(Rect& rect)
403 {
404 Rect joinRect;
405 for (ListNode<Rect>* iter = invalidateRects_.Begin(); iter != invalidateRects_.End(); iter = iter->next_) {
406 if (iter->data_.IsContains(rect)) {
407 return;
408 }
409
410 if (iter->data_.IsIntersect(rect)) {
411 joinRect.Join(iter->data_, rect);
412 if (joinRect.GetSize() < iter->data_.GetSize() + rect.GetSize()) {
413 iter->data_ = joinRect;
414 return;
415 }
416 }
417 }
418
419 if (invalidateRects_.Size() < MAX_INVALIDATE_SIZE) {
420 invalidateRects_.PushBack(rect);
421 } else {
422 invalidateRects_.Clear();
423 invalidateRects_.PushBack(GetScreenRect());
424 }
425 }
426
OptimizeInvalidateRects()427 void RootView::OptimizeInvalidateRects()
428 {
429 Rect joinRect;
430 for (ListNode<Rect>* iter1 = invalidateRects_.Begin(); iter1 != invalidateRects_.End(); iter1 = iter1->next_) {
431 for (ListNode<Rect>* iter2 = invalidateRects_.Begin(); iter2 != invalidateRects_.End(); iter2 = iter2->next_) {
432 if (iter1 == iter2) {
433 continue;
434 }
435
436 if (iter2->data_.IsIntersect(iter1->data_)) {
437 joinRect.Join(iter1->data_, iter2->data_);
438 if (joinRect.GetSize() < (iter1->data_.GetSize() + iter2->data_.GetSize())) {
439 iter2->data_ = joinRect;
440 iter1 = invalidateRects_.Remove(iter1)->prev_;
441 break;
442 }
443 }
444 }
445 }
446 }
447 #endif
448
AddInvalidateRect(Rect & rect,UIView * view)449 void RootView::AddInvalidateRect(Rect& rect, UIView* view)
450 {
451 Rect commonRect;
452 if (commonRect.Intersect(rect, GetScreenRect())) {
453 #if defined(LOCAL_RENDER) && LOCAL_RENDER
454 Vector<Rect>& invalidRects = invalidateMap_[view];
455 if (invalidRects.IsEmpty()) {
456 invalidRects.PushBack(commonRect);
457 } else {
458 invalidRects[0].Join(invalidRects[0], commonRect);
459 }
460 #else
461 OptimizeAddRect(commonRect);
462 #endif
463 }
464 }
465
AddInvalidateRectWithLock(Rect & rect,UIView * view)466 void RootView::AddInvalidateRectWithLock(Rect& rect, UIView* view)
467 {
468 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
469 pthread_mutex_lock(&lock_);
470 #endif
471
472 AddInvalidateRect(rect, view);
473
474 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
475 pthread_mutex_unlock(&lock_);
476 #endif
477 }
478
Measure()479 void RootView::Measure()
480 {
481 #if defined(LOCAL_RENDER) && LOCAL_RENDER
482 if (!invalidateMap_.empty()) {
483 MeasureView(GetChildrenRenderHead());
484 }
485 #else
486 if (invalidateRects_.Size() > 0) {
487 MeasureView(GetChildrenRenderHead());
488 }
489 #endif
490 }
491
MeasureView(UIView * view)492 void RootView::MeasureView(UIView* view)
493 {
494 int16_t stackCount = 0;
495 UIView* curView = view;
496 while (stackCount >= 0) {
497 while (curView != nullptr) {
498 if (curView->IsVisible()) {
499 curView->ReMeasure();
500 if (curView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
501 g_viewStack[stackCount++] = curView;
502 curView = static_cast<UIViewGroup*>(curView)->GetChildrenRenderHead();
503 continue;
504 }
505 }
506 curView = curView->GetNextRenderSibling();
507 }
508 if (--stackCount >= 0) {
509 curView = (g_viewStack[stackCount])->GetNextRenderSibling();
510 }
511 }
512 }
513
Render()514 void RootView::Render()
515 {
516 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
517 pthread_mutex_lock(&lock_);
518 #endif
519 #if defined(LOCAL_RENDER) && (!LOCAL_RENDER)
520 OptimizeInvalidateRects();
521 #endif
522
523 Rect flushRect(GetScreenRect());
524 #if defined(LOCAL_RENDER) && LOCAL_RENDER
525 if (!invalidateMap_.empty()) {
526 RenderManager::RenderRect(flushRect, this);
527 invalidateMap_.clear();
528 #else
529 if (invalidateRects_.Size() > 0) {
530 /* Fully draw whole reacts. If there are two buffers or more to display, buffers could be
531 independent between each other, so buffers need to be FULLY_RENDER. */
532 #if defined(FULLY_RENDER) && (FULLY_RENDER != 1)
533 flushRect = invalidateRects_.Begin()->data_;
534 // only draw invalid rects. in this case, buffers (if there are two buffers or more to display) should keep
535 // same with each others, because only delta changes write to the buffer between each frames, so it fits one
536 // buffer to display.
537 for (ListNode<Rect>* iter = invalidateRects_.Begin(); iter != invalidateRects_.End(); iter = iter->next_) {
538 RenderManager::RenderRect(iter->data_, this);
539 flushRect.Join(flushRect, iter->data_);
540 }
541 #else
542 RenderManager::RenderRect(flushRect, this);
543 #endif
544 invalidateRects_.Clear();
545 #endif
546
547 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
548 pthread_mutex_unlock(&lock_);
549 #endif
550
551 #if defined(ENABLE_WINDOW) && ENABLE_WINDOW
552 if (boundWindow_) {
553 boundWindow_->Flush();
554 boundWindow_->Update();
555 }
556 #endif
557 BaseGfxEngine::GetInstance()->Flush(flushRect);
558 } else {
559 #if defined __linux__ || defined __LITEOS__ || defined __APPLE__
560 pthread_mutex_unlock(&lock_);
561 #endif
562 }
563 }
564
565 void RootView::BlitMapBuffer(Rect& curViewRect, TransformMap& transMap, const Rect& invalidatedArea)
566 {
567 Rect invalidRect = curViewRect;
568 transMap.SetTransMapRect(curViewRect);
569 invalidRect.Join(invalidRect, transMap.GetBoxRect());
570 if (invalidRect.Intersect(invalidRect, invalidatedArea)) {
571 uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode);
572 ImageInfo imageInfo;
573 imageInfo.header.colorMode = dc_.mapBufferInfo->mode;
574 imageInfo.dataSize = dc_.mapBufferInfo->width * dc_.mapBufferInfo->height * (pxSize >> 3);
575 imageInfo.header.width = dc_.mapBufferInfo->width;
576 imageInfo.header.height = dc_.mapBufferInfo->height;
577 imageInfo.header.reserved = 0;
578 imageInfo.data = reinterpret_cast<uint8_t*>(dc_.mapBufferInfo->virAddr);
579 TransformDataInfo imageTranDataInfo = {imageInfo.header, imageInfo.data, pxSize, LEVEL0, BILINEAR};
580 BaseGfxEngine::GetInstance()->DrawTransform(*dc_.bufferInfo, invalidRect, {0, 0}, Color::Black(), OPA_OPAQUE,
581 transMap, imageTranDataInfo);
582 }
583 }
584
585 void RootView::ClearMapBuffer()
586 {
587 uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode);
588 uint32_t dataSize = dc_.mapBufferInfo->width * dc_.mapBufferInfo->height * (pxSize >> 3);
589 if (memset_s(dc_.mapBufferInfo->virAddr, dataSize, 0, dataSize) != EOK) {
590 GRAPHIC_LOGE("animator buffer memset failed.");
591 }
592 }
593
594 void RootView::UpdateMapBufferInfo(Rect& invalidatedArea)
595 {
596 int16_t width = invalidatedArea.GetWidth();
597 int16_t height = invalidatedArea.GetHeight();
598 invalidatedArea.SetWidth(height);
599 invalidatedArea.SetHeight(width);
600 dc_.mapBufferInfo->width = height;
601 dc_.mapBufferInfo->height = width;
602 dc_.mapBufferInfo->stride =
603 dc_.mapBufferInfo->width * (DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode) >> 3); // 3: Shift 3 bits
604 }
605
606 void RootView::RestoreMapBufferInfo()
607 {
608 dc_.mapBufferInfo->width = dc_.bufferInfo->width;
609 dc_.mapBufferInfo->height = dc_.bufferInfo->height;
610 dc_.mapBufferInfo->stride =
611 dc_.mapBufferInfo->width * (DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode) >> 3); // 3: Shift 3 bits
612 }
613
614 bool RootView::CheckNeedRootViewTransView(UIView *curView) {
615 if ((curView->GetViewType() == UI_IMAGE_VIEW) && (curView->GetStyle(STYLE_BORDER_WIDTH) == 0)) {
616 return false;
617 }
618 if (curView->GetViewType() == UI_TEXTURE_MAPPER) {
619 return false;
620 }
621 if (curView->IsTransInvalid()) {
622 return false;
623 }
624 return true;
625 }
626
627 void RootView::DrawTop(UIView* view, const Rect& rect)
628 {
629 if (view == nullptr) {
630 return;
631 }
632
633 int16_t stackCount = 0;
634 UIView* par = view->GetParent();
635 if (par == nullptr) {
636 par = view;
637 }
638 UIView* curView = view;
639 UIView* transViewGroup = nullptr;
640 Rect curViewRect;
641 Rect mask = rect;
642 Rect origRect;
643 Rect relativeRect;
644 bool enableAnimator = false;
645 TransformMap curTransMap;
646 bool updateMapBufferInfo = false;
647
648 #if defined(ENABLE_WINDOW) && ENABLE_WINDOW
649 WindowImpl* boundWin = static_cast<WindowImpl*>(GetBoundWindow());
650 BufferInfo* gfxDstBuffer = boundWin->GetBufferInfo();
651 UpdateBufferInfo(gfxDstBuffer);
652 #endif
653
654 while (par != nullptr) {
655 if (curView != nullptr) {
656 if (curView->IsVisible()) {
657 if (curViewRect.Intersect(curView->GetMaskedRect(), mask) || enableAnimator) {
658 if (CheckNeedRootViewTransView(curView) && !enableAnimator) {
659 origRect = curView->GetOrigRect();
660 relativeRect = curView->GetRelativeRect();
661 curView->GetTransformMap().SetInvalid(true);
662 curView->SetPosition(
663 relativeRect.GetX() - origRect.GetX() - curView->GetStyle(STYLE_MARGIN_LEFT),
664 relativeRect.GetY() - origRect.GetY() - curView->GetStyle(STYLE_MARGIN_TOP));
665
666 ClearMapBuffer();
667 curTransMap = curView->GetTransformMap();
668 enableAnimator = true;
669 }
670
671 if (enableAnimator) {
672 Rect invalidatedArea;
673 invalidatedArea.SetWidth(dc_.mapBufferInfo->width);
674 invalidatedArea.SetHeight(dc_.mapBufferInfo->height);
675 if (invalidatedArea.GetWidth() < curView->GetWidth()) {
676 UpdateMapBufferInfo(invalidatedArea);
677 updateMapBufferInfo = true;
678 }
679 curView->OnDraw(*dc_.mapBufferInfo, invalidatedArea);
680 curViewRect = invalidatedArea;
681 } else {
682 curView->OnDraw(*dc_.bufferInfo, curViewRect);
683 }
684
685 if ((curView->IsViewGroup()) && (stackCount < COMPONENT_NESTING_DEPTH)) {
686 if (enableAnimator && (transViewGroup == nullptr)) {
687 transViewGroup = curView;
688 }
689 par = curView;
690 g_viewStack[stackCount] = curView;
691 g_maskStack[stackCount] = mask;
692 stackCount++;
693 curView = static_cast<UIViewGroup*>(curView)->GetChildrenRenderHead();
694 mask = par->GetContentRect();
695 mask.Intersect(mask, curViewRect);
696 continue;
697 }
698
699 if (enableAnimator) {
700 curView->OnPostDraw(*dc_.mapBufferInfo, curViewRect);
701 } else {
702 curView->OnPostDraw(*dc_.bufferInfo, curViewRect);
703 }
704
705 if (enableAnimator && (transViewGroup == nullptr)) {
706 BlitMapBuffer(origRect, curTransMap, mask);
707 if (updateMapBufferInfo) {
708 RestoreMapBufferInfo();
709 updateMapBufferInfo = false;
710 }
711 curView->GetTransformMap().SetInvalid(false);
712 enableAnimator = false;
713 curView->SetPosition(relativeRect.GetX() - curView->GetStyle(STYLE_MARGIN_LEFT),
714 relativeRect.GetY() - curView->GetStyle(STYLE_MARGIN_TOP));
715 }
716 }
717 }
718 curView = curView->GetNextRenderSibling();
719 continue;
720 }
721 if (--stackCount >= 0) {
722 curViewRect = par->GetMaskedRect();
723 mask = g_maskStack[stackCount];
724 if (enableAnimator) {
725 par->OnPostDraw(*dc_.mapBufferInfo, curViewRect);
726 } else if (curViewRect.Intersect(curViewRect, mask)) {
727 par->OnPostDraw(*dc_.bufferInfo, curViewRect);
728 }
729
730 if (enableAnimator && transViewGroup == g_viewStack[stackCount]) {
731 BlitMapBuffer(origRect, curTransMap, mask);
732 if (updateMapBufferInfo) {
733 RestoreMapBufferInfo();
734 updateMapBufferInfo = false;
735 }
736 transViewGroup->GetTransformMap().SetInvalid(false);
737 enableAnimator = false;
738 transViewGroup->SetPosition(relativeRect.GetX() - transViewGroup->GetStyle(STYLE_MARGIN_LEFT),
739 relativeRect.GetY() - transViewGroup->GetStyle(STYLE_MARGIN_TOP));
740 transViewGroup = nullptr;
741 }
742 curView = g_viewStack[stackCount]->GetNextRenderSibling();
743 par = par->GetParent();
744 continue;
745 }
746 stackCount = 0;
747 curView = par->GetNextRenderSibling();
748 if (enableAnimator) {
749 par->OnPostDraw(*dc_.mapBufferInfo, rect);
750 } else {
751 par->OnPostDraw(*dc_.bufferInfo, rect);
752 }
753 par = par->GetParent();
754 }
755 }
756
757 UIView* RootView::GetTopUIView(const Rect& rect)
758 {
759 int16_t stackCount = 0;
760 UIView* currentView = this;
761 UIView* topView = currentView;
762 Rect copyRect(rect);
763 while (stackCount >= 0) {
764 while (currentView != nullptr) {
765 if (currentView->GetOrigRect().IsContains(rect) && currentView->IsVisible()) {
766 if (currentView->GetStyle(STYLE_BACKGROUND_OPA) == OPA_OPAQUE && currentView->OnPreDraw(copyRect) &&
767 currentView->GetOpaScale() == OPA_OPAQUE) {
768 topView = currentView;
769 }
770 if (currentView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
771 g_viewStack[stackCount++] = currentView;
772 currentView = static_cast<UIViewGroup*>(currentView)->GetChildrenRenderHead();
773 continue;
774 }
775 }
776 currentView = currentView->GetNextRenderSibling();
777 }
778 if (--stackCount >= 0) {
779 currentView = (g_viewStack[stackCount])->GetNextRenderSibling();
780 }
781 }
782 UIView* parentView = topView;
783 while (parentView->GetParent() != nullptr) {
784 UIView* tempView = parentView;
785 parentView = parentView->GetParent();
786 if (!tempView->IsTransInvalid()) {
787 topView = parentView;
788 }
789 }
790 return topView;
791 }
792
793 bool RootView::FindSubView(const UIView& parentView, const UIView* subView)
794 {
795 const UIView* root = &parentView;
796 if (root == subView) {
797 return true;
798 } else if (!root->IsViewGroup() || (subView == nullptr)) {
799 return false;
800 }
801
802 UIView* currentView = static_cast<const UIViewGroup*>(root)->GetChildrenRenderHead();
803 const UIView* parent = root;
804 int8_t deep = 1;
805 while (deep > 0) {
806 if (parent == nullptr) {
807 return false;
808 }
809 if (currentView == subView) {
810 return true;
811 }
812 if (currentView == nullptr) {
813 currentView = parent->GetNextRenderSibling();
814 parent = parent->GetParent();
815 deep--;
816 } else if (currentView->IsViewGroup()) {
817 parent = currentView;
818 currentView = static_cast<UIViewGroup*>(currentView)->GetChildrenRenderHead();
819 deep++;
820 } else {
821 currentView = currentView->GetNextRenderSibling();
822 }
823 }
824 return false;
825 }
826
827 void RootView::InitMapBufferInfo(BufferInfo* bufferInfo)
828 {
829 dc_.mapBufferInfo = new BufferInfo();
830 if (dc_.mapBufferInfo == nullptr) {
831 return;
832 }
833
834 if (memcpy_s(dc_.mapBufferInfo, sizeof(BufferInfo), bufferInfo, sizeof(BufferInfo)) != EOK) {
835 delete dc_.mapBufferInfo;
836 dc_.mapBufferInfo = nullptr;
837 return;
838 }
839 dc_.mapBufferInfo->mode = ARGB8888;
840 dc_.mapBufferInfo->stride = dc_.mapBufferInfo->width * (DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode) >>
841 3); // 3: Shift right 3 bits
842
843 BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
844 baseGfxEngine->AdjustLineStride(*dc_.mapBufferInfo);
845 uint32_t bufferSize = dc_.mapBufferInfo->stride * dc_.mapBufferInfo->height;
846 dc_.mapBufferInfo->virAddr = dc_.mapBufferInfo->phyAddr =
847 baseGfxEngine->AllocBuffer(bufferSize, BUFFER_MAP_SURFACE);
848 }
849
850 void RootView::DestroyMapBufferInfo()
851 {
852 if (dc_.mapBufferInfo != nullptr) {
853 BaseGfxEngine::GetInstance()->FreeBuffer(static_cast<uint8_t*>(dc_.mapBufferInfo->virAddr), BUFFER_MAP_SURFACE);
854 dc_.mapBufferInfo->virAddr = dc_.mapBufferInfo->phyAddr = nullptr;
855 delete dc_.mapBufferInfo;
856 dc_.mapBufferInfo = nullptr;
857 }
858 }
859
860 void RootView::InitDrawContext()
861 {
862 dc_.bufferInfo = BaseGfxEngine::GetInstance()->GetFBBufferInfo();
863 if (dc_.bufferInfo != nullptr) {
864 InitMapBufferInfo(dc_.bufferInfo);
865 }
866
867 bakDc_.bufferInfo = nullptr;
868 bakDc_.mapBufferInfo = nullptr;
869 }
870
871 void RootView::DestroyDrawContext()
872 {
873 DestroyMapBufferInfo();
874 }
875
876 void RootView::UpdateBufferInfo(BufferInfo* fbBufferInfo)
877 {
878 if (dc_.bufferInfo == nullptr) {
879 dc_.bufferInfo = fbBufferInfo;
880 InitMapBufferInfo(fbBufferInfo);
881 } else {
882 if (dc_.bufferInfo->width != fbBufferInfo->width || dc_.bufferInfo->height != fbBufferInfo->height ||
883 dc_.bufferInfo->mode != fbBufferInfo->mode) {
884 DestroyMapBufferInfo();
885 InitMapBufferInfo(fbBufferInfo);
886 }
887 dc_.bufferInfo = fbBufferInfo;
888 }
889 }
890
891 void RootView::SaveDrawContext()
892 {
893 bakDc_.bufferInfo = dc_.bufferInfo;
894 dc_.bufferInfo = nullptr;
895
896 bakDc_.mapBufferInfo = dc_.mapBufferInfo;
897 dc_.mapBufferInfo = nullptr;
898 }
899
900 void RootView::RestoreDrawContext()
901 {
902 DestroyDrawContext();
903
904 dc_.bufferInfo = bakDc_.bufferInfo;
905 bakDc_.bufferInfo = nullptr;
906
907 dc_.mapBufferInfo = bakDc_.mapBufferInfo;
908 bakDc_.mapBufferInfo = nullptr;
909 }
910 } // namespace OHOS
911