1 /*
2  * Copyright (c) 2021-2022 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_recording_canvas.h"
17 #include "pipeline/rs_draw_cmd.h"
18 #include "recording/cmd_list_helper.h"
19 #include "render/rs_pixel_map_util.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 
ExtendRecordingCanvas(int32_t width,int32_t height,bool addDrawOpImmediate)24 ExtendRecordingCanvas::ExtendRecordingCanvas(int32_t width, int32_t height, bool addDrawOpImmediate)
25     : Drawing::RecordingCanvas(width, height, addDrawOpImmediate) {}
26 
Obtain(int32_t width,int32_t height,bool addDrawOpImmediate)27 std::unique_ptr<ExtendRecordingCanvas> ExtendRecordingCanvas::Obtain(int32_t width, int32_t height,
28     bool addDrawOpImmediate)
29 {
30     std::unique_ptr<ExtendRecordingCanvas> canvas = nullptr;
31     {
32         std::lock_guard<std::mutex> lock(canvasMutex_);
33         if (canvasPool_.empty()) {
34             return std::make_unique<ExtendRecordingCanvas>(width, height, addDrawOpImmediate);
35         }
36         canvas = std::move(canvasPool_.front());
37         canvasPool_.pop();
38     }
39 
40     if (!canvas) {
41         canvas = std::make_unique<ExtendRecordingCanvas>(width, height, addDrawOpImmediate);
42     } else {
43         canvas->Reset(width, height, addDrawOpImmediate);
44     }
45     return canvas;
46 }
47 
Recycle(std::unique_ptr<ExtendRecordingCanvas> & canvas)48 void ExtendRecordingCanvas::Recycle(std::unique_ptr<ExtendRecordingCanvas>& canvas)
49 {
50     std::lock_guard<std::mutex> lock(canvasMutex_);
51     if (canvasPool_.size() >= MAX_CANVAS_SIZE) {
52         return;
53     }
54     canvasPool_.push(std::move(canvas));
55 }
56 
DrawImageWithParm(const std::shared_ptr<Drawing::Image> & image,const std::shared_ptr<Drawing::Data> & data,const Drawing::AdaptiveImageInfo & rsImageInfo,const Drawing::SamplingOptions & sampling)57 void ExtendRecordingCanvas::DrawImageWithParm(
58     const std::shared_ptr<Drawing::Image>& image, const std::shared_ptr<Drawing::Data>& data,
59     const Drawing::AdaptiveImageInfo& rsImageInfo, const Drawing::SamplingOptions& sampling)
60 {
61     if (!addDrawOpImmediate_) {
62         AddDrawOpDeferred<Drawing::DrawImageWithParmOpItem>(image, data, rsImageInfo, sampling);
63         return;
64     }
65     auto object = std::make_shared<RSExtendImageObject>(image, data, rsImageInfo);
66     auto drawCallList = Drawing::RecordingCanvas::GetDrawCmdList();
67     auto objectHandle =
68         Drawing::CmdListHelper::AddImageObjectToCmdList(*drawCallList, object);
69     AddDrawOpImmediate<Drawing::DrawImageWithParmOpItem::ConstructorHandle>(objectHandle, sampling);
70 }
71 
DrawPixelMapWithParm(const std::shared_ptr<Media::PixelMap> & pixelMap,const Drawing::AdaptiveImageInfo & rsImageInfo,const Drawing::SamplingOptions & sampling)72 void ExtendRecordingCanvas::DrawPixelMapWithParm(const std::shared_ptr<Media::PixelMap>& pixelMap,
73     const Drawing::AdaptiveImageInfo& rsImageInfo, const Drawing::SamplingOptions& sampling)
74 {
75     if (!addDrawOpImmediate_) {
76         AddDrawOpDeferred<Drawing::DrawPixelMapWithParmOpItem>(pixelMap, rsImageInfo, sampling);
77         return;
78     }
79     auto object = std::make_shared<RSExtendImageObject>(pixelMap, rsImageInfo);
80     auto drawCallList = Drawing::RecordingCanvas::GetDrawCmdList();
81     auto objectHandle =
82         Drawing::CmdListHelper::AddImageObjectToCmdList(*drawCallList, object);
83     AddDrawOpImmediate<Drawing::DrawPixelMapWithParmOpItem::ConstructorHandle>(objectHandle, sampling);
84 }
85 
DrawPixelMapRect(const std::shared_ptr<Media::PixelMap> & pixelMap,const Drawing::Rect & src,const Drawing::Rect & dst,const Drawing::SamplingOptions & sampling,Drawing::SrcRectConstraint constraint)86 void ExtendRecordingCanvas::DrawPixelMapRect(const std::shared_ptr<Media::PixelMap>& pixelMap, const Drawing::Rect& src,
87     const Drawing::Rect& dst, const Drawing::SamplingOptions& sampling,
88     Drawing::SrcRectConstraint constraint)
89 {
90     if (!addDrawOpImmediate_) {
91         AddDrawOpDeferred<Drawing::DrawPixelMapRectOpItem>(pixelMap, src, dst, sampling, constraint);
92         return;
93     }
94     auto object = std::make_shared<RSExtendImageBaseObj>(pixelMap, src, dst);
95     auto drawCallList = Drawing::RecordingCanvas::GetDrawCmdList();
96     auto objectHandle =
97         Drawing::CmdListHelper::AddImageBaseObjToCmdList(*drawCallList, object);
98     AddDrawOpImmediate<Drawing::DrawPixelMapRectOpItem::ConstructorHandle>(objectHandle, sampling, constraint);
99 }
100 
DrawDrawFunc(Drawing::RecordingCanvas::DrawFunc && drawFunc)101 void ExtendRecordingCanvas::DrawDrawFunc(Drawing::RecordingCanvas::DrawFunc&& drawFunc)
102 {
103     if (!addDrawOpImmediate_) {
104         cmdList_->AddDrawOp(std::make_shared<Drawing::DrawFuncOpItem>(std::move(drawFunc)));
105         return;
106     }
107     auto object = std::make_shared<RSExtendDrawFuncObj>(std::move(drawFunc));
108     auto drawCallList = Drawing::RecordingCanvas::GetDrawCmdList();
109     auto objectHandle =
110         Drawing::CmdListHelper::AddDrawFuncObjToCmdList(*drawCallList, object);
111     cmdList_->AddOp<Drawing::DrawFuncOpItem::ConstructorHandle>(objectHandle);
112 }
113 
114 #ifdef ROSEN_OHOS
DrawSurfaceBuffer(const DrawingSurfaceBufferInfo & surfaceBufferInfo)115 void ExtendRecordingCanvas::DrawSurfaceBuffer(const DrawingSurfaceBufferInfo& surfaceBufferInfo)
116 {
117     if (!addDrawOpImmediate_) {
118         AddDrawOpDeferred<Drawing::DrawSurfaceBufferOpItem>(surfaceBufferInfo);
119         return;
120     }
121     std::shared_ptr<Drawing::SurfaceBufferEntry> surfaceBufferEntry = std::make_shared<Drawing::SurfaceBufferEntry>(
122         surfaceBufferInfo.surfaceBuffer_, surfaceBufferInfo.acquireFence_);
123     Drawing::Rect srcRect = surfaceBufferInfo.srcRect_;
124     if ((srcRect.GetWidth() <= 0 || srcRect.GetHeight() <= 0) && surfaceBufferInfo.surfaceBuffer_) {
125         srcRect = Drawing::Rect { 0, 0, surfaceBufferInfo.surfaceBuffer_->GetWidth(),
126             surfaceBufferInfo.surfaceBuffer_->GetHeight() };
127     }
128     AddDrawOpImmediate<Drawing::DrawSurfaceBufferOpItem::ConstructorHandle>(
129         Drawing::CmdListHelper::AddSurfaceBufferEntryToCmdList(*cmdList_, surfaceBufferEntry),
130         surfaceBufferInfo.dstRect_.GetLeft(), surfaceBufferInfo.dstRect_.GetTop(),
131         surfaceBufferInfo.dstRect_.GetWidth(), surfaceBufferInfo.dstRect_.GetHeight(), surfaceBufferInfo.pid_,
132         surfaceBufferInfo.uid_, srcRect);
133 }
134 #endif
135 
136 template<typename T, typename... Args>
AddDrawOpImmediate(Args &&...args)137 void ExtendRecordingCanvas::AddDrawOpImmediate(Args&&... args)
138 {
139     bool brushValid = paintBrush_.IsValid();
140     bool penValid = paintPen_.IsValid();
141     if (!brushValid && !penValid) {
142         Drawing::PaintHandle paintHandle;
143         paintHandle.isAntiAlias = true;
144         paintHandle.style = Drawing::Paint::PaintStyle::PAINT_FILL;
145         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
146         return;
147     }
148     if (brushValid && penValid && Drawing::Paint::CanCombinePaint(paintBrush_, paintPen_)) {
149         Drawing::PaintHandle paintHandle;
150         paintPen_.SetStyle(Drawing::Paint::PaintStyle::PAINT_FILL_STROKE);
151         Drawing::DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintPen_, paintHandle);
152         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
153         paintPen_.SetStyle(Drawing::Paint::PaintStyle::PAINT_STROKE);
154         return;
155     }
156     if (brushValid) {
157         Drawing::PaintHandle paintHandle;
158         Drawing::DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintBrush_, paintHandle);
159         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
160     }
161     if (penValid) {
162         Drawing::PaintHandle paintHandle;
163         Drawing::DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintPen_, paintHandle);
164         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
165     }
166 }
167 
168 template<typename T, typename... Args>
AddDrawOpDeferred(Args &&...args)169 void ExtendRecordingCanvas::AddDrawOpDeferred(Args&&... args)
170 {
171     bool brushValid = paintBrush_.IsValid();
172     bool penValid = paintPen_.IsValid();
173     if (!brushValid && !penValid) {
174         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., defaultPaint_));
175         return;
176     }
177     if (brushValid && penValid && Drawing::Paint::CanCombinePaint(paintBrush_, paintPen_)) {
178         paintPen_.SetStyle(Drawing::Paint::PaintStyle::PAINT_FILL_STROKE);
179         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintPen_));
180         paintPen_.SetStyle(Drawing::Paint::PaintStyle::PAINT_STROKE);
181         return;
182     }
183     if (brushValid) {
184         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintBrush_));
185     }
186     if (penValid) {
187         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintPen_));
188     }
189 }
190 
DrawImageNineWithPixelMap(const std::shared_ptr<Media::PixelMap> & pixelmap,const Drawing::RectI & center,const Drawing::Rect & dst,Drawing::FilterMode filter,const Drawing::Brush * brush)191 void ExtendRecordingCanvas::DrawImageNineWithPixelMap(const std::shared_ptr<Media::PixelMap>& pixelmap,
192     const Drawing::RectI& center, const Drawing::Rect& dst, Drawing::FilterMode filter, const Drawing::Brush* brush)
193 {
194     auto image = RSPixelMapUtil::ExtractDrawingImage(pixelmap);
195     Drawing::RecordingCanvas::DrawImageNine(image.get(), center, dst, filter, brush);
196 }
197 } // namespace Rosen
198 } // namespace OHOS
199