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