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