• 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 #ifndef USE_ROSEN_DRAWING
17 #include "pipeline/rs_draw_cmd_list.h"
18 
19 #include <fstream>
20 #include <string>
21 #include <unordered_map>
22 
23 #include "rs_trace.h"
24 
25 #include "pipeline/rs_draw_cmd.h"
26 #include "pipeline/rs_paint_filter_canvas.h"
27 #include "platform/common/rs_log.h"
28 #include "transaction/rs_marshalling_helper.h"
29 
30 namespace OHOS {
31 namespace Rosen {
32 using OpUnmarshallingFunc = OpItem* (*)(Parcel& parcel);
33 
34 static std::unordered_map<RSOpType, OpUnmarshallingFunc> opUnmarshallingFuncLUT = {
35     { RECT_OPITEM,                 RectOpItem::Unmarshalling },
36     { ROUND_RECT_OPITEM,           RoundRectOpItem::Unmarshalling },
37     { IMAGE_WITH_PARM_OPITEM,      ImageWithParmOpItem::Unmarshalling },
38     { DRRECT_OPITEM,               DRRectOpItem::Unmarshalling },
39     { OVAL_OPITEM,                 OvalOpItem::Unmarshalling },
40     { REGION_OPITEM,               RegionOpItem::Unmarshalling },
41     { ARC_OPITEM,                  ArcOpItem::Unmarshalling },
42     { SAVE_OPITEM,                 SaveOpItem::Unmarshalling },
43     { RESTORE_OPITEM,              RestoreOpItem::Unmarshalling },
44     { FLUSH_OPITEM,                FlushOpItem::Unmarshalling },
45     { MATRIX_OPITEM,               MatrixOpItem::Unmarshalling },
46     { CLIP_RECT_OPITEM,            ClipRectOpItem::Unmarshalling },
47     { CLIP_RRECT_OPITEM,           ClipRRectOpItem::Unmarshalling },
48     { CLIP_REGION_OPITEM,          ClipRegionOpItem::Unmarshalling },
49     { TRANSLATE_OPITEM,            TranslateOpItem::Unmarshalling },
50     { TEXTBLOB_OPITEM,             TextBlobOpItem::Unmarshalling },
51     { BITMAP_OPITEM,               BitmapOpItem::Unmarshalling },
52     { COLOR_FILTER_BITMAP_OPITEM,  ColorFilterBitmapOpItem::Unmarshalling },
53     { BITMAP_RECT_OPITEM,          BitmapRectOpItem::Unmarshalling },
54     { BITMAP_NINE_OPITEM,          BitmapNineOpItem::Unmarshalling },
55     { PIXELMAP_OPITEM,             PixelMapOpItem::Unmarshalling },
56     { PIXELMAP_RECT_OPITEM,        PixelMapRectOpItem::Unmarshalling },
57     { ADAPTIVE_RRECT_OPITEM,       AdaptiveRRectOpItem::Unmarshalling },
58     { ADAPTIVE_RRECT_SCALE_OPITEM, AdaptiveRRectScaleOpItem::Unmarshalling },
59     { CLIP_ADAPTIVE_RRECT_OPITEM,  ClipAdaptiveRRectOpItem::Unmarshalling },
60     { CLIP_OUTSET_RECT_OPITEM,     ClipOutsetRectOpItem::Unmarshalling },
61     { PATH_OPITEM,                 PathOpItem::Unmarshalling },
62     { CLIP_PATH_OPITEM,            ClipPathOpItem::Unmarshalling },
63     { PAINT_OPITEM,                PaintOpItem::Unmarshalling },
64     { CONCAT_OPITEM,               ConcatOpItem::Unmarshalling },
65     { SAVE_LAYER_OPITEM,           SaveLayerOpItem::Unmarshalling },
66     { DRAWABLE_OPITEM,             DrawableOpItem::Unmarshalling },
67     { PICTURE_OPITEM,              PictureOpItem::Unmarshalling },
68     { POINTS_OPITEM,               PointsOpItem::Unmarshalling },
69     { VERTICES_OPITEM,             VerticesOpItem::Unmarshalling },
70     { SHADOW_REC_OPITEM,           ShadowRecOpItem::Unmarshalling },
71     { MULTIPLY_ALPHA_OPITEM,       MultiplyAlphaOpItem::Unmarshalling },
72     { SAVE_ALPHA_OPITEM,           SaveAlphaOpItem::Unmarshalling },
73     { RESTORE_ALPHA_OPITEM,        RestoreAlphaOpItem::Unmarshalling },
74 #ifdef ROSEN_OHOS
75     { SURFACEBUFFER_OPITEM,        SurfaceBufferOpItem::Unmarshalling },
76 #endif
77     { SCALE_OPITEM,               ScaleOpItem::Unmarshalling },
78 };
79 
80 #ifdef ROSEN_OHOS
GetOpUnmarshallingFunc(RSOpType type)81 OpUnmarshallingFunc DrawCmdList::GetOpUnmarshallingFunc(RSOpType type)
82 {
83     auto it = opUnmarshallingFuncLUT.find(type);
84     if (it == opUnmarshallingFuncLUT.end()) {
85         return nullptr;
86     }
87     return it->second;
88 }
89 #endif
90 
DrawCmdList(int w,int h)91 DrawCmdList::DrawCmdList(int w, int h) : width_(w), height_(h) {}
92 
~DrawCmdList()93 DrawCmdList::~DrawCmdList()
94 {
95     ClearOp();
96 }
97 
AddOp(std::unique_ptr<OpItem> && op)98 void DrawCmdList::AddOp(std::unique_ptr<OpItem>&& op)
99 {
100     std::lock_guard<std::mutex> lock(mutex_);
101     ops_.push_back(std::move(op));
102 }
103 
ClearOp()104 void DrawCmdList::ClearOp()
105 {
106     std::lock_guard<std::mutex> lock(mutex_);
107     ops_.clear();
108 }
109 
operator =(DrawCmdList && that)110 DrawCmdList& DrawCmdList::operator=(DrawCmdList&& that)
111 {
112     std::lock_guard<std::mutex> lock(mutex_);
113     ops_.swap(that.ops_);
114     return *this;
115 }
116 
Playback(SkCanvas & canvas,const SkRect * rect)117 void DrawCmdList::Playback(SkCanvas& canvas, const SkRect* rect)
118 {
119     RSPaintFilterCanvas filterCanvas(&canvas);
120     Playback(filterCanvas, rect);
121 }
122 
Playback(RSPaintFilterCanvas & canvas,const SkRect * rect)123 void DrawCmdList::Playback(RSPaintFilterCanvas& canvas, const SkRect* rect)
124 {
125     if (width_ <= 0 || height_ <= 0) {
126         return;
127     }
128     std::lock_guard<std::mutex> lock(mutex_);
129 #ifdef ROSEN_OHOS
130     // invalidate cache if high contrast flag changed
131     if (isCached_ && canvas.isHighContrastEnabled() != cachedHighContrast_) {
132         ClearCache();
133     }
134     // Generate or clear cache if cache state changed.
135     if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED && !isCached_) {
136         GenerateCache(&canvas, rect);
137     } else if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::DISABLED && isCached_) {
138         ClearCache();
139     }
140 #endif
141     for (auto& it : ops_) {
142         if (it == nullptr) {
143             continue;
144         }
145         it->Draw(canvas, rect);
146     }
147 }
148 
PlayBackForRecord(SkCanvas & canvas,int startOpId,int endOpId,int descStartOpId,const SkRect * rect)149 std::string DrawCmdList::PlayBackForRecord(SkCanvas& canvas, int startOpId, int endOpId, int descStartOpId,
150     const SkRect* rect)
151 {
152     RSPaintFilterCanvas filterCanvas(&canvas);
153     return PlayBackForRecord(filterCanvas, startOpId, endOpId, descStartOpId, rect);
154 }
155 
PlayBackForRecord(RSPaintFilterCanvas & canvas,int startOpId,int endOpId,int descStartOpId,const SkRect * rect)156 std::string DrawCmdList::PlayBackForRecord(RSPaintFilterCanvas& canvas, int startOpId, int endOpId,
157     int descStartOpId, const SkRect* rect)
158 {
159     std::string str;
160     if (width_ <= 0 || height_ <= 0) {
161         return str;
162     }
163     std::lock_guard<std::mutex> lock(mutex_);
164     for (int i = startOpId; i < endOpId; ++i) {
165         if (ops_[i] == nullptr) {
166             continue;
167         }
168         if (i < descStartOpId) {
169             ops_[i]->GetTypeWithDesc();
170         } else {
171             str += std::to_string(i) + ":";
172             str += ops_[i]->GetTypeWithDesc();
173         }
174         ops_[i]->Draw(canvas, rect);
175     }
176     return str;
177 }
178 
SetWidth(int width)179 void DrawCmdList::SetWidth(int width)
180 {
181     width_ = width;
182 }
183 
SetHeight(int height)184 void DrawCmdList::SetHeight(int height)
185 {
186     height_ = height;
187 }
188 
GetOpsWithDesc() const189 std::string DrawCmdList::GetOpsWithDesc() const
190 {
191     std::string desc;
192     for (auto& item : ops_) {
193         if (item == nullptr) {
194             continue;
195         }
196         desc += item->GetTypeWithDesc();
197     }
198     return desc + "\n";
199 }
200 
GetSize() const201 size_t DrawCmdList::GetSize() const
202 {
203     return ops_.size();
204 }
205 
GetWidth() const206 int DrawCmdList::GetWidth() const
207 {
208     return width_;
209 }
210 
GetHeight() const211 int DrawCmdList::GetHeight() const
212 {
213     return height_;
214 }
215 
UpdateNodeIdToPicture(NodeId nodeId)216 void DrawCmdList::UpdateNodeIdToPicture(NodeId nodeId)
217 {
218 #ifdef ROSEN_OHOS
219     if (imageIndexs_.empty()) {
220         RS_LOGD("DrawCmdList::UpdateNodeIdToPicture no need update");
221         return;
222     }
223     for (size_t i = 0; i < imageIndexs_.size(); i++) {
224         auto index = imageIndexs_[i];
225         if (index > ops_.size()) {
226             RS_LOGW("DrawCmdList::UpdateNodeIdToPicture index[%d] error", index);
227             continue;
228         }
229         ops_[index]->SetNodeId(nodeId);
230     }
231 #endif
232 }
233 
FindIndexOfImage() const234 void DrawCmdList::FindIndexOfImage() const
235 {
236     for (size_t index = 0; index < ops_.size(); index++) {
237         if (ops_[index]->IsImageOp()) {
238             imageIndexs_.emplace_back(index);
239         }
240     }
241 }
242 
Marshalling(Parcel & parcel) const243 bool DrawCmdList::Marshalling(Parcel& parcel) const
244 {
245 #ifdef ROSEN_OHOS
246     std::lock_guard<std::mutex> lock(mutex_);
247     FindIndexOfImage();
248     bool success = RSMarshallingHelper::Marshalling(parcel, width_) &&
249                    RSMarshallingHelper::Marshalling(parcel, height_) &&
250                    RSMarshallingHelper::Marshalling(parcel, imageIndexs_) &&
251                    RSMarshallingHelper::Marshalling(parcel, ops_) &&
252                    RSMarshallingHelper::Marshalling(parcel, isCached_) &&
253                    RSMarshallingHelper::Marshalling(parcel, cachedHighContrast_) &&
254                    RSMarshallingHelper::Marshalling(parcel, opReplacedByCache_);
255     if (!success) {
256         ROSEN_LOGE("DrawCmdList::Marshalling failed!");
257         return false;
258     }
259     return success;
260 #else
261     return true;
262 #endif
263 }
264 
Unmarshalling(Parcel & parcel)265 DrawCmdList* DrawCmdList::Unmarshalling(Parcel& parcel)
266 {
267 #ifdef ROSEN_OHOS
268     int width;
269     int height;
270     if (!(RSMarshallingHelper::Unmarshalling(parcel, width) &&
271             RSMarshallingHelper::Unmarshalling(parcel, height))) {
272         ROSEN_LOGE("DrawCmdList::Unmarshalling width&height failed!");
273         return nullptr;
274     }
275     std::unique_ptr<DrawCmdList> drawCmdList = std::make_unique<DrawCmdList>(width, height);
276     if (!(RSMarshallingHelper::Unmarshalling(parcel, drawCmdList->imageIndexs_) &&
277             RSMarshallingHelper::Unmarshalling(parcel, drawCmdList->ops_) &&
278             RSMarshallingHelper::Unmarshalling(parcel, drawCmdList->isCached_) &&
279             RSMarshallingHelper::Unmarshalling(parcel, drawCmdList->cachedHighContrast_) &&
280             RSMarshallingHelper::Unmarshalling(parcel, drawCmdList->opReplacedByCache_))) {
281         ROSEN_LOGE("DrawCmdList::Unmarshalling contents failed!");
282         return nullptr;
283     }
284     return drawCmdList.release();
285 #else
286     return nullptr;
287 #endif
288 }
289 
GenerateCache(const RSPaintFilterCanvas * canvas,const SkRect * rect)290 void DrawCmdList::GenerateCache(const RSPaintFilterCanvas* canvas, const SkRect* rect)
291 {
292 #ifdef ROSEN_OHOS
293     for (auto& op : ops_) {
294         if (!op) {
295             continue;
296         }
297         auto bounds = op->GetCacheBounds();
298         if (bounds.has_value() && bounds.value().isEmpty()) {
299             auto task = [&]() {
300                 RS_TRACE_FUNC();
301                 for (auto index = 0u; index < ops_.size(); index++) {
302                     auto& op = ops_[index];
303                     if (op == nullptr) {
304                         continue;
305                     }
306                     if (auto cached_op = op->GenerateCachedOpItem(nullptr, nullptr)) {
307                         std::lock_guard<std::mutex> lock(mutex_);
308                         // backup the original op and position
309                         opReplacedByCache_.emplace_back(index, op.release());
310                         // replace the original op with the cached op
311                         op.reset(cached_op.release());
312                     }
313                 }
314             };
315             OpItemTasks::Instance().AddTask(task);
316             break;
317         }
318     }
319     isCached_ = true;
320     cachedHighContrast_ = canvas && canvas->isHighContrastEnabled();
321 #endif
322 }
323 
ClearCache()324 void DrawCmdList::ClearCache()
325 {
326 #ifdef ROSEN_OHOS
327     RS_TRACE_FUNC();
328     // restore the original op
329     for (auto& [index, op] : opReplacedByCache_) {
330         ops_[index].reset(op.release());
331     }
332     opReplacedByCache_.clear();
333     isCached_ = false;
334 #endif
335 }
336 
337 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
CheckClipRect(SkRect & rect)338 void DrawCmdList::CheckClipRect(SkRect& rect)
339 {
340     std::lock_guard<std::mutex> lock(mutex_);
341     for (const auto& it : ops_) {
342         if (it == nullptr) {
343             continue;
344         }
345         if (it->GetType() == CLIP_RECT_OPITEM) {
346             ClipRectOpItem* clipRectOpItem = static_cast<ClipRectOpItem*>(it.get());
347             auto optionalRect = clipRectOpItem->GetClipRect();
348             if (optionalRect.has_value() && !optionalRect.value().isEmpty()) {
349                 rect = optionalRect.value();
350             }
351             break;
352         }
353     }
354 }
355 
ReplaceDrivenCmds()356 void DrawCmdList::ReplaceDrivenCmds()
357 {
358     RS_TRACE_FUNC();
359     std::lock_guard<std::mutex> lock(mutex_);
360 
361     for (auto index = 0u; index < ops_.size(); index++) {
362         auto& op = ops_[index];
363         if (op != nullptr && op->GetType() == CLIP_RECT_OPITEM) {
364             // backup the original op and position, replace the original op with nullptr
365             opReplacedByDrivenRender_.emplace_back(index, op.release());
366             break;
367         }
368     }
369 }
370 
RestoreOriginCmdsForDriven()371 void DrawCmdList::RestoreOriginCmdsForDriven()
372 {
373     RS_TRACE_FUNC();
374     std::lock_guard<std::mutex> lock(mutex_);
375 
376     // restore the original op
377     for (auto& [index, op] : opReplacedByDrivenRender_) {
378         ops_[index].reset(op.release());
379     }
380     opReplacedByDrivenRender_.clear();
381 }
382 #endif
383 } // namespace Rosen
384 } // namespace OHOS
385 #endif // USE_ROSEN_DRAWING
386