1 /*
2 * Copyright (c) 2021-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 #include "pipeline/rs_draw_cmd_list.h"
17
18 #include <unordered_map>
19
20 #include "rs_trace.h"
21
22 #include "pipeline/rs_draw_cmd.h"
23 #include "pipeline/rs_paint_filter_canvas.h"
24 #include "platform/common/rs_log.h"
25 #include "platform/common/rs_system_properties.h"
26 #include "transaction/rs_marshalling_helper.h"
27
28 namespace OHOS {
29 namespace Rosen {
30 using OpUnmarshallingFunc = OpItem* (*)(Parcel& parcel);
31
32 static std::unordered_map<RSOpType, OpUnmarshallingFunc> opUnmarshallingFuncLUT = {
33 { RECT_OPITEM, RectOpItem::Unmarshalling },
34 { ROUND_RECT_OPITEM, RoundRectOpItem::Unmarshalling },
35 { IMAGE_WITH_PARM_OPITEM, ImageWithParmOpItem::Unmarshalling },
36 { DRRECT_OPITEM, DRRectOpItem::Unmarshalling },
37 { OVAL_OPITEM, OvalOpItem::Unmarshalling },
38 { REGION_OPITEM, RegionOpItem::Unmarshalling },
39 { ARC_OPITEM, ArcOpItem::Unmarshalling },
40 { SAVE_OPITEM, SaveOpItem::Unmarshalling },
41 { RESTORE_OPITEM, RestoreOpItem::Unmarshalling },
42 { FLUSH_OPITEM, FlushOpItem::Unmarshalling },
43 { MATRIX_OPITEM, MatrixOpItem::Unmarshalling },
44 { CLIP_RECT_OPITEM, ClipRectOpItem::Unmarshalling },
45 { CLIP_RRECT_OPITEM, ClipRRectOpItem::Unmarshalling },
46 { CLIP_REGION_OPITEM, ClipRegionOpItem::Unmarshalling },
47 { TRANSLATE_OPITEM, TranslateOpItem::Unmarshalling },
48 { TEXTBLOB_OPITEM, TextBlobOpItem::Unmarshalling },
49 { BITMAP_OPITEM, BitmapOpItem::Unmarshalling },
50 { BITMAP_RECT_OPITEM, BitmapRectOpItem::Unmarshalling },
51 { BITMAP_NINE_OPITEM, BitmapNineOpItem::Unmarshalling },
52 { PIXELMAP_OPITEM, PixelMapOpItem::Unmarshalling },
53 { PIXELMAP_RECT_OPITEM, PixelMapRectOpItem::Unmarshalling },
54 { ADAPTIVE_RRECT_OPITEM, AdaptiveRRectOpItem::Unmarshalling },
55 { ADAPTIVE_RRECT_SCALE_OPITEM, AdaptiveRRectScaleOpItem::Unmarshalling },
56 { CLIP_ADAPTIVE_RRECT_OPITEM, ClipAdaptiveRRectOpItem::Unmarshalling },
57 { CLIP_OUTSET_RECT_OPITEM, ClipOutsetRectOpItem::Unmarshalling },
58 { PATH_OPITEM, PathOpItem::Unmarshalling },
59 { CLIP_PATH_OPITEM, ClipPathOpItem::Unmarshalling },
60 { PAINT_OPITEM, PaintOpItem::Unmarshalling },
61 { CONCAT_OPITEM, ConcatOpItem::Unmarshalling },
62 { SAVE_LAYER_OPITEM, SaveLayerOpItem::Unmarshalling },
63 { DRAWABLE_OPITEM, DrawableOpItem::Unmarshalling },
64 { PICTURE_OPITEM, PictureOpItem::Unmarshalling },
65 { POINTS_OPITEM, PointsOpItem::Unmarshalling },
66 { VERTICES_OPITEM, VerticesOpItem::Unmarshalling },
67 { SHADOW_REC_OPITEM, ShadowRecOpItem::Unmarshalling },
68 { MULTIPLY_ALPHA_OPITEM, MultiplyAlphaOpItem::Unmarshalling },
69 { SAVE_ALPHA_OPITEM, SaveAlphaOpItem::Unmarshalling },
70 { RESTORE_ALPHA_OPITEM, RestoreAlphaOpItem::Unmarshalling },
71 };
72
GetOpUnmarshallingFunc(RSOpType type)73 static OpUnmarshallingFunc GetOpUnmarshallingFunc(RSOpType type)
74 {
75 auto it = opUnmarshallingFuncLUT.find(type);
76 if (it == opUnmarshallingFuncLUT.end()) {
77 return nullptr;
78 }
79 return it->second;
80 }
81
DrawCmdList(int w,int h)82 DrawCmdList::DrawCmdList(int w, int h) : width_(w), height_(h) {}
83
~DrawCmdList()84 DrawCmdList::~DrawCmdList()
85 {
86 ClearOp();
87 }
88
AddOp(std::unique_ptr<OpItem> && op)89 void DrawCmdList::AddOp(std::unique_ptr<OpItem>&& op)
90 {
91 std::lock_guard<std::mutex> lock(mutex_);
92 ops_.push_back(std::move(op));
93 }
94
ClearOp()95 void DrawCmdList::ClearOp()
96 {
97 std::lock_guard<std::mutex> lock(mutex_);
98 ops_.clear();
99 }
100
operator =(DrawCmdList && that)101 DrawCmdList& DrawCmdList::operator=(DrawCmdList&& that)
102 {
103 std::lock_guard<std::mutex> lock(mutex_);
104 ops_.swap(that.ops_);
105 return *this;
106 }
107
Playback(SkCanvas & canvas,const SkRect * rect) const108 void DrawCmdList::Playback(SkCanvas& canvas, const SkRect* rect) const
109 {
110 RSPaintFilterCanvas filterCanvas(&canvas);
111 Playback(filterCanvas, rect);
112 }
113
Playback(RSPaintFilterCanvas & canvas,const SkRect * rect) const114 void DrawCmdList::Playback(RSPaintFilterCanvas& canvas, const SkRect* rect) const
115 {
116 if (width_ <= 0 || height_ <= 0) {
117 return;
118 }
119 std::lock_guard<std::mutex> lock(mutex_);
120 for (auto& it : ops_) {
121 if (it == nullptr) {
122 continue;
123 }
124 it->Draw(canvas, rect);
125 }
126 }
127
GetSize() const128 int DrawCmdList::GetSize() const
129 {
130 return ops_.size();
131 }
132
GetWidth() const133 int DrawCmdList::GetWidth() const
134 {
135 return width_;
136 }
137
GetHeight() const138 int DrawCmdList::GetHeight() const
139 {
140 return height_;
141 }
142
Marshalling(Parcel & parcel) const143 bool DrawCmdList::Marshalling(Parcel& parcel) const
144 {
145 std::lock_guard<std::mutex> lock(mutex_);
146 bool success = RSMarshallingHelper::Marshalling(parcel, width_) &&
147 RSMarshallingHelper::Marshalling(parcel, height_) &&
148 RSMarshallingHelper::Marshalling(parcel, GetSize());
149 if (!success) {
150 ROSEN_LOGE("DrawCmdList::Marshalling failed!");
151 return false;
152 }
153 for (const auto& item : ops_) {
154 auto type = item->GetType();
155 success = success && RSMarshallingHelper::Marshalling(parcel, type);
156 auto func = GetOpUnmarshallingFunc(type);
157 if (!func) {
158 ROSEN_LOGW("unirender: opItem Unmarshalling func not define, skip Marshalling, optype = %d", type);
159 continue;
160 }
161
162 success = success && item->Marshalling(parcel);
163 if (!success) {
164 ROSEN_LOGE("unirender: failed opItem Marshalling, optype = %d", type);
165 return success;
166 }
167 }
168 return success;
169 }
170
Unmarshalling(Parcel & parcel)171 DrawCmdList* DrawCmdList::Unmarshalling(Parcel& parcel)
172 {
173 int width;
174 int height;
175 int size;
176 if (!(RSMarshallingHelper::Unmarshalling(parcel, width) &&
177 RSMarshallingHelper::Unmarshalling(parcel, height) &&
178 RSMarshallingHelper::Unmarshalling(parcel, size))) {
179 ROSEN_LOGE("DrawCmdList::Unmarshalling failed!");
180 return nullptr;
181 }
182 std::unique_ptr<DrawCmdList> drawCmdList = std::make_unique<DrawCmdList>(width, height);
183 for (int i = 0; i < size; ++i) {
184 RSOpType type;
185 if (!RSMarshallingHelper::Unmarshalling(parcel, type)) {
186 ROSEN_LOGE("DrawCmdList::Unmarshalling failed, current processing:%d", i);
187 return nullptr;
188 }
189 auto func = GetOpUnmarshallingFunc(type);
190 if (!func) {
191 ROSEN_LOGW("unirender: opItem Unmarshalling func not define, optype = %d", type);
192 continue;
193 }
194
195 OpItem* item = (*func)(parcel);
196 if (!item) {
197 ROSEN_LOGE("unirender: failed opItem Unmarshalling, optype = %d", type);
198 return nullptr;
199 }
200
201 drawCmdList->AddOp(std::unique_ptr<OpItem>(item));
202 }
203 return drawCmdList.release();
204 }
205
GenerateCache(SkSurface * surface)206 void DrawCmdList::GenerateCache(SkSurface* surface)
207 {
208 #ifdef ROSEN_OHOS
209 if (isCached_) {
210 return;
211 }
212 isCached_ = true;
213 RS_TRACE_FUNC();
214 std::lock_guard<std::mutex> lock(mutex_);
215
216 for (auto index = 0u; index < ops_.size(); index++) {
217 auto& op = ops_[index];
218 if (auto cached_op = op->GenerateCachedOpItem(surface)) {
219 // backup the original op and position
220 opReplacedByCache_.emplace(index, op.release());
221 // replace the original op with the cached op
222 op.reset(cached_op.release());
223 }
224 }
225 #endif
226 }
227
ClearCache()228 void DrawCmdList::ClearCache()
229 {
230 #ifdef ROSEN_OHOS
231 if (!isCached_) {
232 return;
233 }
234 isCached_ = false;
235 RS_TRACE_FUNC();
236 std::lock_guard<std::mutex> lock(mutex_);
237
238 // restore the original op
239 for (auto& it : opReplacedByCache_) {
240 ops_[it.first] = std::move(it.second);
241 }
242 opReplacedByCache_.clear();
243 #endif
244 }
245
246 // modify the DrawCmdListManager instance to global to extend life cycle, fix destructor crash
247 static DrawCmdListManager gDrawCmdListManagerInstance;
248
Instance()249 DrawCmdListManager& DrawCmdListManager::Instance()
250 {
251 return gDrawCmdListManagerInstance;
252 }
253
~DrawCmdListManager()254 DrawCmdListManager::~DrawCmdListManager()
255 {
256 std::lock_guard<std::mutex> lock(listsMutex_);
257 lists_.clear();
258 }
259
RegisterDrawCmdList(NodeId id,std::shared_ptr<DrawCmdList> drawCmdList)260 void DrawCmdListManager::RegisterDrawCmdList(NodeId id, std::shared_ptr<DrawCmdList> drawCmdList)
261 {
262 std::lock_guard<std::mutex> lock(listsMutex_);
263 static bool uniEnabled = RSSystemProperties::GetUniRenderEnabled();
264 if (uniEnabled && drawCmdList) {
265 lists_[id].emplace_back(drawCmdList);
266 }
267 }
268
ClearDrawCmdList(NodeId id)269 void DrawCmdListManager::ClearDrawCmdList(NodeId id)
270 {
271 std::lock_guard<std::mutex> lock(listsMutex_);
272 auto iterator = lists_.find(id);
273 if (iterator == lists_.end()) {
274 return;
275 }
276 if (forceClear_) {
277 for (auto& weakPtr : iterator->second) {
278 if (auto ptr = weakPtr.lock()) {
279 ptr->ClearOp();
280 }
281 }
282 }
283 lists_.erase(iterator);
284 }
285
MarkForceClear(bool flag)286 void DrawCmdListManager::MarkForceClear(bool flag)
287 {
288 forceClear_ = flag;
289 }
290 } // namespace Rosen
291 } // namespace OHOS
292