• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "memory/rs_tag_tracker.h"
17 #include "native_buffer_utils.h"
18 #include "platform/common/rs_log.h"
19 #include "render_context/render_context.h"
20 #include "pipeline/sk_resource_manager.h"
21 
22 #ifdef RS_ENABLE_VK
23 #ifdef USE_M133_SKIA
24 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
25 #else
26 #include "include/gpu/GrBackendSurface.h"
27 #endif
28 #include "platform/ohos/backend/rs_vulkan_context.h"
29 #endif
30 
31 namespace OHOS::Rosen {
32 namespace NativeBufferUtils {
33 namespace {
34 constexpr uint32_t FORMAT_R10G10B10A8 = 0x7FFFFFFF - 255;
35 }
DeleteVkImage(void * context)36 void DeleteVkImage(void* context)
37 {
38     VulkanCleanupHelper* cleanupHelper = static_cast<VulkanCleanupHelper*>(context);
39     if (cleanupHelper != nullptr) {
40         cleanupHelper->UnRef();
41     }
42 }
43 
GetNativeBufferFormatProperties(RsVulkanContext & vkContext,VkDevice device,OH_NativeBuffer * nativeBuffer,VkNativeBufferFormatPropertiesOHOS * nbFormatProps,VkNativeBufferPropertiesOHOS * nbProps)44 bool GetNativeBufferFormatProperties(RsVulkanContext& vkContext, VkDevice device, OH_NativeBuffer* nativeBuffer,
45                                      VkNativeBufferFormatPropertiesOHOS* nbFormatProps,
46                                      VkNativeBufferPropertiesOHOS* nbProps)
47 {
48     if (!nbFormatProps || !nbProps) {
49         RS_LOGE("GetNativeBufferFormatProperties failed!");
50         return false;
51     }
52     nbFormatProps->sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_FORMAT_PROPERTIES_OHOS;
53     nbFormatProps->pNext = nullptr;
54 
55     nbProps->sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_PROPERTIES_OHOS;
56     nbProps->pNext = nbFormatProps;
57 
58     VkResult err = vkContext.GetRsVulkanInterface().vkGetNativeBufferPropertiesOHOS(device, nativeBuffer, nbProps);
59     if (VK_SUCCESS != err) {
60         ROSEN_LOGE("NativeBufferUtils: vkGetNativeBufferPropertiesOHOS Failed ! %{public}d", err);
61         return false;
62     }
63     return true;
64 }
65 
CreateVkImage(RsVulkanContext & vkContext,VkImage * image,const VkNativeBufferFormatPropertiesOHOS & nbFormatProps,const VkExtent3D & imageSize,VkImageUsageFlags usageFlags=0,bool isProtected=false)66 bool CreateVkImage(RsVulkanContext& vkContext, VkImage* image,
67     const VkNativeBufferFormatPropertiesOHOS& nbFormatProps, const VkExtent3D& imageSize,
68     VkImageUsageFlags usageFlags = 0, bool isProtected = false)
69 {
70     VkExternalFormatOHOS externalFormat;
71     externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS;
72     externalFormat.pNext = nullptr;
73     externalFormat.externalFormat = 0;
74 
75     if (nbFormatProps.format == VK_FORMAT_UNDEFINED) {
76         externalFormat.externalFormat = nbFormatProps.externalFormat;
77     }
78 
79     const VkExternalMemoryImageCreateInfo externalMemoryImageInfo {
80         VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
81         &externalFormat, // pNext
82         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OHOS, // handleTypes
83     };
84 
85     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
86 
87     VkImageCreateFlags flags = isProtected ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
88 
89     const VkImageCreateInfo imageCreateInfo = {
90         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
91         &externalMemoryImageInfo,
92         flags,
93         VK_IMAGE_TYPE_2D,
94         nbFormatProps.format,
95         imageSize,
96         1,
97         1,
98         VK_SAMPLE_COUNT_1_BIT,
99         tiling,
100         usageFlags,
101         VK_SHARING_MODE_EXCLUSIVE,
102         0,
103         0,
104         VK_IMAGE_LAYOUT_UNDEFINED,
105     };
106 
107     if (imageSize.width != 0 && imageSize.height != 0 &&
108         imageSize.depth > VKIMAGE_LIMIT_SIZE / imageSize.width / imageSize.height) {
109         ROSEN_LOGE("NativeBufferUtils: vkCreateImag failed, image is too large, width:%{public}u, height::%{public}u,"
110                    "depth::%{public}u",
111             imageSize.width, imageSize.height, imageSize.depth);
112         return false;
113     }
114 
115     VkResult err = vkContext.GetRsVulkanInterface().vkCreateImage(vkContext.GetDevice(),
116         &imageCreateInfo, nullptr, image);
117     if (err != VK_SUCCESS) {
118         ROSEN_LOGE("NativeBufferUtils: vkCreateImage failed");
119         return false;
120     }
121     return true;
122 }
123 
AllocateDeviceMemory(RsVulkanContext & vkContext,VkDeviceMemory * memory,VkImage & image,OH_NativeBuffer * nativeBuffer,VkNativeBufferPropertiesOHOS & nbProps,bool isProtected)124 bool AllocateDeviceMemory(RsVulkanContext& vkContext, VkDeviceMemory* memory, VkImage& image,
125     OH_NativeBuffer* nativeBuffer, VkNativeBufferPropertiesOHOS& nbProps, bool isProtected)
126 {
127     VkPhysicalDeviceMemoryProperties2 physicalDeviceMemProps;
128     physicalDeviceMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
129     physicalDeviceMemProps.pNext = nullptr;
130     auto& vkInterface = vkContext.GetRsVulkanInterface();
131 
132     uint32_t foundTypeIndex = 0;
133     VkDevice device = vkInterface.GetDevice();
134     VkPhysicalDevice physicalDevice = vkInterface.GetPhysicalDevice();
135     vkInterface.vkGetPhysicalDeviceMemoryProperties2(physicalDevice, &physicalDeviceMemProps);
136     uint32_t memTypeCnt = physicalDeviceMemProps.memoryProperties.memoryTypeCount;
137     bool found = false;
138     for (uint32_t i = 0; i < memTypeCnt; ++i) {
139         if (nbProps.memoryTypeBits & (1 << i)) {
140             const VkPhysicalDeviceMemoryProperties& pdmp = physicalDeviceMemProps.memoryProperties;
141             uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
142             if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
143                 foundTypeIndex = i;
144                 found = true;
145                 break;
146             }
147         }
148     }
149     if (!found) {
150         ROSEN_LOGE("NativeBufferUtils: no fit memory type, memoryTypeBits is %{public}u", nbProps.memoryTypeBits);
151         vkInterface.vkDestroyImage(device, image, nullptr);
152         return false;
153     }
154 
155     VkImportNativeBufferInfoOHOS nbImportInfo;
156     nbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_NATIVE_BUFFER_INFO_OHOS;
157     nbImportInfo.pNext = nullptr;
158     nbImportInfo.buffer = nativeBuffer;
159 
160     VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
161     dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
162     dedicatedAllocInfo.pNext = &nbImportInfo;
163     dedicatedAllocInfo.image = image;
164     dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
165 
166     VkMemoryAllocateInfo allocInfo = {
167         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, &dedicatedAllocInfo, nbProps.allocationSize, foundTypeIndex,
168     };
169 
170     VkResult err = vkInterface.vkAllocateMemory(device, &allocInfo, nullptr, memory);
171     if (err != VK_SUCCESS) {
172         vkInterface.vkDestroyImage(device, image, nullptr);
173         ROSEN_LOGE("NativeBufferUtils: vkAllocateMemory Fail");
174         return false;
175     }
176     return true;
177 }
178 
BindImageMemory(VkDevice device,RsVulkanContext & vkContext,VkImage & image,VkDeviceMemory & memory)179 bool BindImageMemory(VkDevice device, RsVulkanContext& vkContext, VkImage& image, VkDeviceMemory& memory)
180 {
181     auto& vkInterface = vkContext.GetRsVulkanInterface();
182     VkBindImageMemoryInfo bindImageInfo;
183     bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
184     bindImageInfo.pNext = nullptr;
185     bindImageInfo.image = image;
186     bindImageInfo.memory = memory;
187     bindImageInfo.memoryOffset = 0;
188 
189     VkResult err = vkInterface.vkBindImageMemory2(device, 1, &bindImageInfo);
190     if (err != VK_SUCCESS) {
191         ROSEN_LOGE("NativeBufferUtils: vkBindImageMemory2 failed");
192         vkInterface.vkDestroyImage(device, image, nullptr);
193         vkInterface.vkFreeMemory(device, memory, nullptr);
194         return false;
195     }
196     return true;
197 }
198 
MakeFromNativeWindowBuffer(std::shared_ptr<Drawing::GPUContext> skContext,NativeWindowBuffer * nativeWindowBuffer,NativeSurfaceInfo & nativeSurface,int width,int height,bool isProtected)199 bool MakeFromNativeWindowBuffer(std::shared_ptr<Drawing::GPUContext> skContext, NativeWindowBuffer* nativeWindowBuffer,
200     NativeSurfaceInfo& nativeSurface, int width, int height, bool isProtected)
201 {
202     OH_NativeBuffer* nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(nativeWindowBuffer);
203     if (nativeBuffer == nullptr) {
204         ROSEN_LOGE("MakeFromNativeWindowBuffer: OH_NativeBufferFromNativeWindowBuffer failed");
205         return false;
206     }
207 
208     auto& vkContext = RsVulkanContext::GetSingleton();
209 
210     VkDevice device = vkContext.GetDevice();
211 
212     VkNativeBufferFormatPropertiesOHOS nbFormatProps;
213     VkNativeBufferPropertiesOHOS nbProps;
214     if (!GetNativeBufferFormatProperties(vkContext, device, nativeBuffer, &nbFormatProps, &nbProps)) {
215         return false;
216     }
217 
218     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
219     if (nbFormatProps.format != VK_FORMAT_UNDEFINED) {
220         usageFlags = usageFlags | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
221             | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
222     }
223 
224     VkImage image;
225     if (!CreateVkImage(vkContext, &image, nbFormatProps, {width, height, 1}, usageFlags, isProtected)) {
226         return false;
227     }
228 
229     VkDeviceMemory memory;
230     if (!AllocateDeviceMemory(vkContext, &memory, image, nativeBuffer, nbProps, isProtected)) {
231         return false;
232     }
233 
234     if (!BindImageMemory(device, vkContext, image, memory)) {
235         return false;
236     }
237 
238     auto colorSpace = RenderContext::ConvertColorGamutToColorSpace(nativeSurface.graphicColorGamut);
239     Drawing::TextureInfo texture_info;
240     texture_info.SetWidth(width);
241     texture_info.SetHeight(height);
242     std::shared_ptr<Drawing::VKTextureInfo> vkTextureInfo = std::make_shared<Drawing::VKTextureInfo>();
243     vkTextureInfo->vkImage = image;
244     vkTextureInfo->vkAlloc.memory = memory;
245     vkTextureInfo->vkAlloc.size = npProps.allocationSize;
246     vkTextureInfo->vkAlloc.source = Drawing::VKMemSource::EXTERNAL;
247     vkTextureInfo->imageTiling = VK_IMAGE_TILING_OPTIMAL;
248     vkTextureInfo->imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
249     vkTextureInfo->format = nbFormatProps.format;
250     vkTextureInfo->imageUsageFlags = usageFlags;
251     vkTextureInfo->sampleCount = 1;
252     vkTextureInfo->levelCount = 1;
253     vkTextureInfo->vkProtected = isProtected;
254     texture_info.SetVKTextureInfo(vkTextureInfo);
255 
256     Drawing::ColorType colorType = Drawing::ColorType::COLORTYPE_RGBA_8888;
257     if (nbFormatProps.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) {
258         colorType = Drawing::ColorType::COLORTYPE_RGBA_1010102;
259     } else if (nbFormatProps.format == static_cast<VkFormat>(FORMAT_R10G10B10A8)) {
260         colorType = Drawing::ColorType::COLORTYPE_RGBA_1010108;
261     }
262 
263     nativeSurface.drawingSurface = Drawing::Surface::MakeFromBackendTexture(
264         skContext.get(),
265         texture_info,
266         Drawing::TextureOrigin::TOP_LEFT,
267         1,
268         colorType,
269         colorSpace,
270         DeleteVkImage,
271         new VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
272             image, memory));
273     if (nativeSurface.drawingSurface) {
274         SKResourceManager::Instance().HoldResource(nativeSurface.drawingSurface);
275     }
276 
277     nativeSurface.image = image;
278     if (nativeSurface.nativeWindowBuffer != nullptr) {
279         NativeObjectUnreference(nativeSurface.nativeWindowBuffer);
280     }
281     NativeObjectReference(nativeWindowBuffer);
282     nativeSurface.nativeWindowBuffer = nativeWindowBuffer;
283 
284     return true;
285 }
286 
287 #ifdef USE_M133_SKIA
GetYcbcrInfo(VkNativeBufferFormatPropertiesOHOS & nbFormatProps)288 skgpu::VulkanYcbcrConversionInfo GetYcbcrInfo(VkNativeBufferFormatPropertiesOHOS& nbFormatProps)
289 {
290     skgpu::VulkanYcbcrConversionInfo ycbcrInfo = {
291 #else
292 GrVkYcbcrConversionInfo GetYcbcrInfo(VkNativeBufferFormatPropertiesOHOS& nbFormatProps)
293 {
294     GrVkYcbcrConversionInfo ycbcrInfo = {
295 #endif
296         .fFormat = nbFormatProps.format,
297         .fExternalFormat = nbFormatProps.externalFormat,
298         .fYcbcrModel = nbFormatProps.suggestedYcbcrModel,
299         .fYcbcrRange = nbFormatProps.suggestedYcbcrRange,
300         .fXChromaOffset = nbFormatProps.suggestedXChromaOffset,
301         .fYChromaOffset = nbFormatProps.suggestedYChromaOffset,
302         .fChromaFilter = VK_FILTER_NEAREST,
303         .fForceExplicitReconstruction = VK_FALSE,
304         .fFormatFeatures = nbFormatProps.formatFeatures
305     };
306 
307     if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT & nbFormatProps.formatFeatures) {
308         ycbcrInfo.fChromaFilter = VK_FILTER_LINEAR;
309     }
310     return ycbcrInfo;
311 }
312 
313 Drawing::BackendTexture MakeBackendTextureFromNativeBuffer(NativeWindowBuffer* nativeWindowBuffer,
314     int width, int height, bool isProtected)
315 {
316     OH_NativeBuffer* nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(nativeWindowBuffer);
317     if (!nativeBuffer) {
318         ROSEN_LOGE("MakeBackendTextureFromNativeBuffer: OH_NativeBufferFromNativeWindowBuffer failed");
319         return {};
320     }
321 
322     auto& vkContext = RsVulkanContext::GetSingleton();
323     VkDevice device = vkContext.GetDevice();
324 
325     VkNativeBufferFormatPropertiesOHOS nbFormatProps;
326     VkNativeBufferPropertiesOHOS nbProps;
327     if (!GetNativeBufferFormatProperties(vkContext, device, nativeBuffer, &nbFormatProps, &nbProps)) {
328         return {};
329     }
330 
331     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
332     if (nbFormatProps.format != VK_FORMAT_UNDEFINED) {
333         usageFlags = usageFlags | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
334     }
335 
336     VkImage image;
337     if (!CreateVkImage(vkContext, &image, nbFormatProps, {width, height, 1}, usageFlags, isProtected)) {
338         return {};
339     }
340 
341     VkDeviceMemory memory;
342     if (!AllocateDeviceMemory(vkContext, &memory, image, nativeBuffer, nbProps, isProtected)) {
343         return {};
344     }
345 
346     if (!BindImageMemory(device, vkContext, image, memory)) {
347         return {};
348     }
349 
350     Drawing::BackendTexture backendTexture(true);
351     Drawing::TextureInfo textureInfo;
352     textureInfo.SetWidth(width);
353     textureInfo.SetHeight(height);
354 
355     std::shared_ptr<Drawing::VKTextureInfo> imageInfo = std::make_shared<Drawing::VKTextureInfo>();
356     imageInfo->vkImage = image;
357     imageInfo->vkAlloc.memory = memory;
358     imageInfo->vkAlloc.size = npProps.allocationSize;
359     imageInfo->vkAlloc.source = Drawing::VKMemSource::EXTERNAL;
360     imageInfo->vkProtected = isProtected ? true : false;
361     imageInfo->imageTiling = VK_IMAGE_TILING_OPTIMAL;
362     imageInfo->imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
363     imageInfo->format = nbFormatProps.format;
364     imageInfo->imageUsageFlags = usageFlags;
365     imageInfo->levelCount = 1;
366     imageInfo->currentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
367     imageInfo->ycbcrConversionInfo.format = nbFormatProps.format;
368     imageInfo->ycbcrConversionInfo.externalFormat = nbFormatProps.externalFormat;
369     imageInfo->ycbcrConversionInfo.ycbcrModel = nbFormatProps.suggestedYcbcrModel;
370     imageInfo->ycbcrConversionInfo.ycbcrRange = nbFormatProps.suggestedYcbcrRange;
371     imageInfo->ycbcrConversionInfo.xChromaOffset = nbFormatProps.suggestedXChromaOffset;
372     imageInfo->ycbcrConversionInfo.yChromaOffset = nbFormatProps.suggestedYChromaOffset;
373     imageInfo->ycbcrConversionInfo.chromaFilter = VK_FILTER_NEAREST;
374     imageInfo->ycbcrConversionInfo.forceExplicitReconstruction = VK_FALSE;
375     imageInfo->ycbcrConversionInfo.formatFeatures = nbFormatProps.formatFeatures;
376     if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT & nbFormatProps.formatFeatures) {
377         imageInfo->ycbcrConversionInfo.chromaFilter = VK_FILTER_LINEAR;
378     }
379     imageInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
380 
381     textureInfo.SetVKTextureInfo(imageInfo);
382     backendTexture.SetTextureInfo(textureInfo);
383     return backendTexture;
384 }
385 
386 std::shared_ptr<Drawing::Surface> CreateFromNativeWindowBuffer(Drawing::GPUContext* gpuContext,
387     const Drawing::ImageInfo& imageInfo, NativeSurfaceInfo& nativeSurface)
388 {
389     OH_NativeBuffer* nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(nativeSurface.nativeWindowBuffer);
390     if (nativeBuffer == nullptr) {
391         ROSEN_LOGE("CreateFromNativeWindowBuffer: OH_NativeBufferFromNativeWindowBuffer failed");
392         return nullptr;
393     }
394 
395     auto& vkContext = RsVulkanContext::GetSingleton();
396 
397     VkDevice device = vkContext.GetDevice();
398 
399     VkNativeBufferFormatPropertiesOHOS nbFormatProps;
400     VkNativeBufferPropertiesOHOS nbProps;
401     if (!GetNativeBufferFormatProperties(vkContext, device, nativeBuffer, &nbFormatProps, &nbProps)) {
402         return nullptr;
403     }
404 
405     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
406     if (nbFormatProps.format != VK_FORMAT_UNDEFINED) {
407         usageFlags = usageFlags | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
408             | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
409     }
410 
411     VkImage image;
412     if (!CreateVkImage(vkContext, &image, nbFormatProps, {imageInfo.GetWidth(), imageInfo.GetHeight(), 1},
413         usageFlags, false)) {
414         return nullptr;
415     }
416 
417     VkDeviceMemory memory;
418     if (!AllocateDeviceMemory(vkContext, &memory, image, nativeBuffer, nbProps, false)) {
419         return nullptr;
420     }
421 
422     if (!BindImageMemory(device, vkContext, image, memory)) {
423         return nullptr;
424     }
425 
426     Drawing::TextureInfo texture_info;
427     texture_info.SetWidth(imageInfo.GetWidth());
428     texture_info.SetHeight(imageInfo.GetHeight());
429     std::shared_ptr<Drawing::VKTextureInfo> vkTextureInfo = std::make_shared<Drawing::VKTextureInfo>();
430     vkTextureInfo->vkImage = image;
431     vkTextureInfo->vkAlloc.memory = memory;
432     vkTextureInfo->vkAlloc.size = npProps.allocationSize;
433     vkTextureInfo->vkAlloc.source = Drawing::VKMemSource::EXTERNAL;
434     vkTextureInfo->imageTiling = VK_IMAGE_TILING_OPTIMAL;
435     vkTextureInfo->imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
436     vkTextureInfo->format = nbFormatProps.format;
437     vkTextureInfo->imageUsageFlags = usageFlags;
438     vkTextureInfo->sampleCount = 1;
439     vkTextureInfo->levelCount = 1;
440     vkTextureInfo->vkProtected = false;
441     texture_info.SetVKTextureInfo(vkTextureInfo);
442 
443     std::shared_ptr<Drawing::Surface> surface = Drawing::Surface::MakeFromBackendTexture(
444         gpuContext,
445         texture_info,
446         Drawing::TextureOrigin::TOP_LEFT,
447         1,
448         imageInfo.GetColorType(),
449         Drawing::ColorSpace::CreateSRGB(),
450         DeleteVkImage,
451         new VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
452             image, memory));
453 
454     nativeSurface.image = image;
455     return surface;
456 }
457 
458 #ifdef RS_ENABLE_VK
459 uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
460 {
461     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
462         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
463         return UINT32_MAX;
464     }
465     auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
466     VkPhysicalDevice physicalDevice = vkContext.GetPhysicalDevice();
467 
468     VkPhysicalDeviceMemoryProperties memProperties;
469     vkContext.vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
470 
471     for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
472         if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
473             return i;
474         }
475     }
476 
477     return UINT32_MAX;
478 }
479 
480 void SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,
481     const VkImageCreateInfo& imageInfo)
482 {
483     if (vkImageInfo == nullptr) {
484         return;
485     }
486     vkImageInfo->imageTiling = imageInfo.tiling;
487     vkImageInfo->imageLayout = imageInfo.initialLayout;
488     vkImageInfo->format = imageInfo.format;
489     vkImageInfo->imageUsageFlags = imageInfo.usage;
490     vkImageInfo->levelCount = imageInfo.mipLevels;
491     vkImageInfo->currentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
492     vkImageInfo->ycbcrConversionInfo = {};
493     vkImageInfo->sharingMode = imageInfo.sharingMode;
494 }
495 
496 Drawing::BackendTexture MakeBackendTexture(
497     uint32_t width, uint32_t height, pid_t pid, VkFormat format)
498 {
499     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
500     VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
501         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
502     VkImageCreateInfo imageInfo {
503         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
504         .pNext = nullptr,
505         .flags = 0,
506         .imageType = VK_IMAGE_TYPE_2D,
507         .format = format,
508         .extent = {width, height, 1},
509         .mipLevels = 1,
510         .arrayLayers = 1,
511         .samples = VK_SAMPLE_COUNT_1_BIT,
512         .tiling = tiling,
513         .usage = usage,
514         .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
515         .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
516     };
517 
518     auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
519     VkDevice device = vkContext.GetDevice();
520     VkImage image = VK_NULL_HANDLE;
521     VkDeviceMemory memory = VK_NULL_HANDLE;
522 
523     if (width * height > OHOS::Rosen::NativeBufferUtils::VKIMAGE_LIMIT_SIZE) {
524         ROSEN_LOGE(
525             "NativeBufferUtils:Image is too large, width:%{public}u, height::%{public}u",
526             width, height);
527         return {};
528     }
529 
530     if (vkContext.vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
531         return {};
532     }
533     Drawing::BackendTexture backendTexture =
534         SetBackendTexture(vkContext, device, image, width, height, memory, imageInfo, pid);
535     return backendTexture;
536 }
537 Drawing::BackendTexture SetBackendTexture(RsVulkanInterface& vkContext, VkDevice device,
538     VkImage image, uint32_t width, uint32_t height, VkDeviceMemory memory, VkImageCreateInfo imageInfo,
539     pid_t pid)
540 {
541     VkMemoryRequirements memRequirements;
542     vkContext.vkGetImageMemoryRequirements(device, image, &memRequirements);
543 
544     VkMemoryAllocateInfo allocInfo{};
545     allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
546     allocInfo.allocationSize = memRequirements.size;
547     allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
548     if (allocInfo.memoryTypeIndex == UINT32_MAX) {
549         return {};
550     }
551 
552     if (vkContext.vkAllocateMemory(device, &allocInfo, nullptr, &memory) != VK_SUCCESS) {
553         return {};
554     }
555 
556     vkContext.vkBindImageMemory(device, image, memory, 0);
557 
558     OHOS::Rosen::RsVulkanMemStat& memStat = vkContext.GetRsVkMemStat();
559     auto time = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
560     std::string timeStamp = std::to_string(static_cast<uint64_t>(time.time_since_epoch().count()));
561     memStat.InsertResource(timeStamp, pid, static_cast<uint64_t>(memRequirements.size));
562 
563     OHOS::Rosen::Drawing::BackendTexture backendTexture(true);
564     OHOS::Rosen::Drawing::TextureInfo textureInfo;
565     textureInfo.SetWidth(width);
566     textureInfo.SetHeight(height);
567 
568     std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo =
569         std::make_shared<OHOS::Rosen::Drawing::VKTextureInfo>();
570     vkImageInfo->vkImage = image;
571     vkImageInfo->vkAlloc.memory = memory;
572     vkImageInfo->vkAlloc.size = memRequirements.size;
573     vkImageInfo->vkAlloc.statName = timeStamp;
574 
575     SetVkImageInfo(vkImageInfo, imageInfo);
576     textureInfo.SetVKTextureInfo(vkImageInfo);
577     backendTexture.SetTextureInfo(textureInfo);
578     return backendTexture;
579 }
580 
581 void CreateVkSemaphore(VkSemaphore& semaphore)
582 {
583     auto& vkContext = RsVulkanContext::GetSingleton().GetRsVulkanInterface();
584     VkExportSemaphoreCreateInfo exportSemaphoreCreateInfo;
585     exportSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
586     exportSemaphoreCreateInfo.pNext = nullptr;
587     exportSemaphoreCreateInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
588 
589     VkSemaphoreCreateInfo semaphoreInfo;
590     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
591     semaphoreInfo.pNext = &exportSemaphoreCreateInfo;
592     semaphoreInfo.flags = 0;
593     vkContext.vkCreateSemaphore(vkContext.GetDevice(), &semaphoreInfo, nullptr, &semaphore);
594 }
595 
596 void GetFenceFdFromSemaphore(VkSemaphore& semaphore, int32_t& syncFenceFd)
597 {
598     auto& vkContext = RsVulkanContext::GetSingleton().GetRsVulkanInterface();
599     VkSemaphoreGetFdInfoKHR getFdInfo;
600 
601     getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
602     getFdInfo.pNext = nullptr;
603     getFdInfo.semaphore = semaphore;
604     getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
605 
606     auto err = vkContext.vkGetSemaphoreFdKHR(vkContext.GetDevice(), &getFdInfo, &syncFenceFd);
607     if (VK_SUCCESS != err) {
608         RS_LOGD("FlushSurfaceWithFence: failed to get semaphore fd");
609         syncFenceFd = -1;
610     }
611 }
612 #endif
613 
614 } // namespace NativeBufferUtils
615 } // namespace OHOS::Rosen
616