15
15
*/
16
16
#include < backend/platforms/VulkanPlatform.h>
17
17
18
+ #include < backend/DriverEnums.h>
19
+ #include < backend/platforms/VulkanPlatformAndroid.h>
20
+
18
21
#include " vulkan/VulkanConstants.h"
19
22
20
23
#include < utils/Panic.h>
24
27
#include < android/hardware_buffer.h>
25
28
#include < android/native_window.h>
26
29
30
+ #include < utility>
31
+
27
32
using namespace bluevk ;
28
33
29
34
namespace filament ::backend {
30
35
31
36
namespace {
32
- void getVKFormatAndUsage (const AHardwareBuffer_Desc& desc, VkFormat& format,
33
- VkImageUsageFlags& usage, bool & isProtected) {
37
+
38
+ VkFormat transformVkFormat (VkFormat format, bool sRGB ) {
39
+ if (!sRGB ) {
40
+ return format;
41
+ }
42
+
43
+ switch (format) {
44
+ case VK_FORMAT_R8G8B8A8_UNORM:
45
+ format = VK_FORMAT_R8G8B8A8_SRGB;
46
+ break ;
47
+ case VK_FORMAT_R8G8B8_UNORM:
48
+ format = VK_FORMAT_R8G8B8_SRGB;
49
+ break ;
50
+ default :
51
+ break ;
52
+ }
53
+
54
+ return format;
55
+ }
56
+
57
+ bool isProtectedFromUsage (uint64_t usage) {
58
+ return (usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) ? true : false ;
59
+ }
60
+
61
+ std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage (const AHardwareBuffer_Desc& desc, bool sRGB ) {
62
+ VkFormat format = VK_FORMAT_UNDEFINED;
63
+ VkImageUsageFlags usage = 0 ;
34
64
// Refer to "11.2.17. External Memory Handle Types" in the spec, and
35
65
// Tables 13/14 for how the following derivation works.
36
66
bool isDepthFormat = false ;
37
- isProtected = false ;
38
67
switch (desc.format ) {
39
68
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
40
69
format = VK_FORMAT_R8G8B8A8_UNORM;
@@ -82,6 +111,8 @@ void getVKFormatAndUsage(const AHardwareBuffer_Desc& desc, VkFormat& format,
82
111
format = VK_FORMAT_UNDEFINED;
83
112
}
84
113
114
+ format = transformVkFormat (format, sRGB );
115
+
85
116
// The following only concern usage flags derived from Table 14.
86
117
usage = 0 ;
87
118
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
@@ -98,16 +129,89 @@ void getVKFormatAndUsage(const AHardwareBuffer_Desc& desc, VkFormat& format,
98
129
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) {
99
130
usage = VK_IMAGE_USAGE_STORAGE_BIT;
100
131
}
101
- if (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
102
- isProtected = true ;
132
+
133
+ return {format, usage};
134
+ }
135
+
136
+ TextureFormat mapToFilamentFormat (unsigned int format, bool isSrgbTransfer) noexcept {
137
+ if (isSrgbTransfer) {
138
+ switch (format) {
139
+ case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
140
+ return TextureFormat::SRGB8;
141
+ default :
142
+ return TextureFormat::SRGB8_A8;
143
+ }
144
+ }
145
+ switch (format) {
146
+ case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
147
+ case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
148
+ return TextureFormat::RGBA8;
149
+ case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
150
+ case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
151
+ return TextureFormat::RGB8;
152
+ case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
153
+ return TextureFormat::RGB565;
154
+ case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
155
+ return TextureFormat::RGBA16F;
156
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
157
+ return TextureFormat::RGB10_A2;
158
+ case AHARDWAREBUFFER_FORMAT_D16_UNORM:
159
+ return TextureFormat::DEPTH16;
160
+ case AHARDWAREBUFFER_FORMAT_D24_UNORM:
161
+ return TextureFormat::DEPTH24;
162
+ case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
163
+ return TextureFormat::DEPTH24_STENCIL8;
164
+ case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
165
+ return TextureFormat::DEPTH32F;
166
+ case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
167
+ return TextureFormat::DEPTH32F_STENCIL8;
168
+ case AHARDWAREBUFFER_FORMAT_S8_UINT:
169
+ return TextureFormat::STENCIL8;
170
+ case AHARDWAREBUFFER_FORMAT_R8_UNORM:
171
+ return TextureFormat::R8;
172
+ default :
173
+ return TextureFormat::UNUSED;
174
+ }
175
+ }
176
+
177
+ TextureUsage mapToFilamentUsage (unsigned int usage, TextureFormat format) noexcept {
178
+ TextureUsage usageFlags = TextureUsage::NONE;
179
+
180
+ if (usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
181
+ usageFlags |= TextureUsage::SAMPLEABLE;
182
+ }
183
+
184
+ if (usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) {
185
+ if (isDepthFormat (format)) {
186
+ usageFlags |= TextureUsage::DEPTH_ATTACHMENT;
187
+ }
188
+ if (isStencilFormat (format)) {
189
+ usageFlags |= TextureUsage::STENCIL_ATTACHMENT;
190
+ }
191
+ if (isColorFormat (format)) {
192
+ usageFlags |= TextureUsage::COLOR_ATTACHMENT;
193
+ }
194
+ }
195
+
196
+ if (usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) {
197
+ usageFlags |= TextureUsage::UPLOADABLE;
198
+ }
199
+
200
+ if (usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
201
+ usageFlags |= TextureUsage::PROTECTED;
202
+ }
203
+
204
+ if (usageFlags == TextureUsage::NONE) {
205
+ usageFlags = TextureUsage::COLOR_ATTACHMENT | TextureUsage::SAMPLEABLE;
103
206
}
207
+
208
+ return usageFlags;
104
209
}
105
210
106
- VulkanPlatform::ImageData allocateExternalImage (void * externalBuffer ,
211
+ VulkanPlatform::ImageData allocateExternalImage (AHardwareBuffer* buffer ,
107
212
VkDevice device, const VkAllocationCallbacks* allocator,
108
213
VulkanPlatform::ExternalImageMetadata const & metadata) {
109
214
VulkanPlatform::ImageData data;
110
- AHardwareBuffer* buffer = static_cast <AHardwareBuffer*>(externalBuffer);
111
215
112
216
// if external format we need to specifiy it in the allocation
113
217
const bool useExternalFormat = metadata.format == VK_FORMAT_UNDEFINED;
@@ -167,20 +271,50 @@ VulkanPlatform::ImageData allocateExternalImage(void* externalBuffer,
167
271
return data;
168
272
}
169
273
170
- }// namespace
274
+ } // namespace
275
+
276
+ namespace fvkandroid {
277
+
278
+ ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid () = default ;
279
+
280
+ Platform::ExternalImageHandle createExternalImage (AHardwareBuffer const *buffer,
281
+ bool sRGB ) noexcept {
282
+ if (__builtin_available (android 26 , *)) {
283
+ AHardwareBuffer_Desc hardwareBufferDescription = {};
284
+ AHardwareBuffer_describe (buffer, &hardwareBufferDescription);
285
+
286
+ auto * const p = new (std::nothrow) ExternalImageVulkanAndroid;
287
+ p->aHardwareBuffer = const_cast <AHardwareBuffer*>(buffer);
288
+ p->sRGB = sRGB ;
289
+ p->height = hardwareBufferDescription.height ;
290
+ p->width = hardwareBufferDescription.width ;
291
+ TextureFormat textureFormat = mapToFilamentFormat (hardwareBufferDescription.format , sRGB );
292
+ p->format = textureFormat;
293
+ p->usage = mapToFilamentUsage (hardwareBufferDescription.usage , textureFormat);
294
+ return Platform::ExternalImageHandle{p};
295
+ }
296
+
297
+ return Platform::ExternalImageHandle{};
298
+ }
299
+
300
+ }
301
+
302
+ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl (
303
+ ExternalImageHandleRef externalImage, VkDevice device) {
304
+ auto const *fvkExternalImage =
305
+ static_cast <fvkandroid::ExternalImageVulkanAndroid const *>(externalImage.get ());
171
306
172
- VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl (void * externalImage,
173
- VkDevice device) {
174
307
ExternalImageMetadata metadata;
175
- AHardwareBuffer* buffer = static_cast <AHardwareBuffer*>(externalImage) ;
308
+ AHardwareBuffer* buffer = fvkExternalImage-> aHardwareBuffer ;
176
309
if (__builtin_available (android 26 , *)) {
177
310
AHardwareBuffer_Desc bufferDesc;
178
311
AHardwareBuffer_describe (buffer, &bufferDesc);
179
312
metadata.width = bufferDesc.width ;
180
313
metadata.height = bufferDesc.height ;
181
314
metadata.layers = bufferDesc.layers ;
182
-
183
- getVKFormatAndUsage (bufferDesc, metadata.format , metadata.usage , metadata.isProtected );
315
+ metadata.isProtected = isProtectedFromUsage (bufferDesc.usage );
316
+ std::tie (metadata.format , metadata.usage ) = getVKFormatAndUsage (bufferDesc,
317
+ fvkExternalImage->sRGB );
184
318
}
185
319
// In the unprotected case add R/W capabilities
186
320
if (metadata.isProtected == false ) {
@@ -197,20 +331,26 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
197
331
};
198
332
VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID (device, buffer, &properties);
199
333
FILAMENT_CHECK_POSTCONDITION (result == VK_SUCCESS)
200
- << " vkGetAndroidHardwareBufferProperties failed with error="
201
- << static_cast <int32_t >(result);
202
- FILAMENT_CHECK_POSTCONDITION (metadata.format == formatInfo.format )
203
- << " mismatched image format for external image (AHB)" ;
334
+ << " vkGetAndroidHardwareBufferProperties failed with error="
335
+ << static_cast <int32_t >(result);
336
+
337
+ VkFormat bufferPropertiesFormat = transformVkFormat (formatInfo.format , fvkExternalImage->sRGB );
338
+ FILAMENT_CHECK_POSTCONDITION (metadata.format == bufferPropertiesFormat)
339
+ << " mismatched image format( " << metadata.format << " ) and queried format("
340
+ << bufferPropertiesFormat << " ) for external image (AHB)" ;
204
341
metadata.externalFormat = formatInfo.externalFormat ;
205
342
metadata.allocationSize = properties.allocationSize ;
206
343
metadata.memoryTypeBits = properties.memoryTypeBits ;
207
344
return metadata;
208
345
}
209
346
210
- VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl ( void * externalImage,
211
- VkDevice device, const VkAllocationCallbacks* allocator ,
347
+ VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl (
348
+ ExternalImageHandleRef externalImage, VkDevice device ,
212
349
const ExternalImageMetadata& metadata) {
213
- ImageData data = allocateExternalImage (externalImage, device, allocator, metadata);
350
+ auto const * fvkExternalImage =
351
+ static_cast <fvkandroid::ExternalImageVulkanAndroid const *>(externalImage.get ());
352
+ ImageData data = allocateExternalImage (fvkExternalImage->aHardwareBuffer ,
353
+ device, VKALLOC, metadata);
214
354
VkResult result = vkBindImageMemory (device, data.first , data.second , 0 );
215
355
FILAMENT_CHECK_POSTCONDITION (result == VK_SUCCESS)
216
356
<< " vkBindImageMemory error=" << static_cast <int32_t >(result);
0 commit comments