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