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 #include "pipeline/rs_draw_cmd.h"
17 #include "pipeline/rs_recording_canvas.h"
18 #include "platform/common/rs_log.h"
19 #include "render/rs_pixel_map_util.h"
20 #include "render/rs_image_cache.h"
21 #include "recording/cmd_list_helper.h"
22 #include "recording/draw_cmd_list.h"
23 #include "rs_trace.h"
24 #include "utils/system_properties.h"
25 #include "pipeline/rs_task_dispatcher.h"
26 #include "platform/common/rs_system_properties.h"
27 #include "pipeline/sk_resource_manager.h"
28 #ifdef ROSEN_OHOS
29 #include "common/rs_common_tools.h"
30 #include "native_buffer_inner.h"
31 #include "native_window.h"
32 #endif
33 #ifdef RS_ENABLE_VK
34 #include "include/gpu/GrBackendSemaphore.h"
35 #include "platform/ohos/backend/native_buffer_utils.h"
36 #include "platform/ohos/backend/rs_vulkan_context.h"
37 #endif
38
39 #include "include/gpu/GrDirectContext.h"
40
41 namespace OHOS {
42 namespace Rosen {
43 constexpr int32_t CORNER_SIZE = 4;
44 #ifdef ROSEN_OHOS
45 constexpr uint32_t FENCE_WAIT_TIME = 3000; // ms
46 #endif
47 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
48 constexpr uint8_t ASTC_HEADER_SIZE = 16;
49 #endif
50
51 #ifdef RS_ENABLE_VK
GetColorTypeFromVKFormat(VkFormat vkFormat)52 Drawing::ColorType GetColorTypeFromVKFormat(VkFormat vkFormat)
53 {
54 if (!RSSystemProperties::IsUseVukan()) {
55 return Drawing::COLORTYPE_RGBA_8888;
56 }
57 switch (vkFormat) {
58 case VK_FORMAT_R8G8B8A8_UNORM:
59 return Drawing::COLORTYPE_RGBA_8888;
60 case VK_FORMAT_R16G16B16A16_SFLOAT:
61 return Drawing::COLORTYPE_RGBA_F16;
62 case VK_FORMAT_R5G6B5_UNORM_PACK16:
63 return Drawing::COLORTYPE_RGB_565;
64 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
65 return Drawing::COLORTYPE_RGBA_1010102;
66 default:
67 return Drawing::COLORTYPE_RGBA_8888;
68 }
69 }
70 #endif
71
RSExtendImageObject(const std::shared_ptr<Drawing::Image> & image,const std::shared_ptr<Drawing::Data> & data,const Drawing::AdaptiveImageInfo & imageInfo)72 RSExtendImageObject::RSExtendImageObject(const std::shared_ptr<Drawing::Image>& image,
73 const std::shared_ptr<Drawing::Data>& data, const Drawing::AdaptiveImageInfo& imageInfo)
74 {
75 rsImage_ = std::make_shared<RSImage>();
76 rsImage_->SetImage(image);
77 rsImage_->SetCompressData(data, imageInfo.uniqueId, imageInfo.width, imageInfo.height);
78 rsImage_->SetImageFit(imageInfo.fitNum);
79 rsImage_->SetImageRepeat(imageInfo.repeatNum);
80 rsImage_->SetImageRotateDegree(imageInfo.rotateDegree);
81 std::vector<Drawing::Point> radiusValue(imageInfo.radius, imageInfo.radius + CORNER_SIZE);
82 rsImage_->SetRadius(radiusValue);
83 rsImage_->SetScale(imageInfo.scale);
84 imageInfo_ = imageInfo;
85 }
86
RSExtendImageObject(const std::shared_ptr<Media::PixelMap> & pixelMap,const Drawing::AdaptiveImageInfo & imageInfo)87 RSExtendImageObject::RSExtendImageObject(const std::shared_ptr<Media::PixelMap>& pixelMap,
88 const Drawing::AdaptiveImageInfo& imageInfo)
89 {
90 if (pixelMap) {
91 #ifdef ROSEN_OHOS
92 if (RSSystemProperties::GetDumpUIPixelmapEnabled()) {
93 CommonTools::SavePixelmapToFile(pixelMap, "/data/storage/el1/base/imageObject_");
94 }
95 #endif
96 rsImage_ = std::make_shared<RSImage>();
97 rsImage_->SetPixelMap(pixelMap);
98 rsImage_->SetImageFit(imageInfo.fitNum);
99 rsImage_->SetImageRotateDegree(imageInfo.rotateDegree);
100 rsImage_->SetImageRepeat(imageInfo.repeatNum);
101 std::vector<Drawing::Point> radiusValue(imageInfo.radius, imageInfo.radius + CORNER_SIZE);
102 rsImage_->SetRadius(radiusValue);
103 rsImage_->SetScale(imageInfo.scale);
104 rsImage_->SetDynamicRangeMode(imageInfo.dynamicRangeMode);
105 RectF frameRect(imageInfo.frameRect.GetLeft(),
106 imageInfo.frameRect.GetTop(),
107 imageInfo.frameRect.GetRight(),
108 imageInfo.frameRect.GetBottom());
109 rsImage_->SetFrameRect(frameRect);
110 }
111 }
112
SetNodeId(NodeId id)113 void RSExtendImageObject::SetNodeId(NodeId id)
114 {
115 if (rsImage_) {
116 rsImage_->UpdateNodeIdToPicture(id);
117 }
118 }
119
SetPaint(Drawing::Paint paint)120 void RSExtendImageObject::SetPaint(Drawing::Paint paint)
121 {
122 if (rsImage_) {
123 rsImage_->SetPaint(paint);
124 }
125 }
126
Purge()127 void RSExtendImageObject::Purge()
128 {
129 if (rsImage_) {
130 rsImage_->Purge();
131 }
132 }
133
Playback(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & sampling,bool isBackground)134 void RSExtendImageObject::Playback(Drawing::Canvas& canvas, const Drawing::Rect& rect,
135 const Drawing::SamplingOptions& sampling, bool isBackground)
136 {
137 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
138 if (!rsImage_) {
139 return;
140 }
141 std::shared_ptr<Media::PixelMap> pixelmap = rsImage_->GetPixelMap();
142 if (pixelmap && pixelmap->IsAstc()) {
143 if (auto recordingCanvas = static_cast<ExtendRecordingCanvas*>(canvas.GetRecordingCanvas())) {
144 Drawing::AdaptiveImageInfo imageInfo = rsImage_->GetAdaptiveImageInfoWithCustomizedFrameRect(rect);
145 recordingCanvas->DrawPixelMapWithParm(pixelmap, imageInfo, sampling);
146 return;
147 }
148 }
149 if (canvas.GetRecordingCanvas()) {
150 image_ = RSPixelMapUtil::ExtractDrawingImage(pixelmap);
151 if (image_) {
152 SKResourceManager::Instance().HoldResource(image_);
153 rsImage_->SetDmaImage(image_);
154 }
155 rsImage_->CanvasDrawImage(canvas, rect, sampling, isBackground);
156 return;
157 }
158 PreProcessPixelMap(canvas, pixelmap, sampling);
159 #endif
160 rsImage_->CanvasDrawImage(canvas, rect, sampling, isBackground);
161 }
162
Marshalling(Parcel & parcel) const163 bool RSExtendImageObject::Marshalling(Parcel &parcel) const
164 {
165 bool ret = RSMarshallingHelper::Marshalling(parcel, rsImage_);
166 return ret;
167 }
168
Unmarshalling(Parcel & parcel)169 RSExtendImageObject *RSExtendImageObject::Unmarshalling(Parcel &parcel)
170 {
171 auto object = new RSExtendImageObject();
172 bool ret = RSMarshallingHelper::Unmarshalling(parcel, object->rsImage_);
173 if (!ret) {
174 delete object;
175 return nullptr;
176 }
177 return object;
178 }
179
180 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
PreProcessPixelMap(Drawing::Canvas & canvas,const std::shared_ptr<Media::PixelMap> & pixelMap,const Drawing::SamplingOptions & sampling)181 void RSExtendImageObject::PreProcessPixelMap(Drawing::Canvas& canvas, const std::shared_ptr<Media::PixelMap>& pixelMap,
182 const Drawing::SamplingOptions& sampling)
183 {
184 if (!pixelMap || !rsImage_) {
185 return;
186 }
187 auto colorSpace = RSPixelMapUtil::GetPixelmapColorSpace(pixelMap);
188 #ifdef USE_VIDEO_PROCESSING_ENGINE
189 if (pixelMap->IsHdr()) {
190 colorSpace = Drawing::ColorSpace::CreateSRGB();
191 }
192 #endif
193 if (!pixelMap->IsAstc() && RSPixelMapUtil::IsSupportZeroCopy(pixelMap, sampling)) {
194 #if defined(RS_ENABLE_GL)
195 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL &&
196 GetDrawingImageFromSurfaceBuffer(canvas, reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd()))) {
197 rsImage_->SetDmaImage(image_);
198 }
199 #endif
200 #if defined(RS_ENABLE_VK)
201 if (RSSystemProperties::IsUseVukan() &&
202 GetRsImageCache(canvas, pixelMap, reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd()), colorSpace)) {
203 rsImage_->SetDmaImage(image_);
204 }
205 #endif
206 return;
207 }
208 if (pixelMap->IsAstc()) {
209 std::shared_ptr<Drawing::Data> fileData = std::make_shared<Drawing::Data>();
210 // After RS is switched to Vulkan, the judgment of GpuApiType can be deleted.
211 if (pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC &&
212 RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN) {
213 if (!nativeWindowBuffer_) {
214 sptr<SurfaceBuffer> sfBuffer(reinterpret_cast<SurfaceBuffer *>(pixelMap->GetFd()));
215 nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&sfBuffer);
216 }
217 OH_NativeBuffer* nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(nativeWindowBuffer_);
218 if (nativeBuffer == nullptr || !fileData->BuildFromOHNativeBuffer(nativeBuffer, pixelMap->GetCapacity())) {
219 LOGE("PreProcessPixelMap data BuildFromOHNativeBuffer fail");
220 return;
221 }
222 } else {
223 const void* data = pixelMap->GetPixels();
224 if (pixelMap->GetCapacity() > ASTC_HEADER_SIZE &&
225 (data == nullptr || !fileData->BuildWithoutCopy((void*)((char*) data + ASTC_HEADER_SIZE),
226 pixelMap->GetCapacity() - ASTC_HEADER_SIZE))) {
227 LOGE("PreProcessPixelMap data BuildWithoutCopy fail");
228 return;
229 }
230 }
231 rsImage_->SetCompressData(fileData);
232 return;
233 }
234 if (RSPixelMapUtil::IsYUVFormat(pixelMap)) {
235 rsImage_->MarkYUVImage();
236 }
237 }
238 #endif
239
240 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
GetRsImageCache(Drawing::Canvas & canvas,const std::shared_ptr<Media::PixelMap> & pixelMap,SurfaceBuffer * surfaceBuffer,const std::shared_ptr<Drawing::ColorSpace> & colorSpace)241 bool RSExtendImageObject::GetRsImageCache(Drawing::Canvas& canvas, const std::shared_ptr<Media::PixelMap>& pixelMap,
242 SurfaceBuffer *surfaceBuffer, const std::shared_ptr<Drawing::ColorSpace>& colorSpace)
243 {
244 if (pixelMap == nullptr) {
245 return false;
246 }
247 std::shared_ptr<Drawing::Image> imageCache = nullptr;
248 if (!pixelMap->IsEditable()) {
249 imageCache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(
250 rsImage_->GetUniqueId(), gettid());
251 }
252 if (imageCache) {
253 this->image_ = imageCache;
254 } else {
255 bool ret = MakeFromTextureForVK(
256 canvas, reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd()), colorSpace);
257 if (ret && image_ && !pixelMap->IsEditable()) {
258 SKResourceManager::Instance().HoldResource(image_);
259 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(
260 rsImage_->GetUniqueId(), image_, gettid());
261 }
262 return ret;
263 }
264 return true;
265 }
266 #endif
267
268 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_GL)
GetDrawingImageFromSurfaceBuffer(Drawing::Canvas & canvas,SurfaceBuffer * surfaceBuffer)269 bool RSExtendImageObject::GetDrawingImageFromSurfaceBuffer(Drawing::Canvas& canvas, SurfaceBuffer* surfaceBuffer)
270 {
271 if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
272 return false;
273 }
274 if (surfaceBuffer == nullptr) {
275 RS_LOGE("GetDrawingImageFromSurfaceBuffer surfaceBuffer is nullptr");
276 return false;
277 }
278 if (nativeWindowBuffer_ == nullptr) {
279 sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
280 nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&sfBuffer);
281 if (!nativeWindowBuffer_) {
282 RS_LOGE("GetDrawingImageFromSurfaceBuffer create native window buffer fail");
283 return false;
284 }
285 }
286 EGLint attrs[] = { EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE };
287
288 auto disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
289 if (eglImage_ == EGL_NO_IMAGE_KHR) {
290 eglImage_ = eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, nativeWindowBuffer_, attrs);
291 if (eglImage_ == EGL_NO_IMAGE_KHR) {
292 RS_LOGE("%{public}s create egl image fail %{public}d", __func__, eglGetError());
293 return false;
294 }
295 tid_ = gettid();
296 }
297
298 // Create texture object
299 if (texId_ == 0U) {
300 glGenTextures(1, &texId_);
301 glBindTexture(GL_TEXTURE_2D, texId_);
302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
306 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(eglImage_));
307 }
308
309 Drawing::TextureInfo externalTextureInfo;
310 externalTextureInfo.SetWidth(surfaceBuffer->GetWidth());
311 externalTextureInfo.SetHeight(surfaceBuffer->GetHeight());
312 externalTextureInfo.SetIsMipMapped(false);
313 externalTextureInfo.SetTarget(GL_TEXTURE_2D);
314 externalTextureInfo.SetID(texId_);
315 externalTextureInfo.SetFormat(GL_RGBA8_OES);
316
317 Drawing::BitmapFormat bitmapFormat = {
318 Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
319 if (!canvas.GetGPUContext()) {
320 RS_LOGE("GetDrawingImageFromSurfaceBuffer gpu context is nullptr");
321 return false;
322 }
323
324 image_ = std::make_shared<Drawing::Image>();
325 #ifndef ROSEN_EMULATOR
326 auto surfaceOrigin = Drawing::TextureOrigin::TOP_LEFT;
327 #else
328 auto surfaceOrigin = Drawing::TextureOrigin::BOTTOM_LEFT;
329 #endif
330 if (!image_->BuildFromTexture(*(canvas.GetGPUContext()), externalTextureInfo,
331 surfaceOrigin, bitmapFormat,
332 std::make_shared<Drawing::ColorSpace>(Drawing::ColorSpace::ColorSpaceType::SRGB))) {
333 RS_LOGE("BuildFromTexture failed");
334 return false;
335 }
336 return true;
337 }
338 #endif
339
340 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
MakeFromTextureForVK(Drawing::Canvas & canvas,SurfaceBuffer * surfaceBuffer,const std::shared_ptr<Drawing::ColorSpace> & colorSpace)341 bool RSExtendImageObject::MakeFromTextureForVK(Drawing::Canvas& canvas, SurfaceBuffer *surfaceBuffer,
342 const std::shared_ptr<Drawing::ColorSpace>& colorSpace)
343 {
344 if (!RSSystemProperties::IsUseVukan()) {
345 return false;
346 }
347 if (surfaceBuffer == nullptr || surfaceBuffer->GetBufferHandle() == nullptr) {
348 RS_LOGE("MakeFromTextureForVK surfaceBuffer is nullptr or buffer handle is nullptr");
349 return false;
350 }
351 if (nativeWindowBuffer_ == nullptr) {
352 sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
353 nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&sfBuffer);
354 if (!nativeWindowBuffer_) {
355 RS_LOGE("MakeFromTextureForVK create native window buffer fail");
356 return false;
357 }
358 }
359 if (!backendTexture_.IsValid()) {
360 backendTexture_ = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer_,
361 surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), false);
362 if (backendTexture_.IsValid()) {
363 auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
364 if (!vkTextureInfo) {
365 return false;
366 }
367 cleanUpHelper_ = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
368 vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
369 } else {
370 return false;
371 }
372 tid_ = gettid();
373 }
374
375 auto context = canvas.GetGPUContext();
376 if (!context) {
377 RS_LOGE("MakeFromTextureForVK gpu context is nullptr");
378 return false;
379 }
380 image_ = std::make_shared<Drawing::Image>();
381 auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
382 if (!vkTextureInfo || !cleanUpHelper_) {
383 return false;
384 }
385 Drawing::ColorType colorType = GetColorTypeFromVKFormat(vkTextureInfo->format);
386 Drawing::BitmapFormat bitmapFormat = { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
387 if (!image_->BuildFromTexture(*context, backendTexture_.GetTextureInfo(),
388 Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, colorSpace,
389 NativeBufferUtils::DeleteVkImage,
390 cleanUpHelper_->Ref())) {
391 RS_LOGE("MakeFromTextureForVK build image failed");
392 return false;
393 }
394 return true;
395 }
396 #endif
397
~RSExtendImageObject()398 RSExtendImageObject::~RSExtendImageObject()
399 {
400 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_GL)
401 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
402 RSTaskDispatcher::GetInstance().PostTask(tid_, [texId = texId_,
403 nativeWindowBuffer = nativeWindowBuffer_,
404 eglImage = eglImage_]() {
405 if (texId != 0U) {
406 glBindTexture(GL_TEXTURE_2D, 0);
407 glDeleteTextures(1, &texId);
408 }
409 if (nativeWindowBuffer != nullptr) {
410 DestroyNativeWindowBuffer(nativeWindowBuffer);
411 }
412 if (eglImage != EGL_NO_IMAGE_KHR) {
413 auto disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
414 eglDestroyImageKHR(disp, eglImage);
415 }
416 });
417 }
418 #endif
419 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
420 if (RSSystemProperties::IsUseVukan()) {
421 RSTaskDispatcher::GetInstance().PostTask(tid_, [nativeWindowBuffer = nativeWindowBuffer_,
422 cleanupHelper = cleanUpHelper_]() {
423 if (nativeWindowBuffer != nullptr) {
424 DestroyNativeWindowBuffer(nativeWindowBuffer);
425 }
426 if (cleanupHelper != nullptr) {
427 NativeBufferUtils::DeleteVkImage(cleanupHelper);
428 }
429 });
430 }
431 #endif
432 }
433
RSExtendImageBaseObj(const std::shared_ptr<Media::PixelMap> & pixelMap,const Drawing::Rect & src,const Drawing::Rect & dst)434 RSExtendImageBaseObj::RSExtendImageBaseObj(const std::shared_ptr<Media::PixelMap>& pixelMap, const Drawing::Rect& src,
435 const Drawing::Rect& dst)
436 {
437 if (pixelMap) {
438 rsImage_ = std::make_shared<RSImageBase>();
439 rsImage_->SetPixelMap(pixelMap);
440 rsImage_->SetSrcRect(RectF(src.GetLeft(), src.GetTop(), src.GetWidth(), src.GetHeight()));
441 rsImage_->SetDstRect(RectF(dst.GetLeft(), dst.GetTop(), dst.GetWidth(), dst.GetHeight()));
442 }
443 }
444
Playback(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & sampling,Drawing::SrcRectConstraint constraint)445 void RSExtendImageBaseObj::Playback(Drawing::Canvas& canvas, const Drawing::Rect& rect,
446 const Drawing::SamplingOptions& sampling, Drawing::SrcRectConstraint constraint)
447 {
448 if (rsImage_) {
449 rsImage_->DrawImage(canvas, sampling, constraint);
450 }
451 }
452
SetNodeId(NodeId id)453 void RSExtendImageBaseObj::SetNodeId(NodeId id)
454 {
455 if (rsImage_) {
456 rsImage_->UpdateNodeIdToPicture(id);
457 }
458 }
459
Purge()460 void RSExtendImageBaseObj::Purge()
461 {
462 if (rsImage_) {
463 rsImage_->Purge();
464 }
465 }
466
Marshalling(Parcel & parcel) const467 bool RSExtendImageBaseObj::Marshalling(Parcel &parcel) const
468 {
469 bool ret = RSMarshallingHelper::Marshalling(parcel, rsImage_);
470 return ret;
471 }
472
Unmarshalling(Parcel & parcel)473 RSExtendImageBaseObj *RSExtendImageBaseObj::Unmarshalling(Parcel &parcel)
474 {
475 auto object = new RSExtendImageBaseObj();
476 bool ret = RSMarshallingHelper::Unmarshalling(parcel, object->rsImage_);
477 if (!ret) {
478 delete object;
479 return nullptr;
480 }
481 return object;
482 }
483
Playback(Drawing::Canvas * canvas,const Drawing::Rect * rect)484 void RSExtendDrawFuncObj::Playback(Drawing::Canvas* canvas, const Drawing::Rect* rect)
485 {
486 if (drawFunc_) {
487 drawFunc_(canvas, rect);
488 }
489 }
490
Marshalling(Parcel & parcel) const491 bool RSExtendDrawFuncObj::Marshalling(Parcel &parcel) const
492 {
493 return false;
494 }
495
Unmarshalling(Parcel & parcel)496 RSExtendDrawFuncObj *RSExtendDrawFuncObj::Unmarshalling(Parcel &parcel)
497 {
498 return nullptr;
499 }
500
501 namespace Drawing {
502 /* DrawImageWithParmOpItem */
503 UNMARSHALLING_REGISTER(DrawImageWithParm, DrawOpItem::IMAGE_WITH_PARM_OPITEM,
504 DrawImageWithParmOpItem::Unmarshalling, sizeof(DrawImageWithParmOpItem::ConstructorHandle));
505
DrawImageWithParmOpItem(const DrawCmdList & cmdList,DrawImageWithParmOpItem::ConstructorHandle * handle)506 DrawImageWithParmOpItem::DrawImageWithParmOpItem(
507 const DrawCmdList& cmdList, DrawImageWithParmOpItem::ConstructorHandle* handle)
508 : DrawWithPaintOpItem(cmdList, handle->paintHandle, IMAGE_WITH_PARM_OPITEM), sampling_(handle->sampling)
509 {
510 objectHandle_ = CmdListHelper::GetImageObjectFromCmdList(cmdList, handle->objectHandle);
511 }
512
DrawImageWithParmOpItem(const std::shared_ptr<Image> & image,const std::shared_ptr<Data> & data,const AdaptiveImageInfo & rsImageInfo,const SamplingOptions & sampling,const Paint & paint)513 DrawImageWithParmOpItem::DrawImageWithParmOpItem(const std::shared_ptr<Image>& image, const std::shared_ptr<Data>& data,
514 const AdaptiveImageInfo& rsImageInfo, const SamplingOptions& sampling, const Paint& paint)
515 : DrawWithPaintOpItem(paint, IMAGE_WITH_PARM_OPITEM), sampling_(sampling)
516 {
517 objectHandle_ = std::make_shared<RSExtendImageObject>(image, data, rsImageInfo);
518 }
519
Unmarshalling(const DrawCmdList & cmdList,void * handle)520 std::shared_ptr<DrawOpItem> DrawImageWithParmOpItem::Unmarshalling(const DrawCmdList& cmdList, void* handle)
521 {
522 return std::make_shared<DrawImageWithParmOpItem>(
523 cmdList, static_cast<DrawImageWithParmOpItem::ConstructorHandle*>(handle));
524 }
525
Marshalling(DrawCmdList & cmdList)526 void DrawImageWithParmOpItem::Marshalling(DrawCmdList& cmdList)
527 {
528 PaintHandle paintHandle;
529 GenerateHandleFromPaint(cmdList, paint_, paintHandle);
530 auto objectHandle = CmdListHelper::AddImageObjectToCmdList(cmdList, objectHandle_);
531 cmdList.AddOp<ConstructorHandle>(objectHandle, sampling_, paintHandle);
532 }
533
Playback(Canvas * canvas,const Rect * rect)534 void DrawImageWithParmOpItem::Playback(Canvas* canvas, const Rect* rect)
535 {
536 if (objectHandle_ == nullptr) {
537 LOGE("DrawImageWithParmOpItem objectHandle is nullptr!");
538 return;
539 }
540 canvas->AttachPaint(paint_);
541 objectHandle_->Playback(*canvas, *rect, sampling_, false);
542 }
543
SetNodeId(NodeId id)544 void DrawImageWithParmOpItem::SetNodeId(NodeId id)
545 {
546 if (objectHandle_ == nullptr) {
547 LOGE("DrawImageWithParmOpItem objectHandle is nullptr!");
548 return;
549 }
550 objectHandle_->SetNodeId(id);
551 }
552
553 /* DrawPixelMapWithParmOpItem */
554 UNMARSHALLING_REGISTER(DrawPixelMapWithParm, DrawOpItem::PIXELMAP_WITH_PARM_OPITEM,
555 DrawPixelMapWithParmOpItem::Unmarshalling, sizeof(DrawPixelMapWithParmOpItem::ConstructorHandle));
556
DrawPixelMapWithParmOpItem(const DrawCmdList & cmdList,DrawPixelMapWithParmOpItem::ConstructorHandle * handle)557 DrawPixelMapWithParmOpItem::DrawPixelMapWithParmOpItem(
558 const DrawCmdList& cmdList, DrawPixelMapWithParmOpItem::ConstructorHandle* handle)
559 : DrawWithPaintOpItem(cmdList, handle->paintHandle, PIXELMAP_WITH_PARM_OPITEM), sampling_(handle->sampling)
560 {
561 objectHandle_ = CmdListHelper::GetImageObjectFromCmdList(cmdList, handle->objectHandle);
562 }
563
DrawPixelMapWithParmOpItem(const std::shared_ptr<Media::PixelMap> & pixelMap,const AdaptiveImageInfo & rsImageInfo,const SamplingOptions & sampling,const Paint & paint)564 DrawPixelMapWithParmOpItem::DrawPixelMapWithParmOpItem(const std::shared_ptr<Media::PixelMap>& pixelMap,
565 const AdaptiveImageInfo& rsImageInfo, const SamplingOptions& sampling, const Paint& paint)
566 : DrawWithPaintOpItem(paint, PIXELMAP_WITH_PARM_OPITEM), sampling_(sampling)
567 {
568 objectHandle_ = std::make_shared<RSExtendImageObject>(pixelMap, rsImageInfo);
569 }
570
Unmarshalling(const DrawCmdList & cmdList,void * handle)571 std::shared_ptr<DrawOpItem> DrawPixelMapWithParmOpItem::Unmarshalling(const DrawCmdList& cmdList, void* handle)
572 {
573 return std::make_shared<DrawPixelMapWithParmOpItem>(
574 cmdList, static_cast<DrawPixelMapWithParmOpItem::ConstructorHandle*>(handle));
575 }
576
Marshalling(DrawCmdList & cmdList)577 void DrawPixelMapWithParmOpItem::Marshalling(DrawCmdList& cmdList)
578 {
579 PaintHandle paintHandle;
580 GenerateHandleFromPaint(cmdList, paint_, paintHandle);
581 auto objectHandle = CmdListHelper::AddImageObjectToCmdList(cmdList, objectHandle_);
582 cmdList.AddOp<ConstructorHandle>(objectHandle, sampling_, paintHandle);
583 }
584
Playback(Canvas * canvas,const Rect * rect)585 void DrawPixelMapWithParmOpItem::Playback(Canvas* canvas, const Rect* rect)
586 {
587 if (objectHandle_ == nullptr) {
588 LOGE("DrawPixelMapWithParmOpItem objectHandle is nullptr!");
589 return;
590 }
591 objectHandle_->SetPaint(paint_);
592 canvas->AttachPaint(paint_);
593 objectHandle_->Playback(*canvas, *rect, sampling_, false);
594 }
595
SetNodeId(NodeId id)596 void DrawPixelMapWithParmOpItem::SetNodeId(NodeId id)
597 {
598 if (objectHandle_ == nullptr) {
599 LOGE("DrawPixelMapWithParmOpItem objectHandle is nullptr!");
600 return;
601 }
602 objectHandle_->SetNodeId(id);
603 }
604
605 /* DrawPixelMapRectOpItem */
606 UNMARSHALLING_REGISTER(DrawPixelMapRect, DrawOpItem::PIXELMAP_RECT_OPITEM,
607 DrawPixelMapRectOpItem::Unmarshalling, sizeof(DrawPixelMapRectOpItem::ConstructorHandle));
608
DrawPixelMapRectOpItem(const DrawCmdList & cmdList,DrawPixelMapRectOpItem::ConstructorHandle * handle)609 DrawPixelMapRectOpItem::DrawPixelMapRectOpItem(
610 const DrawCmdList& cmdList, DrawPixelMapRectOpItem::ConstructorHandle* handle)
611 : DrawWithPaintOpItem(cmdList, handle->paintHandle, PIXELMAP_RECT_OPITEM), sampling_(handle->sampling),
612 constraint_(handle->constraint)
613 {
614 objectHandle_ = CmdListHelper::GetImageBaseObjFromCmdList(cmdList, handle->objectHandle);
615 }
616
DrawPixelMapRectOpItem(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & src,const Rect & dst,const SamplingOptions & sampling,SrcRectConstraint constraint,const Paint & paint)617 DrawPixelMapRectOpItem::DrawPixelMapRectOpItem(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& src,
618 const Rect& dst, const SamplingOptions& sampling, SrcRectConstraint constraint, const Paint& paint)
619 : DrawWithPaintOpItem(paint, PIXELMAP_RECT_OPITEM), sampling_(sampling), constraint_(constraint)
620 {
621 objectHandle_ = std::make_shared<RSExtendImageBaseObj>(pixelMap, src, dst);
622 }
623
Unmarshalling(const DrawCmdList & cmdList,void * handle)624 std::shared_ptr<DrawOpItem> DrawPixelMapRectOpItem::Unmarshalling(const DrawCmdList& cmdList, void* handle)
625 {
626 return std::make_shared<DrawPixelMapRectOpItem>(
627 cmdList, static_cast<DrawPixelMapRectOpItem::ConstructorHandle*>(handle));
628 }
629
Marshalling(DrawCmdList & cmdList)630 void DrawPixelMapRectOpItem::Marshalling(DrawCmdList& cmdList)
631 {
632 PaintHandle paintHandle;
633 GenerateHandleFromPaint(cmdList, paint_, paintHandle);
634 auto objectHandle = CmdListHelper::AddImageBaseObjToCmdList(cmdList, objectHandle_);
635 cmdList.AddOp<ConstructorHandle>(objectHandle, sampling_, constraint_, paintHandle);
636 }
637
Playback(Canvas * canvas,const Rect * rect)638 void DrawPixelMapRectOpItem::Playback(Canvas* canvas, const Rect* rect)
639 {
640 if (objectHandle_ == nullptr) {
641 LOGE("DrawPixelMapRectOpItem objectHandle is nullptr!");
642 return;
643 }
644 canvas->AttachPaint(paint_);
645 objectHandle_->Playback(*canvas, *rect, sampling_, constraint_);
646 }
647
SetNodeId(NodeId id)648 void DrawPixelMapRectOpItem::SetNodeId(NodeId id)
649 {
650 if (objectHandle_ == nullptr) {
651 LOGE("DrawPixelMapRectOpItem objectHandle is nullptr!");
652 return;
653 }
654 objectHandle_->SetNodeId(id);
655 }
656
657 /* DrawFuncOpItem */
658 UNMARSHALLING_REGISTER(DrawFunc, DrawOpItem::DRAW_FUNC_OPITEM,
659 DrawFuncOpItem::Unmarshalling, sizeof(DrawFuncOpItem::ConstructorHandle));
660
DrawFuncOpItem(const DrawCmdList & cmdList,DrawFuncOpItem::ConstructorHandle * handle)661 DrawFuncOpItem::DrawFuncOpItem(const DrawCmdList& cmdList, DrawFuncOpItem::ConstructorHandle* handle)
662 : DrawOpItem(DRAW_FUNC_OPITEM)
663 {
664 objectHandle_ = CmdListHelper::GetDrawFuncObjFromCmdList(cmdList, handle->funcObjectId);
665 }
666
DrawFuncOpItem(RecordingCanvas::DrawFunc && drawFunc)667 DrawFuncOpItem::DrawFuncOpItem(RecordingCanvas::DrawFunc&& drawFunc) : DrawOpItem(DRAW_FUNC_OPITEM)
668 {
669 objectHandle_ = std::make_shared<RSExtendDrawFuncObj>(std::move(drawFunc));
670 }
671
Unmarshalling(const DrawCmdList & cmdList,void * handle)672 std::shared_ptr<DrawOpItem> DrawFuncOpItem::Unmarshalling(const DrawCmdList& cmdList, void* handle)
673 {
674 return std::make_shared<DrawFuncOpItem>(cmdList, static_cast<DrawFuncOpItem::ConstructorHandle*>(handle));
675 }
676
Marshalling(DrawCmdList & cmdList)677 void DrawFuncOpItem::Marshalling(DrawCmdList& cmdList)
678 {
679 auto objectHandle = CmdListHelper::AddDrawFuncObjToCmdList(cmdList, objectHandle_);
680 cmdList.AddOp<ConstructorHandle>(objectHandle);
681 }
682
Playback(Canvas * canvas,const Rect * rect)683 void DrawFuncOpItem::Playback(Canvas* canvas, const Rect* rect)
684 {
685 if (objectHandle_) {
686 objectHandle_->Playback(canvas, rect);
687 }
688 }
689
690 #ifdef ROSEN_OHOS
691 /* DrawSurfaceBufferOpItem */
692 UNMARSHALLING_REGISTER(DrawSurfaceBuffer, DrawOpItem::SURFACEBUFFER_OPITEM,
693 DrawSurfaceBufferOpItem::Unmarshalling, sizeof(DrawSurfaceBufferOpItem::ConstructorHandle));
694
DrawSurfaceBufferOpItem(const DrawCmdList & cmdList,DrawSurfaceBufferOpItem::ConstructorHandle * handle)695 DrawSurfaceBufferOpItem::DrawSurfaceBufferOpItem(
696 const DrawCmdList& cmdList, DrawSurfaceBufferOpItem::ConstructorHandle* handle)
697 : DrawWithPaintOpItem(cmdList, handle->paintHandle, SURFACEBUFFER_OPITEM),
698 surfaceBufferInfo_(nullptr, handle->surfaceBufferInfo.dstRect_.GetLeft(),
699 handle->surfaceBufferInfo.dstRect_.GetTop(), handle->surfaceBufferInfo.dstRect_.GetWidth(),
700 handle->surfaceBufferInfo.dstRect_.GetHeight(), handle->surfaceBufferInfo.pid_,
701 handle->surfaceBufferInfo.uid_, nullptr, handle->surfaceBufferInfo.srcRect_)
702 {
703 auto surfaceBufferEntry = CmdListHelper::GetSurfaceBufferEntryFromCmdList(cmdList, handle->surfaceBufferId);
704 if (surfaceBufferEntry) {
705 surfaceBufferInfo_.surfaceBuffer_ = surfaceBufferEntry->surfaceBuffer_;
706 surfaceBufferInfo_.acquireFence_ = surfaceBufferEntry->acquireFence_;
707 }
708 }
709
~DrawSurfaceBufferOpItem()710 DrawSurfaceBufferOpItem::~DrawSurfaceBufferOpItem()
711 {
712 OnDestruct();
713 Clear();
714 }
715
Unmarshalling(const DrawCmdList & cmdList,void * handle)716 std::shared_ptr<DrawOpItem> DrawSurfaceBufferOpItem::Unmarshalling(const DrawCmdList& cmdList, void* handle)
717 {
718 return std::make_shared<DrawSurfaceBufferOpItem>(cmdList,
719 static_cast<DrawSurfaceBufferOpItem::ConstructorHandle*>(handle));
720 }
721
Marshalling(DrawCmdList & cmdList)722 void DrawSurfaceBufferOpItem::Marshalling(DrawCmdList& cmdList)
723 {
724 PaintHandle paintHandle;
725 GenerateHandleFromPaint(cmdList, paint_, paintHandle);
726 std::shared_ptr<SurfaceBufferEntry> surfaceBufferEntry =
727 std::make_shared<SurfaceBufferEntry>(surfaceBufferInfo_.surfaceBuffer_, surfaceBufferInfo_.acquireFence_);
728 cmdList.AddOp<ConstructorHandle>(CmdListHelper::AddSurfaceBufferEntryToCmdList(cmdList, surfaceBufferEntry),
729 surfaceBufferInfo_.dstRect_.GetLeft(), surfaceBufferInfo_.dstRect_.GetTop(),
730 surfaceBufferInfo_.dstRect_.GetWidth(), surfaceBufferInfo_.dstRect_.GetHeight(), surfaceBufferInfo_.pid_,
731 surfaceBufferInfo_.uid_, surfaceBufferInfo_.srcRect_, paintHandle);
732 }
733
734 namespace {
735 std::function<void(const DrawSurfaceBufferFinishCbData&)> surfaceBufferFinishCb;
736 std::function<void(const DrawSurfaceBufferAfterAcquireCbData&)> surfaceBufferAfterAcquireCb;
737 std::function<NodeId()> getRootNodeIdForRT;
738 bool contextIsUniRender = true;
739 }
740
OnDestruct()741 void DrawSurfaceBufferOpItem::OnDestruct()
742 {
743 ReleaseBuffer();
744 }
745
SetIsUniRender(bool isUniRender)746 void DrawSurfaceBufferOpItem::SetIsUniRender(bool isUniRender)
747 {
748 contextIsUniRender = isUniRender;
749 }
750
OnAfterDraw()751 void DrawSurfaceBufferOpItem::OnAfterDraw()
752 {
753 isRendered_ = true;
754 if (contextIsUniRender) {
755 return;
756 }
757 rootNodeId_ = getRootNodeIdForRT ? std::invoke(getRootNodeIdForRT) : INVALID_NODEID;
758 #ifdef RS_ENABLE_GL
759 if (SystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
760 auto disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
761 auto sync = eglCreateSyncKHR(disp, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
762 if (sync == EGL_NO_SYNC_KHR) {
763 RS_LOGE("DrawSurfaceBufferOpItem::OnAfterDraw Error on eglCreateSyncKHR %{public}d",
764 static_cast<int>(eglGetError()));
765 return;
766 }
767 auto fd = eglDupNativeFenceFDANDROID(disp, sync);
768 eglDestroySyncKHR(disp, sync);
769 if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
770 RS_LOGE("DrawSurfaceBufferOpItem::OnAfterDraw: Error on eglDupNativeFenceFD");
771 return;
772 }
773 releaseFence_ = new (std::nothrow) SyncFence(fd);
774 if (!releaseFence_) {
775 releaseFence_ = SyncFence::INVALID_FENCE;
776 }
777 }
778 #endif
779 }
780
ReleaseBuffer()781 void DrawSurfaceBufferOpItem::ReleaseBuffer()
782 {
783 if (surfaceBufferFinishCb && surfaceBufferInfo_.surfaceBuffer_) {
784 RS_TRACE_NAME_FMT("DrawSurfaceBufferOpItem::ReleaseBuffer %s Release, isNeedTriggerCbDirectly = %d",
785 std::to_string(surfaceBufferInfo_.surfaceBuffer_->GetSeqNum()).c_str(),
786 releaseFence_ && releaseFence_->IsValid());
787 std::invoke(surfaceBufferFinishCb, DrawSurfaceBufferFinishCbData {
788 .uid = surfaceBufferInfo_.uid_,
789 .pid = surfaceBufferInfo_.pid_,
790 .surfaceBufferId = surfaceBufferInfo_.surfaceBuffer_->GetSeqNum(),
791 .rootNodeId = rootNodeId_,
792 .releaseFence = releaseFence_,
793 .isRendered = isRendered_,
794 .isNeedTriggerCbDirectly = releaseFence_ && releaseFence_->IsValid(),
795 });
796 }
797 }
798
OnAfterAcquireBuffer()799 void DrawSurfaceBufferOpItem::OnAfterAcquireBuffer()
800 {
801 if (surfaceBufferAfterAcquireCb && surfaceBufferInfo_.surfaceBuffer_) {
802 std::invoke(surfaceBufferAfterAcquireCb, DrawSurfaceBufferAfterAcquireCbData {
803 .uid = surfaceBufferInfo_.uid_,
804 .pid = surfaceBufferInfo_.pid_,
805 });
806 }
807 }
808
RegisterSurfaceBufferCallback(DrawSurfaceBufferOpItemCb callbacks)809 void DrawSurfaceBufferOpItem::RegisterSurfaceBufferCallback(
810 DrawSurfaceBufferOpItemCb callbacks)
811 {
812 if (std::exchange(surfaceBufferFinishCb, callbacks.OnFinish)) {
813 RS_LOGE("DrawSurfaceBufferOpItem::RegisterSurfaceBufferCallback"
814 " registered OnFinish twice incorrectly.");
815 }
816 if (std::exchange(surfaceBufferAfterAcquireCb, callbacks.OnAfterAcquireBuffer)) {
817 RS_LOGE("DrawSurfaceBufferOpItem::RegisterSurfaceBufferCallback"
818 " registered OnAfterAcquireBuffer twice incorrectly.");
819 }
820 }
821
RegisterGetRootNodeIdFuncForRT(std::function<NodeId ()> func)822 void DrawSurfaceBufferOpItem::RegisterGetRootNodeIdFuncForRT(std::function<NodeId()> func)
823 {
824 if (std::exchange(getRootNodeIdForRT, func)) {
825 RS_LOGE("DrawSurfaceBufferOpItem::RegisterGetRootNodeIdFuncForRT"
826 " registered OnFinish twice incorrectly.");
827 }
828 }
829
Playback(Canvas * canvas,const Rect * rect)830 void DrawSurfaceBufferOpItem::Playback(Canvas* canvas, const Rect* rect)
831 {
832 if (auto recordingCanvas = static_cast<ExtendRecordingCanvas*>(canvas->GetRecordingCanvas())) {
833 recordingCanvas->DrawSurfaceBuffer(surfaceBufferInfo_);
834 return;
835 }
836 Clear();
837 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
838 if (surfaceBufferInfo_.surfaceBuffer_ == nullptr) {
839 LOGE("SurfaceBufferOpItem::Draw surfaceBuffer_ is nullptr");
840 return;
841 }
842 nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&(surfaceBufferInfo_.surfaceBuffer_));
843 if (!nativeWindowBuffer_) {
844 LOGE("create nativeWindowBuffer_ fail.");
845 return;
846 }
847 #endif
848 canvas->AttachPaint(paint_);
849 Draw(canvas);
850 }
851
Clear()852 void DrawSurfaceBufferOpItem::Clear()
853 {
854 #ifdef RS_ENABLE_GL
855 if (SystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
856 if (texId_ != 0U) {
857 glDeleteTextures(1, &texId_);
858 }
859 if (eglImage_ != EGL_NO_IMAGE_KHR) {
860 auto disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
861 eglDestroyImageKHR(disp, eglImage_);
862 }
863 }
864 #endif
865 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
866 if (nativeWindowBuffer_ != nullptr) {
867 DestroyNativeWindowBuffer(nativeWindowBuffer_);
868 nativeWindowBuffer_ = nullptr;
869 }
870 #endif
871 }
872
Draw(Canvas * canvas)873 void DrawSurfaceBufferOpItem::Draw(Canvas* canvas)
874 {
875 #ifdef RS_ENABLE_VK
876 if (RSSystemProperties::IsUseVulkan()) {
877 DrawWithVulkan(canvas);
878 }
879 #endif
880 #ifdef RS_ENABLE_GL
881 if (SystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
882 DrawWithGles(canvas);
883 }
884 #endif
885 OnAfterDraw();
886 }
887
CreateBitmapFormat(int32_t bufferFormat)888 Drawing::BitmapFormat DrawSurfaceBufferOpItem::CreateBitmapFormat(int32_t bufferFormat)
889 {
890 switch (bufferFormat) {
891 case OH_NativeBuffer_Format::NATIVEBUFFER_PIXEL_FMT_RGBA_8888 : {
892 return {
893 .colorType = Drawing::ColorType::COLORTYPE_RGBA_8888,
894 .alphaType = Drawing::AlphaType::ALPHATYPE_PREMUL,
895 };
896 }
897 case OH_NativeBuffer_Format::NATIVEBUFFER_PIXEL_FMT_RGBX_8888 : {
898 return {
899 .colorType = Drawing::ColorType::COLORTYPE_RGB_888X,
900 .alphaType = Drawing::AlphaType::ALPHATYPE_OPAQUE,
901 };
902 }
903 case OH_NativeBuffer_Format::NATIVEBUFFER_PIXEL_FMT_BGRA_8888 : {
904 return {
905 .colorType = Drawing::ColorType::COLORTYPE_BGRA_8888,
906 .alphaType = Drawing::AlphaType::ALPHATYPE_PREMUL,
907 };
908 }
909 case OH_NativeBuffer_Format::NATIVEBUFFER_PIXEL_FMT_RGB_565 : {
910 return {
911 .colorType = Drawing::ColorType::COLORTYPE_RGB_565,
912 .alphaType = Drawing::AlphaType::ALPHATYPE_OPAQUE,
913 };
914 }
915 case OH_NativeBuffer_Format::NATIVEBUFFER_PIXEL_FMT_RGBA_1010102 : {
916 return {
917 .colorType = Drawing::ColorType::COLORTYPE_RGBA_1010102,
918 .alphaType = Drawing::AlphaType::ALPHATYPE_PREMUL,
919 };
920 }
921 default : {
922 return {
923 .colorType = Drawing::ColorType::COLORTYPE_RGBA_8888,
924 .alphaType = Drawing::AlphaType::ALPHATYPE_PREMUL,
925 };
926 }
927 }
928 }
929
930 #ifdef RS_ENABLE_GL
GetGLTextureFormatByBitmapFormat(Drawing::ColorType colorType)931 GLenum DrawSurfaceBufferOpItem::GetGLTextureFormatByBitmapFormat(Drawing::ColorType colorType)
932 {
933 switch (colorType) {
934 case Drawing::ColorType::COLORTYPE_ALPHA_8 : {
935 return GL_ALPHA8_OES;
936 }
937 case Drawing::ColorType::COLORTYPE_RGB_888X : {
938 return GL_RGBA8_OES;
939 }
940 case Drawing::ColorType::COLORTYPE_RGB_565 : {
941 return GL_RGB565_OES;
942 }
943 case Drawing::ColorType::COLORTYPE_RGBA_1010102 : {
944 return GL_RGB10_A2_EXT;
945 }
946 case Drawing::ColorType::COLORTYPE_BGRA_8888 : {
947 return GL_BGRA8_EXT;
948 }
949 case Drawing::ColorType::COLORTYPE_RGBA_8888 : {
950 return GL_RGBA8_OES;
951 }
952 case Drawing::ColorType::COLORTYPE_RGBA_F16 : {
953 return GL_RGBA16F_EXT;
954 }
955 case Drawing::ColorType::COLORTYPE_GRAY_8 :
956 [[fallthrough]];
957 case Drawing::ColorType::COLORTYPE_ARGB_4444 :
958 [[fallthrough]];
959 case Drawing::ColorType::COLORTYPE_N32 :
960 [[fallthrough]];
961 default : {
962 return GL_RGBA8_OES;
963 }
964 }
965 }
966 #endif
967
DrawWithVulkan(Canvas * canvas)968 void DrawSurfaceBufferOpItem::DrawWithVulkan(Canvas* canvas)
969 {
970 #ifdef RS_ENABLE_VK
971 if (surfaceBufferInfo_.acquireFence_) {
972 RS_TRACE_NAME_FMT("DrawSurfaceBufferOpItem::DrawWithVulkan waitfence");
973 int res = surfaceBufferInfo_.acquireFence_->Wait(FENCE_WAIT_TIME);
974 if (res < 0) {
975 LOGW("DrawSurfaceBufferOpItem::DrawWithVulkan waitfence timeout");
976 } else {
977 OnAfterAcquireBuffer();
978 }
979 }
980 auto backendTexture = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer_,
981 surfaceBufferInfo_.surfaceBuffer_->GetWidth(), surfaceBufferInfo_.surfaceBuffer_->GetHeight());
982 if (!backendTexture.IsValid()) {
983 LOGE("DrawSurfaceBufferOpItem::Draw backendTexture is not valid");
984 return;
985 }
986 if (!canvas->GetGPUContext()) {
987 LOGE("DrawSurfaceBufferOpItem::Draw gpu context is nullptr");
988 return;
989 }
990 Drawing::BitmapFormat bitmapFormat = CreateBitmapFormat(surfaceBufferInfo_.surfaceBuffer_->GetFormat());
991 auto image = std::make_shared<Drawing::Image>();
992 auto vkTextureInfo = backendTexture.GetTextureInfo().GetVKTextureInfo();
993 if (!vkTextureInfo || !image->BuildFromTexture(*canvas->GetGPUContext(), backendTexture.GetTextureInfo(),
994 Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr, NativeBufferUtils::DeleteVkImage,
995 new NativeBufferUtils::VulkanCleanupHelper(
996 RsVulkanContext::GetSingleton(), vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory))) {
997 LOGE("DrawSurfaceBufferOpItem::Draw image BuildFromTexture failed");
998 return;
999 }
1000 canvas->DrawImageRect(*image, surfaceBufferInfo_.srcRect_, surfaceBufferInfo_.dstRect_, Drawing::SamplingOptions());
1001 #endif
1002 }
1003
DrawWithGles(Canvas * canvas)1004 void DrawSurfaceBufferOpItem::DrawWithGles(Canvas* canvas)
1005 {
1006 #ifdef RS_ENABLE_GL
1007 if (surfaceBufferInfo_.acquireFence_) {
1008 RS_TRACE_NAME_FMT("DrawSurfaceBufferOpItem::DrawWithGles waitfence");
1009 int res = surfaceBufferInfo_.acquireFence_->Wait(FENCE_WAIT_TIME);
1010 if (res < 0) {
1011 LOGW("DrawSurfaceBufferOpItem::DrawWithGles waitfence timeout");
1012 } else {
1013 OnAfterAcquireBuffer();
1014 }
1015 }
1016 if (!CreateEglTextureId()) {
1017 return;
1018 }
1019 Drawing::BitmapFormat bitmapFormat = CreateBitmapFormat(surfaceBufferInfo_.surfaceBuffer_->GetFormat());
1020 Drawing::TextureInfo externalTextureInfo;
1021 externalTextureInfo.SetWidth(surfaceBufferInfo_.dstRect_.GetWidth());
1022 externalTextureInfo.SetHeight(surfaceBufferInfo_.dstRect_.GetHeight());
1023 externalTextureInfo.SetIsMipMapped(false);
1024 externalTextureInfo.SetTarget(GL_TEXTURE_EXTERNAL_OES);
1025 externalTextureInfo.SetID(texId_);
1026 externalTextureInfo.SetFormat(GetGLTextureFormatByBitmapFormat(bitmapFormat.colorType));
1027 if (!canvas->GetGPUContext()) {
1028 LOGE("DrawSurfaceBufferOpItem::Draw: gpu context is nullptr");
1029 return;
1030 }
1031 #ifndef ROSEN_EMULATOR
1032 auto surfaceOrigin = Drawing::TextureOrigin::TOP_LEFT;
1033 #else
1034 auto surfaceOrigin = Drawing::TextureOrigin::BOTTOM_LEFT;
1035 #endif
1036 auto newImage = std::make_shared<Drawing::Image>();
1037 if (!newImage->BuildFromTexture(*canvas->GetGPUContext(), externalTextureInfo,
1038 surfaceOrigin, bitmapFormat, nullptr)) {
1039 LOGE("DrawSurfaceBufferOpItem::Draw: image BuildFromTexture failed");
1040 return;
1041 }
1042 canvas->DrawImage(*newImage, surfaceBufferInfo_.dstRect_.GetLeft(), surfaceBufferInfo_.dstRect_.GetTop(),
1043 Drawing::SamplingOptions());
1044 #endif // RS_ENABLE_GL
1045 }
1046
CreateEglTextureId()1047 bool DrawSurfaceBufferOpItem::CreateEglTextureId()
1048 {
1049 EGLint attrs[] = { EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE };
1050
1051 auto disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1052 eglImage_ = eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, nativeWindowBuffer_, attrs);
1053 if (eglImage_ == EGL_NO_IMAGE_KHR) {
1054 DestroyNativeWindowBuffer(nativeWindowBuffer_);
1055 nativeWindowBuffer_ = nullptr;
1056 LOGE("%{public}s create egl image fail %{public}d", __func__, eglGetError());
1057 return false;
1058 }
1059
1060 // save
1061 GLuint originTexture;
1062 glGetIntegerv(GL_TEXTURE_BINDING_2D, reinterpret_cast<GLint *>(&originTexture));
1063 GLint minFilter;
1064 glGetTexParameteriv(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, &minFilter);
1065 GLint magFilter;
1066 glGetTexParameteriv(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, &magFilter);
1067 GLint wrapS;
1068 glGetTexParameteriv(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, &wrapS);
1069 GLint wrapT;
1070 glGetTexParameteriv(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, &wrapT);
1071
1072 // Create texture object
1073 texId_ = 0;
1074 glGenTextures(1, &texId_);
1075 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId_);
1076 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1077 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1078 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1079 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1080 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, static_cast<GLeglImageOES>(eglImage_));
1081
1082 // restore
1083 glBindTexture(GL_TEXTURE_EXTERNAL_OES, originTexture);
1084 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
1085 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, magFilter);
1086 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapS);
1087 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapT);
1088
1089 return true;
1090 }
1091 #endif
1092 }
1093 } // namespace Rosen
1094 } // namespace OHOS
1095