1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // HardwareBufferImageSiblingVkAndroid.cpp: Implements HardwareBufferImageSiblingVkAndroid.
8
9 #include "libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h"
10
11 #include "common/android_util.h"
12
13 #include "libANGLE/Display.h"
14 #include "libANGLE/renderer/vulkan/DisplayVk.h"
15 #include "libANGLE/renderer/vulkan/android/AHBFunctions.h"
16 #include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h"
17 #include "libANGLE/renderer/vulkan/vk_renderer.h"
18
19 namespace rx
20 {
21
22 namespace
23 {
AhbDescUsageToVkImageTiling(const AHardwareBuffer_Desc & ahbDescription)24 VkImageTiling AhbDescUsageToVkImageTiling(const AHardwareBuffer_Desc &ahbDescription)
25 {
26 // A note about the choice of OPTIMAL here.
27
28 // When running Android on certain GPUs, there are problems creating Vulkan
29 // image siblings of AHardwareBuffers because it's currently assumed that
30 // the underlying driver can create linear tiling images that have input
31 // attachment usage, which isn't supported on NVIDIA for example, resulting
32 // in failure to create the image siblings. Yet, we don't currently take
33 // advantage of linear elsewhere in ANGLE. To maintain maximum
34 // compatibility on Android for such drivers, use optimal tiling for image
35 // siblings.
36 //
37 // Note that while we have switched to optimal unconditionally in this path
38 // versus linear, it's possible that previously compatible linear usages
39 // might become uncompatible after switching to optimal. However, from what
40 // we've seen on Samsung/NVIDIA/Intel/AMD GPUs so far, formats generally
41 // have more possible usages in optimal tiling versus linear tiling:
42 //
43 // http://vulkan.gpuinfo.org/displayreport.php?id=10804#formats_linear
44 // http://vulkan.gpuinfo.org/displayreport.php?id=10804#formats_optimal
45 //
46 // http://vulkan.gpuinfo.org/displayreport.php?id=10807#formats_linear
47 // http://vulkan.gpuinfo.org/displayreport.php?id=10807#formats_optimal
48 //
49 // http://vulkan.gpuinfo.org/displayreport.php?id=10809#formats_linear
50 // http://vulkan.gpuinfo.org/displayreport.php?id=10809#formats_optimal
51 //
52 // http://vulkan.gpuinfo.org/displayreport.php?id=10787#formats_linear
53 // http://vulkan.gpuinfo.org/displayreport.php?id=10787#formats_optimal
54 //
55 // Also, as an aside, in terms of what's generally expected from the Vulkan
56 // ICD in Android when determining AHB compatibility, if the vendor wants
57 // to declare a particular combination of format/tiling/usage/etc as not
58 // supported AHB-wise, it's up to the ICD vendor to zero out bits in
59 // supportedHandleTypes in the vkGetPhysicalDeviceImageFormatProperties2
60 // query:
61 //
62 // ``` *
63 // [VUID-VkImageCreateInfo-pNext-00990](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-VkImageCreateInfo-pNext-00990)
64 // If the pNext chain includes a VkExternalMemoryImageCreateInfo structure,
65 // its handleTypes member must only contain bits that are also in
66 // VkExternalImageFormatProperties::externalMemoryProperties.compatibleHandleTypes,
67 // as returned by vkGetPhysicalDeviceImageFormatProperties2 with format,
68 // imageType, tiling, usage, and flags equal to those in this structure,
69 // and with a VkPhysicalDeviceExternalImageFormatInfo structure included in
70 // the pNext chain, with a handleType equal to any one of the handle types
71 // specified in VkExternalMemoryImageCreateInfo::handleTypes ```
72
73 return VK_IMAGE_TILING_OPTIMAL;
74 }
75
76 // Map AHB usage flags to VkImageUsageFlags using this table from the Vulkan spec
77 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap11.html#memory-external-android-hardware-buffer-usage
AhbDescUsageToVkImageUsage(const AHardwareBuffer_Desc & ahbDescription,bool isDepthOrStencilFormat,bool isExternal)78 VkImageUsageFlags AhbDescUsageToVkImageUsage(const AHardwareBuffer_Desc &ahbDescription,
79 bool isDepthOrStencilFormat,
80 bool isExternal)
81 {
82 VkImageUsageFlags usage = 0;
83
84 if (!isExternal)
85 {
86 usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
87 }
88
89 if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) != 0)
90 {
91 usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
92 }
93
94 if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0)
95 {
96 if (isDepthOrStencilFormat)
97 {
98 usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
99 }
100 else
101 {
102 usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
103 }
104 }
105
106 return usage;
107 }
108
109 // Map AHB usage flags to VkImageCreateFlags using this table from the Vulkan spec
110 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap11.html#memory-external-android-hardware-buffer-usage
AhbDescUsageToVkImageCreateFlags(const AHardwareBuffer_Desc & ahbDescription)111 VkImageCreateFlags AhbDescUsageToVkImageCreateFlags(const AHardwareBuffer_Desc &ahbDescription)
112 {
113 VkImageCreateFlags imageCreateFlags = vk::kVkImageCreateFlagsNone;
114
115 if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) != 0)
116 {
117 imageCreateFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
118 }
119
120 if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) != 0)
121 {
122 imageCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT;
123 }
124
125 return imageCreateFlags;
126 }
127
128 // Deduce texture type based on AHB usage flags and layer count
AhbDescUsageToTextureType(const AHardwareBuffer_Desc & ahbDescription,const uint32_t layerCount)129 gl::TextureType AhbDescUsageToTextureType(const AHardwareBuffer_Desc &ahbDescription,
130 const uint32_t layerCount)
131 {
132 gl::TextureType textureType = layerCount > 1 ? gl::TextureType::_2DArray : gl::TextureType::_2D;
133 if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) != 0)
134 {
135 textureType = layerCount > gl::kCubeFaceCount ? gl::TextureType::CubeMapArray
136 : gl::TextureType::CubeMap;
137 }
138 return textureType;
139 }
140 // TODO(anglebug.com/42266422): remove when NDK header is updated to contain FRONT_BUFFER usage flag
141 constexpr uint64_t kAHardwareBufferUsageFrontBuffer = (1ULL << 32);
142 } // namespace
143
HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)144 HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)
145 : mBuffer(buffer),
146 mFormat(GL_NONE),
147 mRenderable(false),
148 mTextureable(false),
149 mYUV(false),
150 mLevelCount(0),
151 mUsage(0),
152 mSamples(0),
153 mImage(nullptr)
154 {}
155
~HardwareBufferImageSiblingVkAndroid()156 HardwareBufferImageSiblingVkAndroid::~HardwareBufferImageSiblingVkAndroid() {}
157
158 // Static
ValidateHardwareBuffer(vk::Renderer * renderer,EGLClientBuffer buffer,const egl::AttributeMap & attribs)159 egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(
160 vk::Renderer *renderer,
161 EGLClientBuffer buffer,
162 const egl::AttributeMap &attribs)
163 {
164 struct ANativeWindowBuffer *windowBuffer =
165 angle::android::ClientBufferToANativeWindowBuffer(buffer);
166 struct AHardwareBuffer *hardwareBuffer = nullptr;
167 if (windowBuffer != nullptr)
168 {
169 if (!angle::android::IsValidNativeWindowBuffer(windowBuffer))
170 {
171 return egl::Error(EGL_BAD_PARAMETER,
172 "The given buffer is not a valid native window buffer.");
173 }
174 hardwareBuffer = angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
175 if (hardwareBuffer == nullptr)
176 {
177 return egl::Error(EGL_BAD_PARAMETER,
178 "Failed to obtain hardware buffer through given window buffer.");
179 }
180 }
181 else
182 {
183 return egl::Error(EGL_BAD_PARAMETER,
184 "Failed to obtain Window buffer through given client buffer handler.");
185 }
186
187 VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties = {};
188 bufferFormatProperties.sType =
189 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
190 bufferFormatProperties.pNext = nullptr;
191
192 VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
193 bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
194 bufferProperties.pNext = &bufferFormatProperties;
195
196 VkDevice device = renderer->getDevice();
197 VkResult result =
198 vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer, &bufferProperties);
199 if (result != VK_SUCCESS)
200 {
201 return egl::Error(EGL_BAD_PARAMETER, "Failed to query AHardwareBuffer properties");
202 }
203
204 int width = 0;
205 int height = 0;
206 int depth = 0;
207 int pixelFormat = 0;
208 uint64_t usage = 0;
209 angle::android::GetANativeWindowBufferProperties(windowBuffer, &width, &height, &depth,
210 &pixelFormat, &usage);
211
212 if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)
213 {
214 ASSERT(bufferFormatProperties.externalFormat != 0);
215 // We must have an external format, check that it supports texture sampling
216 if (!(bufferFormatProperties.formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
217 {
218 std::ostringstream err;
219 err << "Sampling from AHardwareBuffer externalFormat 0x" << std::hex
220 << bufferFormatProperties.externalFormat << " is unsupported.";
221 return egl::Error(EGL_BAD_PARAMETER, err.str());
222 }
223 }
224 else
225 {
226 angle::FormatID formatID = vk::GetFormatIDFromVkFormat(bufferFormatProperties.format);
227 const bool hasNecessaryFormatSupport =
228 (usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0
229 ? HasFullTextureFormatSupport(renderer, formatID)
230 : HasNonRenderableTextureFormatSupport(renderer, formatID);
231 if (!hasNecessaryFormatSupport)
232 {
233 std::ostringstream err;
234 err << "AHardwareBuffer format " << bufferFormatProperties.format
235 << " does not support enough features to use as a texture.";
236 return egl::Error(EGL_BAD_PARAMETER, err.str());
237 }
238 }
239
240 if (attribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE)
241 {
242 if ((usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) == 0)
243 {
244 return egl::Error(EGL_BAD_ACCESS,
245 "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
246 "of EGLClientBuffer.");
247 }
248 }
249
250 return egl::NoError();
251 }
252
initialize(const egl::Display * display)253 egl::Error HardwareBufferImageSiblingVkAndroid::initialize(const egl::Display *display)
254 {
255 DisplayVk *displayVk = vk::GetImpl(display);
256 return angle::ToEGL(initImpl(displayVk), EGL_BAD_PARAMETER);
257 }
258
initImpl(DisplayVk * displayVk)259 angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk)
260 {
261 const AHBFunctions &functions = static_cast<DisplayVkAndroid *>(displayVk)->getAHBFunctions();
262 ANGLE_VK_CHECK(displayVk, functions.valid(), VK_ERROR_INITIALIZATION_FAILED);
263
264 vk::Renderer *renderer = displayVk->getRenderer();
265
266 struct ANativeWindowBuffer *windowBuffer =
267 angle::android::ClientBufferToANativeWindowBuffer(mBuffer);
268
269 int pixelFormat = 0;
270 angle::android::GetANativeWindowBufferProperties(windowBuffer, &mSize.width, &mSize.height,
271 &mSize.depth, &pixelFormat, &mUsage);
272
273 struct AHardwareBuffer *hardwareBuffer =
274 angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
275
276 functions.acquire(hardwareBuffer);
277
278 VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
279 bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
280 bufferProperties.pNext = nullptr;
281
282 VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties;
283 bufferFormatProperties.sType =
284 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
285 bufferFormatProperties.pNext = nullptr;
286 vk::AddToPNextChain(&bufferProperties, &bufferFormatProperties);
287
288 VkAndroidHardwareBufferFormatResolvePropertiesANDROID bufferFormatResolveProperties = {};
289 if (renderer->getFeatures().supportsExternalFormatResolve.enabled)
290 {
291 bufferFormatResolveProperties.sType =
292 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID;
293 bufferFormatResolveProperties.pNext = nullptr;
294 vk::AddToPNextChain(&bufferFormatProperties, &bufferFormatResolveProperties);
295 }
296
297 VkDevice device = renderer->getDevice();
298 ANGLE_VK_TRY(displayVk, vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer,
299 &bufferProperties));
300
301 const bool isExternal = bufferFormatProperties.format == VK_FORMAT_UNDEFINED;
302
303 VkExternalFormatANDROID externalFormat = {};
304 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
305 externalFormat.externalFormat = 0;
306
307 // Use bufferFormatProperties.format directly when possible. For RGBX, the spec requires the
308 // corresponding format to be RGB, which is not _technically_ correct. The Vulkan backend uses
309 // the RGBX8_ANGLE format, so that's overriden.
310 //
311 // Where bufferFormatProperties.format returns UNDEFINED, NativePixelFormatToGLInternalFormat is
312 // used to infer the format.
313 const vk::Format *vkFormat = nullptr;
314 if (pixelFormat == AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM)
315 {
316 vkFormat = &renderer->getFormat(GL_RGBX8_ANGLE);
317 }
318 else if (!isExternal)
319 {
320 vkFormat = &renderer->getFormat(vk::GetFormatIDFromVkFormat(bufferFormatProperties.format));
321 }
322 else
323 {
324 vkFormat =
325 &renderer->getFormat(angle::android::NativePixelFormatToGLInternalFormat(pixelFormat));
326 }
327
328 const angle::Format &imageFormat = vkFormat->getActualRenderableImageFormat();
329 bool isDepthOrStencilFormat = imageFormat.hasDepthOrStencilBits();
330 mFormat = gl::Format(vkFormat->getIntendedGLFormat());
331
332 bool externalRenderTargetSupported =
333 renderer->getFeatures().supportsExternalFormatResolve.enabled &&
334 bufferFormatResolveProperties.colorAttachmentFormat != VK_FORMAT_UNDEFINED;
335 // Can assume based on us getting here already. The supportsYUVSamplerConversion
336 // check below should serve as a backup otherwise.
337 bool externalTexturingSupported = true;
338
339 // Query AHB description and do the following -
340 // 1. Derive VkImageTiling mode based on AHB usage flags
341 // 2. Map AHB usage flags to VkImageUsageFlags
342 AHardwareBuffer_Desc ahbDescription;
343 functions.describe(hardwareBuffer, &ahbDescription);
344 VkImageTiling imageTilingMode = AhbDescUsageToVkImageTiling(ahbDescription);
345 VkImageUsageFlags usage =
346 AhbDescUsageToVkImageUsage(ahbDescription, isDepthOrStencilFormat, isExternal);
347
348 if (isExternal)
349 {
350 ANGLE_VK_CHECK(displayVk, bufferFormatProperties.externalFormat != 0, VK_ERROR_UNKNOWN);
351 externalFormat.externalFormat = bufferFormatProperties.externalFormat;
352
353 // VkImageCreateInfo struct: If the pNext chain includes a VkExternalFormatANDROID structure
354 // whose externalFormat member is not 0, usage must not include any usages except
355 // VK_IMAGE_USAGE_SAMPLED_BIT
356 if (externalFormat.externalFormat != 0 && !externalRenderTargetSupported)
357 {
358 // Clear all other bits except sampled
359 usage &= VK_IMAGE_USAGE_SAMPLED_BIT;
360 }
361
362 // If the pNext chain includes a VkExternalFormatANDROID structure whose externalFormat
363 // member is not 0, tiling must be VK_IMAGE_TILING_OPTIMAL
364 imageTilingMode = VK_IMAGE_TILING_OPTIMAL;
365 }
366
367 // If forceSampleUsageForAhbBackedImages feature is enabled force enable
368 // VK_IMAGE_USAGE_SAMPLED_BIT
369 if (renderer->getFeatures().forceSampleUsageForAhbBackedImages.enabled)
370 {
371 usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
372 }
373
374 VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
375 externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
376 externalMemoryImageCreateInfo.pNext = &externalFormat;
377 externalMemoryImageCreateInfo.handleTypes =
378 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
379
380 VkExtent3D vkExtents;
381 gl_vk::GetExtent(mSize, &vkExtents);
382
383 // Setup level count
384 mLevelCount = ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE) != 0)
385 ? static_cast<uint32_t>(log2(std::max(mSize.width, mSize.height))) + 1
386 : 1;
387
388 // No support for rendering to external YUV AHB with multiple miplevels
389 ANGLE_VK_CHECK(displayVk, (!externalRenderTargetSupported || mLevelCount == 1),
390 VK_ERROR_INITIALIZATION_FAILED);
391
392 // Setup layer count
393 const uint32_t layerCount = mSize.depth;
394 vkExtents.depth = 1;
395
396 mImage = new vk::ImageHelper();
397
398 // disable robust init for this external image.
399 bool robustInitEnabled = false;
400
401 mImage->setTilingMode(imageTilingMode);
402 VkImageCreateFlags imageCreateFlags = AhbDescUsageToVkImageCreateFlags(ahbDescription);
403 vk::YcbcrConversionDesc conversionDesc{};
404
405 if (isExternal)
406 {
407 if (externalRenderTargetSupported)
408 {
409 angle::FormatID externalFormatID =
410 renderer->getExternalFormatTable()->getOrAllocExternalFormatID(
411 bufferFormatProperties.externalFormat,
412 bufferFormatResolveProperties.colorAttachmentFormat,
413 bufferFormatProperties.formatFeatures);
414
415 vkFormat = &renderer->getFormat(externalFormatID);
416 }
417 else
418 {
419 // If not renderable, don't burn a slot on it.
420 vkFormat = &renderer->getFormat(angle::FormatID::NONE);
421 }
422 }
423
424 if (isExternal || imageFormat.isYUV)
425 {
426 // Note from Vulkan spec: Since GL_OES_EGL_image_external does not require the same sampling
427 // and conversion calculations as Vulkan does, achieving identical results between APIs may
428 // not be possible on some implementations.
429 ANGLE_VK_CHECK(displayVk, renderer->getFeatures().supportsYUVSamplerConversion.enabled,
430 VK_ERROR_FEATURE_NOT_PRESENT);
431 ASSERT(externalFormat.pNext == nullptr);
432
433 // This may not actually mean the format is YUV. But the rest of ANGLE makes this
434 // assumption and needs this member variable.
435 mYUV = true;
436
437 vk::YcbcrLinearFilterSupport linearFilterSupported =
438 (bufferFormatProperties.formatFeatures &
439 VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) != 0
440 ? vk::YcbcrLinearFilterSupport::Supported
441 : vk::YcbcrLinearFilterSupport::Unsupported;
442
443 conversionDesc.update(
444 renderer, isExternal ? bufferFormatProperties.externalFormat : 0,
445 bufferFormatProperties.suggestedYcbcrModel, bufferFormatProperties.suggestedYcbcrRange,
446 bufferFormatProperties.suggestedXChromaOffset,
447 bufferFormatProperties.suggestedYChromaOffset, vk::kDefaultYCbCrChromaFilter,
448 bufferFormatProperties.samplerYcbcrConversionComponents,
449 isExternal ? angle::FormatID::NONE : imageFormat.id, linearFilterSupported);
450 }
451
452 const gl::TextureType textureType = AhbDescUsageToTextureType(ahbDescription, layerCount);
453 const angle::FormatID actualRenderableFormatID = vkFormat->getActualRenderableImageFormatID();
454
455 VkImageFormatListCreateInfoKHR imageFormatListInfoStorage;
456 vk::ImageHelper::ImageListFormats imageListFormatsStorage;
457
458 const void *imageCreateInfoPNext = vk::ImageHelper::DeriveCreateInfoPNext(
459 displayVk, usage, actualRenderableFormatID, &externalMemoryImageCreateInfo,
460 &imageFormatListInfoStorage, &imageListFormatsStorage, &imageCreateFlags);
461
462 ANGLE_TRY(mImage->initExternal(displayVk, textureType, vkExtents,
463 vkFormat->getIntendedFormatID(), actualRenderableFormatID, 1,
464 usage, imageCreateFlags, vk::ImageLayout::ExternalPreInitialized,
465 imageCreateInfoPNext, gl::LevelIndex(0), mLevelCount, layerCount,
466 robustInitEnabled, hasProtectedContent(), conversionDesc,
467 nullptr));
468
469 VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
470 importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
471 importHardwareBufferInfo.buffer = hardwareBuffer;
472
473 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {};
474 dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
475 dedicatedAllocInfo.pNext = &importHardwareBufferInfo;
476 dedicatedAllocInfo.image = mImage->getImage().getHandle();
477 dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
478 const void *dedicatedAllocInfoPtr = &dedicatedAllocInfo;
479
480 VkMemoryRequirements externalMemoryRequirements = {};
481 externalMemoryRequirements.size = bufferProperties.allocationSize;
482 externalMemoryRequirements.alignment = 0;
483 externalMemoryRequirements.memoryTypeBits = bufferProperties.memoryTypeBits;
484
485 const VkMemoryPropertyFlags flags =
486 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
487 (hasProtectedContent() ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0);
488
489 ANGLE_TRY(mImage->initExternalMemory(displayVk, renderer->getMemoryProperties(),
490 externalMemoryRequirements, 1, &dedicatedAllocInfoPtr,
491 vk::kForeignDeviceQueueIndex, flags));
492
493 if (isExternal)
494 {
495 // External format means that we are working with VK_FORMAT_UNDEFINED,
496 // so hasImageFormatFeatureBits will assert. Set these based on
497 // presence of extensions or assumption.
498 mRenderable = externalRenderTargetSupported;
499 mTextureable = externalTexturingSupported;
500 }
501 else
502 {
503 constexpr uint32_t kColorRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
504 constexpr uint32_t kDepthStencilRenderableRequiredBits =
505 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
506 mRenderable = renderer->hasImageFormatFeatureBits(actualRenderableFormatID,
507 kColorRenderableRequiredBits) ||
508 renderer->hasImageFormatFeatureBits(actualRenderableFormatID,
509 kDepthStencilRenderableRequiredBits);
510 constexpr uint32_t kTextureableRequiredBits =
511 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
512 mTextureable =
513 renderer->hasImageFormatFeatureBits(actualRenderableFormatID, kTextureableRequiredBits);
514 }
515
516 return angle::Result::Continue;
517 }
518
onDestroy(const egl::Display * display)519 void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
520 {
521 const AHBFunctions &functions = GetImplAs<DisplayVkAndroid>(display)->getAHBFunctions();
522 ASSERT(functions.valid());
523
524 functions.release(angle::android::ANativeWindowBufferToAHardwareBuffer(
525 angle::android::ClientBufferToANativeWindowBuffer(mBuffer)));
526
527 ASSERT(mImage == nullptr);
528 }
529
getFormat() const530 gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
531 {
532 return mFormat;
533 }
534
isRenderable(const gl::Context * context) const535 bool HardwareBufferImageSiblingVkAndroid::isRenderable(const gl::Context *context) const
536 {
537 return mRenderable;
538 }
539
isTexturable(const gl::Context * context) const540 bool HardwareBufferImageSiblingVkAndroid::isTexturable(const gl::Context *context) const
541 {
542 return mTextureable;
543 }
544
isYUV() const545 bool HardwareBufferImageSiblingVkAndroid::isYUV() const
546 {
547 return mYUV;
548 }
549
hasFrontBufferUsage() const550 bool HardwareBufferImageSiblingVkAndroid::hasFrontBufferUsage() const
551 {
552 return (mUsage & kAHardwareBufferUsageFrontBuffer) != 0;
553 }
554
isCubeMap() const555 bool HardwareBufferImageSiblingVkAndroid::isCubeMap() const
556 {
557 return (mUsage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) != 0;
558 }
559
hasProtectedContent() const560 bool HardwareBufferImageSiblingVkAndroid::hasProtectedContent() const
561 {
562 return ((mUsage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) != 0);
563 }
564
getSize() const565 gl::Extents HardwareBufferImageSiblingVkAndroid::getSize() const
566 {
567 return mSize;
568 }
569
getSamples() const570 size_t HardwareBufferImageSiblingVkAndroid::getSamples() const
571 {
572 return mSamples;
573 }
574
getLevelCount() const575 uint32_t HardwareBufferImageSiblingVkAndroid::getLevelCount() const
576 {
577 return mLevelCount;
578 }
579
580 // ExternalImageSiblingVk interface
getImage() const581 vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
582 {
583 return mImage;
584 }
585
release(vk::Renderer * renderer)586 void HardwareBufferImageSiblingVkAndroid::release(vk::Renderer *renderer)
587 {
588 if (mImage != nullptr)
589 {
590 // TODO: Handle the case where the EGLImage is used in two contexts not in the same share
591 // group. https://issuetracker.google.com/169868803
592 mImage->releaseImage(renderer);
593 mImage->releaseStagedUpdates(renderer);
594 SafeDelete(mImage);
595 }
596 }
597
598 } // namespace rx
599