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