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