• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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