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"
26namespace OHOS {
27namespace {
28#if defined(LOCAL_RENDER) && LOCAL_RENDER
29const constexpr uint8_t MAX_SPLIT_NUM = 32; // split at most 32 parts
30// view along with its parents and siblings are at most 128
31const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH * 2;
32#else
33const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH;
34const constexpr uint8_t MAX_INVALIDATE_SIZE = 24;
35#endif
36static Rect g_maskStack[COMPONENT_NESTING_DEPTH];
37static UIView* g_viewStack[VIEW_STACK_DEPTH];
38} // namespace
39RootView::RootView()
40{
41#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
42    pthread_mutex_init(&lock_, nullptr);
43#endif
44    InitDrawContext();
45}
46
47RootView* RootView::GetInstance()
48{
49    static RootView instance;
50    return &instance;
51}
52
53RootView::~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
61Window* RootView::GetBoundWindow() const
62{
63    return boundWindow_;
64}
65#endif
66
67Rect 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
78using namespace Graphic;
79static 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
226static 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
260void 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
293void 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
335void 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
389void 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
402void 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
427void 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
449void 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
466void 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
479void 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
492void 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
514void 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
565void 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
585void 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
594void 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
606void 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
614bool 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
627void 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
757UIView* 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
793bool 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
827void 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
850void 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
860void 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
871void RootView::DestroyDrawContext()
872{
873    DestroyMapBufferInfo();
874}
875
876void 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
891void RootView::SaveDrawContext()
892{
893    bakDc_.bufferInfo = dc_.bufferInfo;
894    dc_.bufferInfo = nullptr;
895
896    bakDc_.mapBufferInfo = dc_.mapBufferInfo;
897    dc_.mapBufferInfo = nullptr;
898}
899
900void 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