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