1 /*
2  * Copyright (c) 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 #ifndef IOS_PLATFORM
17 #include "egl_manager.h"
18 #endif
19 
20 #if defined(NEW_SKIA)
21 #include <include/gpu/GrDirectContext.h>
22 #else
23 #include <include/gpu/GrContext.h>
24 #endif
25 #include "include/gpu/gl/GrGLInterface.h"
26 
27 #if (!defined(ANDROID_PLATFORM)) && (!defined(IOS_PLATFORM))
28 #include "rs_trace.h"
29 #endif
30 
31 #include "sk_image_chain.h"
32 #include "platform/common/rs_system_properties.h"
33 
34 namespace OHOS {
35 namespace Rosen {
SKImageChain(SkCanvas * canvas,sk_sp<SkImage> image)36 SKImageChain::SKImageChain(SkCanvas* canvas, sk_sp<SkImage> image) : canvas_(canvas), image_(image)
37 {}
38 
SKImageChain(std::shared_ptr<Media::PixelMap> srcPixelMap)39 SKImageChain::SKImageChain(std::shared_ptr<Media::PixelMap> srcPixelMap) : srcPixelMap_(srcPixelMap)
40 {}
41 
~SKImageChain()42 SKImageChain::~SKImageChain()
43 {
44     canvas_ = nullptr;
45     gpuSurface_ = nullptr;
46     dstPixmap_ = nullptr;
47     srcPixelMap_ = nullptr;
48     dstPixelMap_ = nullptr;
49     filters_ = nullptr;
50     cpuSurface_ = nullptr;
51     image_ = nullptr;
52 }
53 
Render(const std::vector<sk_sp<SkImageFilter>> & skFilters,const bool & forceCPU,std::shared_ptr<Media::PixelMap> & dstPixelMap)54 DrawError SKImageChain::Render(const std::vector<sk_sp<SkImageFilter>>& skFilters, const bool& forceCPU,
55     std::shared_ptr<Media::PixelMap>& dstPixelMap)
56 {
57     for (auto filter : skFilters) {
58         SetFilters(filter);
59     }
60 
61     ForceCPU(forceCPU);
62     DrawError ret = Draw();
63     if (ret == DrawError::ERR_OK) {
64         dstPixelMap = GetPixelMap();
65     } else {
66         LOGE("skImage.Draw() = %{public}d", ret);
67     }
68 
69     return ret;
70 }
71 
InitWithoutCanvas()72 DrawError SKImageChain::InitWithoutCanvas()
73 {
74     if (srcPixelMap_ == nullptr) {
75         LOGE("The srcPixelMap_ is nullptr.");
76         return DrawError::ERR_IMAGE_NULL;
77     }
78     imageInfo_ = SkImageInfo::Make(srcPixelMap_->GetWidth(), srcPixelMap_->GetHeight(),
79     PixelFormatConvert(srcPixelMap_->GetPixelFormat()), static_cast<SkAlphaType>(srcPixelMap_->GetAlphaType()));
80     SkPixmap srcPixmap(imageInfo_, srcPixelMap_->GetPixels(), srcPixelMap_->GetRowStride());
81     SkBitmap srcBitmap;
82     srcBitmap.installPixels(srcPixmap);
83     image_ = SkImage::MakeFromBitmap(srcBitmap);
84     Media::InitializationOptions opts;
85     opts.size.width = srcPixelMap_->GetWidth();
86     opts.size.height = srcPixelMap_->GetHeight();
87     opts.editable = true;
88     auto dstPixelMap = Media::PixelMap::Create(opts);
89     if (dstPixelMap != nullptr) {
90         dstPixmap_ = std::make_shared<SkPixmap>(imageInfo_, dstPixelMap->GetPixels(), dstPixelMap->GetRowStride());
91         dstPixelMap_ = std::shared_ptr<Media::PixelMap>(dstPixelMap.release());
92     } else {
93         LOGE("Failed to create the dstPixelMap.");
94         return DrawError::ERR_IMAGE_NULL;
95     }
96 
97     return DrawError::ERR_OK;
98 }
99 
CreateCPUCanvas()100 bool SKImageChain::CreateCPUCanvas()
101 {
102     if (dstPixmap_ == nullptr) {
103         LOGE("The dstPixmap_ is nullptr.");
104         return false;
105     }
106     cpuSurface_ = SkSurface::MakeRasterDirect(imageInfo_, const_cast<void*>(dstPixmap_->addr()),
107     dstPixelMap_->GetRowStride());
108     if (!cpuSurface_) {
109         LOGE("Failed to create surface for CPU.");
110         return false;
111     }
112     canvas_ = cpuSurface_->getCanvas();
113     if (canvas_ == nullptr) {
114         LOGE("Failed to getCanvas for CPU.");
115         return false;
116     }
117 
118     return true;
119 }
120 
CreateGPUCanvas()121 bool SKImageChain::CreateGPUCanvas()
122 {
123 #if defined(ACE_ENABLE_GL) && (!defined(IOS_PLATFORM))
124     if (!EglManager::GetInstance().Init()) {
125         LOGE("Failed to init for GPU.");
126         return false;
127     }
128     sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
129 #if defined(NEW_SKIA)
130     sk_sp<GrDirectContext> grContext(GrDirectContext::MakeGL(std::move(glInterface)));
131 #else
132     sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface)));
133 #endif
134     gpuSurface_ = SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kNo, imageInfo_);
135     if (!gpuSurface_) {
136         LOGE("Failed to create surface for GPU.");
137         return false;
138     }
139     canvas_ = gpuSurface_->getCanvas();
140     if (canvas_ == nullptr) {
141         LOGE("Failed to getCanvas for GPU.");
142         return false;
143     }
144 
145     return true;
146 #else
147     LOGI("GPU rendering is not supported.");
148     return false;
149 #endif
150 }
151 
ForceCPU(bool forceCPU)152 void SKImageChain::ForceCPU(bool forceCPU)
153 {
154     if (forceCPU_ == forceCPU) {
155         LOGI("Same result without change.");
156         return;
157     }
158     forceCPU_ = forceCPU;
159     if (canvas_ == nullptr) {
160         LOGI("The canvas_ is nullptr.");
161         return;
162     }
163     if (forceCPU) {
164         if (cpuSurface_ != nullptr) {
165             canvas_ = cpuSurface_->getCanvas();
166         } else {
167             canvas_ = nullptr;
168         }
169     } else {
170         if (gpuSurface_ != nullptr) {
171             canvas_ = gpuSurface_->getCanvas();
172         } else {
173             canvas_ = nullptr;
174         }
175     }
176 }
177 
SetFilters(sk_sp<SkImageFilter> filter)178 void SKImageChain::SetFilters(sk_sp<SkImageFilter> filter)
179 {
180     if (filters_ == nullptr) {
181         filters_ = filter;
182     } else {
183         filters_ = SkImageFilters::Compose(filter, filters_);
184     }
185 }
186 
SetClipRect(SkRect * rect)187 void SKImageChain::SetClipRect(SkRect* rect)
188 {
189     rect_ = rect;
190 }
191 
SetClipPath(SkPath * path)192 void SKImageChain::SetClipPath(SkPath* path)
193 {
194     path_ = path;
195 }
196 
SetClipRRect(SkRRect * rRect)197 void SKImageChain::SetClipRRect(SkRRect* rRect)
198 {
199     rRect_ = rRect;
200 }
201 
GetPixelMap()202 std::shared_ptr<Media::PixelMap> SKImageChain::GetPixelMap()
203 {
204     return dstPixelMap_;
205 }
206 
InitializeCanvas()207 bool SKImageChain::InitializeCanvas()
208 {
209     DrawError ret = InitWithoutCanvas();
210     if (ret != DrawError::ERR_OK) {
211         LOGE("Failed to init.");
212         return false;
213     }
214 
215     if (forceCPU_) {
216         if (!CreateCPUCanvas()) {
217             LOGE("Failed to create canvas for CPU.");
218             return false;
219         }
220     } else {
221         if (!CreateGPUCanvas()) {
222             LOGE("Failed to create canvas for GPU.");
223             return false;
224         }
225     }
226     return canvas_ != nullptr;
227 }
228 
CheckForErrors()229 DrawError SKImageChain::CheckForErrors()
230 {
231     if (canvas_ == nullptr) {
232         LOGE("Failed to create canvas");
233         return DrawError::ERR_CANVAS_NULL;
234     }
235     if (image_ == nullptr) {
236         LOGE("The image_ is nullptr, nothing to draw.");
237         return DrawError::ERR_IMAGE_NULL;
238     }
239     return DrawError::ERR_OK;
240 }
241 
SetupPaint(SkPaint & paint)242 void SKImageChain::SetupPaint(SkPaint& paint)
243 {
244     paint.setAntiAlias(true);
245     paint.setBlendMode(SkBlendMode::kSrc);
246     paint.setImageFilter(filters_);
247 }
248 
ApplyClipping()249 void SKImageChain::ApplyClipping()
250 {
251     if (rect_ != nullptr) {
252         canvas_->clipRect(*rect_, true);
253     } else if (path_ != nullptr) {
254         canvas_->clipPath(*path_, true);
255     } else if (rRect_ != nullptr) {
256         canvas_->clipRRect(*rRect_, true);
257     }
258 }
259 
DrawImage(SkPaint & paint)260 bool SKImageChain::DrawImage(SkPaint& paint)
261 {
262     canvas_->save();
263     canvas_->resetMatrix();
264 #if defined(NEW_SKIA)
265     canvas_->drawImage(image_.get(), 0, 0, SkSamplingOptions(), &paint);
266 #else
267     canvas_->drawImage(image_.get(), 0, 0, &paint);
268 #endif
269     if (!forceCPU_ && dstPixmap_ != nullptr) {
270         if (!canvas_->readPixels(*dstPixmap_.get(), 0, 0)) {
271             LOGE("Failed to readPixels to target Pixmap.");
272             canvas_->restore();
273             return false;
274         }
275     }
276     canvas_->restore();
277     return true;
278 }
279 
Draw()280 DrawError SKImageChain::Draw()
281 {
282     if (!InitializeCanvas()) {
283         return DrawError::ERR_CPU_CANVAS;
284     }
285 
286     DrawError error = CheckForErrors();
287     if (error != DrawError::ERR_OK) {
288         return error;
289     }
290 #if (!defined(ANDROID_PLATFORM)) && (!defined(IOS_PLATFORM))
291     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SKImageChain::Draw");
292 #endif
293     SkPaint paint;
294     SetupPaint(paint);
295     ApplyClipping();
296 
297     if (!DrawImage(paint)) {
298         return DrawError::ERR_PIXEL_READ;
299     }
300 #if (!defined(ANDROID_PLATFORM)) && (!defined(IOS_PLATFORM))
301     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
302 #endif
303     return DrawError::ERR_OK;
304 }
305 
PixelFormatConvert(const Media::PixelFormat & pixelFormat)306 SkColorType SKImageChain::PixelFormatConvert(const Media::PixelFormat& pixelFormat)
307 {
308     SkColorType colorType;
309     switch (pixelFormat) {
310         case Media::PixelFormat::BGRA_8888:
311             colorType = SkColorType::kBGRA_8888_SkColorType;
312             break;
313         case Media::PixelFormat::RGBA_8888:
314             colorType = SkColorType::kRGBA_8888_SkColorType;
315             break;
316         case Media::PixelFormat::RGB_565:
317             colorType = SkColorType::kRGB_565_SkColorType;
318             break;
319         case Media::PixelFormat::ALPHA_8:
320             colorType = SkColorType::kAlpha_8_SkColorType;
321             break;
322         default:
323             colorType = SkColorType::kUnknown_SkColorType;
324             break;
325     }
326     return colorType;
327 }
328 } // namespcae Rosen
329 } // namespace OHOS