• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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