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/RendererVk.h"
16
17 namespace rx
18 {
19
HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)20 HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)
21 : mBuffer(buffer),
22 mFormat(GL_NONE),
23 mRenderable(false),
24 mTextureable(false),
25 mSamples(0),
26 mImage(nullptr)
27 {}
28
~HardwareBufferImageSiblingVkAndroid()29 HardwareBufferImageSiblingVkAndroid::~HardwareBufferImageSiblingVkAndroid() {}
30
31 // Static
ValidateHardwareBuffer(RendererVk * renderer,EGLClientBuffer buffer)32 egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(RendererVk *renderer,
33 EGLClientBuffer buffer)
34 {
35 struct ANativeWindowBuffer *windowBuffer =
36 angle::android::ClientBufferToANativeWindowBuffer(buffer);
37 struct AHardwareBuffer *hardwareBuffer =
38 angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
39
40 VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties = {};
41 bufferFormatProperties.sType =
42 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
43 bufferFormatProperties.pNext = nullptr;
44
45 VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
46 bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
47 bufferProperties.pNext = &bufferFormatProperties;
48
49 VkDevice device = renderer->getDevice();
50 VkResult result =
51 vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer, &bufferProperties);
52 if (result != VK_SUCCESS)
53 {
54 return egl::EglBadParameter() << "Failed to query AHardwareBuffer properties";
55 }
56
57 if (!HasFullTextureFormatSupport(renderer, bufferFormatProperties.format))
58 {
59 return egl::EglBadParameter()
60 << "AHardwareBuffer format does not support enough features to use as a texture.";
61 }
62
63 return egl::NoError();
64 }
65
initialize(const egl::Display * display)66 egl::Error HardwareBufferImageSiblingVkAndroid::initialize(const egl::Display *display)
67 {
68 DisplayVk *displayVk = vk::GetImpl(display);
69 return angle::ToEGL(initImpl(displayVk), displayVk, EGL_BAD_PARAMETER);
70 }
71
initImpl(DisplayVk * displayVk)72 angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk)
73 {
74 RendererVk *renderer = displayVk->getRenderer();
75
76 struct ANativeWindowBuffer *windowBuffer =
77 angle::android::ClientBufferToANativeWindowBuffer(mBuffer);
78
79 int pixelFormat = 0;
80 angle::android::GetANativeWindowBufferProperties(windowBuffer, &mSize.width, &mSize.height,
81 &mSize.depth, &pixelFormat);
82 GLenum internalFormat = angle::android::NativePixelFormatToGLInternalFormat(pixelFormat);
83 mFormat = gl::Format(internalFormat);
84
85 struct AHardwareBuffer *hardwareBuffer =
86 angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
87
88 VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties;
89 bufferFormatProperties.sType =
90 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
91 bufferFormatProperties.pNext = nullptr;
92
93 VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
94 bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
95 bufferProperties.pNext = &bufferFormatProperties;
96
97 VkDevice device = renderer->getDevice();
98 ANGLE_VK_TRY(displayVk, vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer,
99 &bufferProperties));
100
101 const vk::Format &vkFormat = renderer->getFormat(internalFormat);
102 const angle::Format &imageFormat = vkFormat.actualImageFormat();
103 bool isDepthOrStencilFormat = imageFormat.depthBits > 0 || imageFormat.stencilBits > 0;
104 const VkImageUsageFlags usage =
105 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
106 VK_IMAGE_USAGE_SAMPLED_BIT |
107 (imageFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
108 (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
109
110 VkExternalFormatANDROID externalFormat = {};
111 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
112 externalFormat.externalFormat = 0;
113
114 if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)
115 {
116 externalFormat.externalFormat = bufferFormatProperties.externalFormat;
117 }
118
119 VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
120 externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
121 externalMemoryImageCreateInfo.pNext = &externalFormat;
122 externalMemoryImageCreateInfo.handleTypes =
123 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
124
125 VkExtent3D vkExtents;
126 gl_vk::GetExtent(mSize, &vkExtents);
127
128 mImage = new vk::ImageHelper();
129 ANGLE_TRY(mImage->initExternal(displayVk, gl::TextureType::_2D, vkExtents, vkFormat, 1, usage,
130 vk::ImageLayout::ExternalPreInitialized,
131 &externalMemoryImageCreateInfo, 0, 0, 1, 1));
132
133 VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
134 importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
135 importHardwareBufferInfo.buffer = hardwareBuffer;
136
137 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {};
138 dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
139 dedicatedAllocInfo.pNext = &importHardwareBufferInfo;
140 dedicatedAllocInfo.image = mImage->getImage().getHandle();
141 dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
142
143 VkMemoryRequirements externalMemoryRequirements = {};
144 externalMemoryRequirements.size = bufferProperties.allocationSize;
145 externalMemoryRequirements.alignment = 0;
146 externalMemoryRequirements.memoryTypeBits = bufferProperties.memoryTypeBits;
147
148 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
149 ANGLE_TRY(mImage->initExternalMemory(displayVk, renderer->getMemoryProperties(),
150 externalMemoryRequirements, &dedicatedAllocInfo,
151 VK_QUEUE_FAMILY_FOREIGN_EXT, flags));
152
153 constexpr uint32_t kColorRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
154 constexpr uint32_t kDepthStencilRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
155 mRenderable =
156 renderer->hasImageFormatFeatureBits(vkFormat.vkImageFormat, kColorRenderableRequiredBits) ||
157 renderer->hasImageFormatFeatureBits(vkFormat.vkImageFormat,
158 kDepthStencilRenderableRequiredBits);
159
160 constexpr uint32_t kTextureableRequiredBits =
161 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
162 mTextureable =
163 renderer->hasImageFormatFeatureBits(vkFormat.vkImageFormat, kTextureableRequiredBits);
164
165 return angle::Result::Continue;
166 }
167
onDestroy(const egl::Display * display)168 void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
169 {
170 ASSERT(mImage == nullptr);
171 }
172
getFormat() const173 gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
174 {
175 return mFormat;
176 }
177
isRenderable(const gl::Context * context) const178 bool HardwareBufferImageSiblingVkAndroid::isRenderable(const gl::Context *context) const
179 {
180 return mRenderable;
181 }
182
isTexturable(const gl::Context * context) const183 bool HardwareBufferImageSiblingVkAndroid::isTexturable(const gl::Context *context) const
184 {
185 return mTextureable;
186 }
187
getSize() const188 gl::Extents HardwareBufferImageSiblingVkAndroid::getSize() const
189 {
190 return mSize;
191 }
192
getSamples() const193 size_t HardwareBufferImageSiblingVkAndroid::getSamples() const
194 {
195 return mSamples;
196 }
197
198 // ExternalImageSiblingVk interface
getImage() const199 vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
200 {
201 return mImage;
202 }
203
release(RendererVk * renderer)204 void HardwareBufferImageSiblingVkAndroid::release(RendererVk *renderer)
205 {
206 if (mImage != nullptr)
207 {
208 mImage->releaseImage(renderer);
209 mImage->releaseStagingBuffer(renderer);
210 SafeDelete(mImage);
211 }
212 }
213
214 } // namespace rx
215