1 /*
2  * Copyright (c) 2023 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 #ifndef DRAW_CMD_LIST_H
17 #define DRAW_CMD_LIST_H
18 
19 #include "draw/canvas.h"
20 #include "recording/cmd_list.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 namespace Drawing {
25 class DrawOpItem;
26 class DRAWING_API DrawCmdList : public CmdList {
27 public:
28     /**
29      * @brief   there are two mode for DrawCmdList to add new op
30      * @param   IMMEDIATE   add op to continouns buffer immediately, overload will benefit from this
31      * @param   DEFERRED    add op to vector and then add to contiguous buffer if needed
32      * @detail  playback can get all op from continouns buffer in IMMEDIATE mode or vector int DEFERRED mode
33      */
34     enum class UnmarshalMode {
35         IMMEDIATE,
36         DEFERRED
37     };
38 
39     /**
40      * @brief   Creates a DrawCmdList with contiguous buffers.
41      * @param   data    A contiguous buffers.
42      * @param   isCopy  Whether to copy data or not.
43      * @detail  Called only by Unmarshalling-Thread, the default mode is DEFERRED since all DrawOp store in vector
44      */
45     static std::shared_ptr<DrawCmdList> CreateFromData(const CmdListData& data, bool isCopy = false);
46 
47     /**
48      * @brief   Creates a DrawCmdList
49      */
50     DrawCmdList(UnmarshalMode mode = UnmarshalMode::IMMEDIATE);
51     DrawCmdList(int32_t width, int32_t height, UnmarshalMode mode = UnmarshalMode::IMMEDIATE);
52 
53     /**
54      * @brief   Destroy a DrawCmdList
55      */
56     ~DrawCmdList() override;
57 
58     /**
59      * @brief   Gets cmd list type.
60      * @return  Returns DRAW_CMD_LIST
61      */
GetType()62     uint32_t GetType() const override
63     {
64         return Type::DRAW_CMD_LIST;
65     }
66 
67     /**
68      * @brief   Add DrawOpItem to DrawCmdList, only can be used in IMMEDIATE mode
69      * @param   T   The name of DrawOpItem class
70      * @param   Args    Constructs arguments to the DrawOpItem
71      * @return  true if add success, false if not in IMMEDIATE mode or create op in contiguous buffer failed
72      */
73     template<typename T, typename... Args>
AddDrawOp(Args &&...args)74     bool AddDrawOp(Args&&... args)
75     {
76         if (mode_ != UnmarshalMode::IMMEDIATE) {
77             return false;
78         }
79         std::lock_guard<std::recursive_mutex> lock(mutex_);
80         T* op = opAllocator_.Allocate<T>(std::forward<Args>(args)...);
81         if (op == nullptr) {
82             return false;
83         }
84 
85         uint32_t offset = opAllocator_.AddrToOffset(op);
86         if (lastOpItemOffset_.has_value()) {
87 #ifdef CROSS_PLATFORM
88             auto* lastOpItem = static_cast<OpItem*>(
89                 opAllocator_.OffsetToAddr(lastOpItemOffset_.__get(), sizeof(OpItem)));
90 #else
91             auto* lastOpItem = static_cast<OpItem*>(
92                 opAllocator_.OffsetToAddr(lastOpItemOffset_.value(), sizeof(OpItem)));
93 #endif
94             if (lastOpItem != nullptr) {
95                 lastOpItem->SetNextOpItemOffset(offset);
96             }
97         }
98         lastOpItemOffset_.emplace(offset);
99         opCnt_++;
100         return true;
101     }
102 
103     /**
104      * @brief   Add DrawOpItem to DrawCmdList, only can be used in DEFERRED mode
105      * @param   drawOpItem  A real DrawOpItem instance
106      * @return  true if add success, false if not in DEFERRED mode
107      */
108     bool AddDrawOp(std::shared_ptr<DrawOpItem>&& drawOpItem);
109 
110     /**
111      * @brief   Clear DrawOpItem in contiguous buffer, draw op vector, and other resource associated with draw op
112      */
113     void ClearOp();
114 
115     /**
116      * @brief   Get op vector size
117      */
118     size_t GetOpItemSize() const;
119 
120     /**
121      * @brief   for each op in vector, combine there desc together
122      */
123     std::string GetOpsWithDesc() const;
124 
125     /**
126      * @brief   Marshalling Draw Ops Param from vector to contiguous buffers.
127      */
128     void MarshallingDrawOps();
129 
130     /**
131      * @brief   Unmarshalling Draw Ops from contiguous buffers to vector
132      *          it is only called by Unmarshalling-Thread, the mode should be set to DEFERRED when create.
133      */
134     void UnmarshallingDrawOps(uint32_t* opItemCount = nullptr);
135 
136     /**
137      * @brief   Draw cmd is empty or not.
138      */
139     bool IsEmpty() const;
140 
141     /**
142      * @brief         Calls the corresponding operations of all opitems in DrawCmdList to the canvas.
143      * @param canvas  Implements the playback action of the DrawCmdList in the Canvas.
144      * @param rect    Rect used to playback, may be nullptr.
145      */
146     void Playback(Canvas& canvas, const Rect* rect = nullptr);
147 
148     /**
149      * @brief  Gets the width of the DrawCmdList.
150      */
151     int32_t GetWidth() const;
152 
153     /**
154      * @brief  Gets the height of the DrawCmdList.
155      */
156     int32_t GetHeight() const;
157 
158     /**
159      * @brief  Sets the width of the DrawCmdList.
160      */
161     void SetWidth(int32_t width);
162 
163     /**
164      * @brief  Sets the height of the DrawCmdList.
165      */
166     void SetHeight(int32_t height);
167 
168     /**
169      * @brief   Convert Textblob Op to Image Op, it is different for difference mode
170      *          IMMEDIATE: the Image Op will add to the end of buffer, and the mapped offset will be recorded in
171      *          replacedOpListForBuffer.
172      *          DEFERRED: the image Op will replace the Textblob op in vector, and the index-op_ptr will be recorded
173      *          in replacedOpListForVector.
174      */
175     void GenerateCache(Canvas* canvas = nullptr, const Rect* rect = nullptr);
176 
177     bool GetIsCache() const;
178 
179     void SetIsCache(bool isCached);
180 
181     bool GetCachedHighContrast() const;
182 
183     void SetCachedHighContrast(bool cachedHighContrast);
184 
185     std::vector<std::pair<size_t, size_t>> GetReplacedOpList();
186 
187     void SetReplacedOpList(std::vector<std::pair<size_t, size_t>> replacedOpList);
188 
189     void UpdateNodeIdToPicture(NodeId nodeId);
190 
191     size_t CountTextBlobNum();
192 
193     void Dump(std::string& out);
194 
195     void Purge();
196 
197     void SetIsNeedUnmarshalOnDestruct(bool isNeedUnmarshalOnDestruct);
198 private:
199     void ClearCache();
200     void GenerateCacheByVector(Canvas* canvas, const Rect* rect);
201     void GenerateCacheByBuffer(Canvas* canvas, const Rect* rect);
202 
203     void PlaybackToDrawCmdList(std::shared_ptr<DrawCmdList> drawCmdList);
204     void PlaybackByVector(Canvas& canvas, const Rect* rect = nullptr);
205     void PlaybackByBuffer(Canvas& canvas, const Rect* rect = nullptr);
206     void CaculatePerformanceOpType();
207 
208     int32_t width_;
209     int32_t height_;
210     const UnmarshalMode mode_;
211     const size_t offset_ = 2 * sizeof(int32_t); // 2 is width and height.Offset of first OpItem is behind the w and h
212     std::vector<std::shared_ptr<DrawOpItem>> drawOpItems_;
213 
214     size_t lastOpGenSize_ = 0;
215     std::vector<std::pair<size_t, size_t>> replacedOpListForBuffer_;
216     std::vector<std::pair<int, std::shared_ptr<DrawOpItem>>> replacedOpListForVector_;
217     bool isCached_ = false;
218     bool cachedHighContrast_ = false;
219     uint32_t performanceCaculateOpType_ = 0;
220     bool isNeedUnmarshalOnDestruct_ = false;
221 };
222 
223 using DrawCmdListPtr = std::shared_ptr<DrawCmdList>;
224 } // namespace Drawing
225 } // namespace Rosen
226 } // namespace OHOS
227 
228 #endif // DRAW_CMD_LIST_H
229