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