• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkTypes.h"
9 
10 #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
11 #define GL_GLEXT_PROTOTYPES
12 #define EGL_EGLEXT_PROTOTYPES
13 
14 #include "src/gpu/ganesh/GrAHardwareBufferUtils_impl.h"
15 
16 #include <android/hardware_buffer.h>
17 #ifdef SK_GL
18 #include <EGL/egl.h>
19 #include <EGL/eglext.h>
20 #include <GLES/gl.h>
21 #include <GLES/glext.h>
22 #endif
23 
24 #include "include/gpu/GrDirectContext.h"
25 #include "src/gpu/ganesh/GrDirectContextPriv.h"
26 
27 #ifdef SK_GL
28 #include "include/gpu/gl/GrGLTypes.h"
29 #include "src/gpu/ganesh/gl/GrGLDefines_impl.h"
30 #include "src/gpu/ganesh/gl/GrGLUtil.h"
31 #endif
32 
33 #ifdef SK_VULKAN
34 #include "src/gpu/ganesh/vk/GrVkCaps.h"
35 #include "src/gpu/ganesh/vk/GrVkGpu.h"
36 #endif
37 
38 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
39 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
40 
41 #define VK_CALL(X) gpu->vkInterface()->fFunctions.f##X
42 
43 namespace GrAHardwareBufferUtils {
44 
GetSkColorTypeFromBufferFormat(uint32_t bufferFormat)45 SkColorType GetSkColorTypeFromBufferFormat(uint32_t bufferFormat) {
46     switch (bufferFormat) {
47         case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
48             return kRGBA_8888_SkColorType;
49         case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
50             return kRGB_888x_SkColorType;
51         case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
52             return kRGBA_F16_SkColorType;
53         case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
54             return kRGB_565_SkColorType;
55         case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
56             return kRGB_888x_SkColorType;
57         case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
58             return kRGBA_1010102_SkColorType;
59 #if __ANDROID_API__ >= 33
60         case AHARDWAREBUFFER_FORMAT_R8_UNORM:
61             return kAlpha_8_SkColorType;
62 #endif
63         default:
64             // Given that we only use this texture as a source, colorType will not impact how Skia
65             // uses the texture.  The only potential affect this is anticipated to have is that for
66             // some format types if we are not bound as an OES texture we may get invalid results
67             // for SKP capture if we read back the texture.
68             return kRGBA_8888_SkColorType;
69     }
70 }
71 
GetBackendFormat(GrDirectContext * dContext,AHardwareBuffer * hardwareBuffer,uint32_t bufferFormat,bool requireKnownFormat)72 GrBackendFormat GetBackendFormat(GrDirectContext* dContext, AHardwareBuffer* hardwareBuffer,
73                                  uint32_t bufferFormat, bool requireKnownFormat) {
74     GrBackendApi backend = dContext->backend();
75 
76     if (backend == GrBackendApi::kOpenGL) {
77 #ifdef SK_GL
78         switch (bufferFormat) {
79             //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
80             case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
81             case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
82                 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
83             case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
84                 return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
85             case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
86                 return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
87             case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
88                 return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
89             case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
90                 return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
91 #if __ANDROID_API__ >= 33
92             case AHARDWAREBUFFER_FORMAT_R8_UNORM:
93                 return GrBackendFormat::MakeGL(GR_GL_R8, GR_GL_TEXTURE_EXTERNAL);
94 #endif
95             default:
96                 if (requireKnownFormat) {
97                     return GrBackendFormat();
98                 } else {
99                     return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
100                 }
101         }
102 #else // SK_GL
103         return GrBackendFormat();
104 #endif // SK_GL
105     } else if (backend == GrBackendApi::kVulkan) {
106 #ifdef SK_VULKAN
107         switch (bufferFormat) {
108             case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
109                 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
110             case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
111                 return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT);
112             case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
113                 return GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16);
114             case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
115                 return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32);
116             case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
117                 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
118             case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
119                 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
120 #if __ANDROID_API__ >= 33
121             case AHARDWAREBUFFER_FORMAT_R8_UNORM:
122                 return GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM);
123 #endif
124             default: {
125                 if (requireKnownFormat) {
126                     return GrBackendFormat();
127                 } else {
128                     GrVkGpu* gpu = static_cast<GrVkGpu*>(dContext->priv().getGpu());
129                     SkASSERT(gpu);
130                     VkDevice device = gpu->device();
131 
132                     if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
133                         return GrBackendFormat();
134                     }
135                     VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
136                     hwbFormatProps.sType =
137                             VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
138                     hwbFormatProps.pNext = nullptr;
139 
140                     VkAndroidHardwareBufferPropertiesANDROID hwbProps;
141                     hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
142                     hwbProps.pNext = &hwbFormatProps;
143 
144                     VkResult err = VK_CALL(GetAndroidHardwareBufferProperties(device,
145                                                                               hardwareBuffer,
146                                                                               &hwbProps));
147                     if (VK_SUCCESS != err) {
148                         return GrBackendFormat();
149                     }
150 
151                     if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
152                         return GrBackendFormat();
153                     }
154 
155                     GrVkYcbcrConversionInfo ycbcrConversion;
156                     ycbcrConversion.fYcbcrModel = hwbFormatProps.suggestedYcbcrModel;
157                     ycbcrConversion.fYcbcrRange = hwbFormatProps.suggestedYcbcrRange;
158                     ycbcrConversion.fXChromaOffset = hwbFormatProps.suggestedXChromaOffset;
159                     ycbcrConversion.fYChromaOffset = hwbFormatProps.suggestedYChromaOffset;
160                     ycbcrConversion.fForceExplicitReconstruction = VK_FALSE;
161                     ycbcrConversion.fExternalFormat = hwbFormatProps.externalFormat;
162                     ycbcrConversion.fFormatFeatures = hwbFormatProps.formatFeatures;
163                     if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT &
164                         hwbFormatProps.formatFeatures) {
165                         ycbcrConversion.fChromaFilter = VK_FILTER_LINEAR;
166                     } else {
167                         ycbcrConversion.fChromaFilter = VK_FILTER_NEAREST;
168                     }
169 
170                     return GrBackendFormat::MakeVk(ycbcrConversion);
171                 }
172             }
173         }
174 #else // SK_VULKAN
175         return GrBackendFormat();
176 #endif // SK_VULKAN
177     }
178     return GrBackendFormat();
179 }
180 
181 #ifdef SK_GL
182 class GLTextureHelper {
183 public:
GLTextureHelper(GrGLuint texID,EGLImageKHR image,EGLDisplay display,GrGLuint texTarget)184     GLTextureHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display, GrGLuint texTarget)
185         : fTexID(texID)
186         , fImage(image)
187         , fDisplay(display)
188         , fTexTarget(texTarget) { }
~GLTextureHelper()189     ~GLTextureHelper() {
190         glDeleteTextures(1, &fTexID);
191         // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
192         eglDestroyImageKHR(fDisplay, fImage);
193     }
194     void rebind(GrDirectContext*);
195 
196 private:
197     GrGLuint    fTexID;
198     EGLImageKHR fImage;
199     EGLDisplay  fDisplay;
200     GrGLuint    fTexTarget;
201 };
202 
rebind(GrDirectContext * dContext)203 void GLTextureHelper::rebind(GrDirectContext* dContext) {
204     glBindTexture(fTexTarget, fTexID);
205     GLenum status = GL_NO_ERROR;
206     if ((status = glGetError()) != GL_NO_ERROR) {
207         SkDebugf("glBindTexture(%#x, %d) failed (%#x)", (int) fTexTarget,
208             (int) fTexID, (int) status);
209         return;
210     }
211     glEGLImageTargetTexture2DOES(fTexTarget, fImage);
212     if ((status = glGetError()) != GL_NO_ERROR) {
213         SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
214         return;
215     }
216     dContext->resetContext(kTextureBinding_GrGLBackendState);
217 }
218 
delete_gl_texture(void * context)219 void delete_gl_texture(void* context) {
220     GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
221     delete cleanupHelper;
222 }
223 
update_gl_texture(void * context,GrDirectContext * dContext)224 void update_gl_texture(void* context, GrDirectContext* dContext) {
225     GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
226     cleanupHelper->rebind(dContext);
227 }
228 
make_gl_backend_texture(GrDirectContext * dContext,AHardwareBuffer * hardwareBuffer,int width,int height,DeleteImageProc * deleteProc,UpdateImageProc * updateProc,TexImageCtx * imageCtx,bool isProtectedContent,const GrBackendFormat & backendFormat,bool isRenderable)229 static GrBackendTexture make_gl_backend_texture(
230         GrDirectContext* dContext,
231         AHardwareBuffer* hardwareBuffer,
232         int width, int height,
233         DeleteImageProc* deleteProc,
234         UpdateImageProc* updateProc,
235         TexImageCtx* imageCtx,
236         bool isProtectedContent,
237         const GrBackendFormat& backendFormat,
238         bool isRenderable) {
239     while (GL_NO_ERROR != glGetError()) {} //clear GL errors
240 
241     EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
242     EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
243                          isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
244                          isProtectedContent ? EGL_TRUE : EGL_NONE,
245                          EGL_NONE };
246     EGLDisplay display = eglGetCurrentDisplay();
247     // eglCreateImageKHR will add a ref to the AHardwareBuffer
248     EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
249                                           clientBuffer, attribs);
250     if (EGL_NO_IMAGE_KHR == image) {
251         SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
252         return GrBackendTexture();
253     }
254 
255     GrGLuint texID;
256     glGenTextures(1, &texID);
257     if (!texID) {
258         eglDestroyImageKHR(display, image);
259         return GrBackendTexture();
260     }
261 
262     GrGLuint target = isRenderable ? GR_GL_TEXTURE_2D : GR_GL_TEXTURE_EXTERNAL;
263 
264     glBindTexture(target, texID);
265     GLenum status = GL_NO_ERROR;
266     if ((status = glGetError()) != GL_NO_ERROR) {
267         SkDebugf("glBindTexture failed (%#x)", (int) status);
268         glDeleteTextures(1, &texID);
269         eglDestroyImageKHR(display, image);
270         return GrBackendTexture();
271     }
272     glEGLImageTargetTexture2DOES(target, image);
273     if ((status = glGetError()) != GL_NO_ERROR) {
274         SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
275         glDeleteTextures(1, &texID);
276         eglDestroyImageKHR(display, image);
277         return GrBackendTexture();
278     }
279     dContext->resetContext(kTextureBinding_GrGLBackendState);
280 
281     GrGLTextureInfo textureInfo;
282     textureInfo.fID = texID;
283     SkASSERT(backendFormat.isValid());
284     textureInfo.fTarget = target;
285     textureInfo.fFormat = GrGLFormatToEnum(backendFormat.asGLFormat());
286 
287     *deleteProc = delete_gl_texture;
288     *updateProc = update_gl_texture;
289     *imageCtx = new GLTextureHelper(texID, image, display, target);
290 
291     return GrBackendTexture(width, height, GrMipmapped::kNo, textureInfo);
292 }
293 #endif // SK_GL
294 
295 #ifdef SK_VULKAN
296 class VulkanCleanupHelper {
297 public:
VulkanCleanupHelper(GrVkGpu * gpu,VkImage image,VkDeviceMemory memory)298     VulkanCleanupHelper(GrVkGpu* gpu, VkImage image, VkDeviceMemory memory)
299         : fDevice(gpu->device())
300         , fImage(image)
301         , fMemory(memory)
302         , fDestroyImage(gpu->vkInterface()->fFunctions.fDestroyImage)
303         , fFreeMemory(gpu->vkInterface()->fFunctions.fFreeMemory) {}
~VulkanCleanupHelper()304     ~VulkanCleanupHelper() {
305         fDestroyImage(fDevice, fImage, nullptr);
306         fFreeMemory(fDevice, fMemory, nullptr);
307     }
308 private:
309     VkDevice           fDevice;
310     VkImage            fImage;
311     VkDeviceMemory     fMemory;
312     PFN_vkDestroyImage fDestroyImage;
313     PFN_vkFreeMemory   fFreeMemory;
314 };
315 
delete_vk_image(void * context)316 void delete_vk_image(void* context) {
317     VulkanCleanupHelper* cleanupHelper = static_cast<VulkanCleanupHelper*>(context);
318     delete cleanupHelper;
319 }
320 
update_vk_image(void * context,GrDirectContext * dContext)321 void update_vk_image(void* context, GrDirectContext* dContext) {
322     // no op
323 }
324 
make_vk_backend_texture(GrDirectContext * dContext,AHardwareBuffer * hardwareBuffer,int width,int height,DeleteImageProc * deleteProc,UpdateImageProc * updateProc,TexImageCtx * imageCtx,bool isProtectedContent,const GrBackendFormat & backendFormat,bool isRenderable,bool fromAndroidWindow)325 static GrBackendTexture make_vk_backend_texture(
326         GrDirectContext* dContext, AHardwareBuffer* hardwareBuffer,
327         int width, int height,
328         DeleteImageProc* deleteProc,
329         UpdateImageProc* updateProc,
330         TexImageCtx* imageCtx,
331         bool isProtectedContent,
332         const GrBackendFormat& backendFormat,
333         bool isRenderable,
334         bool fromAndroidWindow) {
335     SkASSERT(dContext->backend() == GrBackendApi::kVulkan);
336     GrVkGpu* gpu = static_cast<GrVkGpu*>(dContext->priv().getGpu());
337 
338     SkASSERT(!isProtectedContent || gpu->protectedContext());
339 
340     VkPhysicalDevice physicalDevice = gpu->physicalDevice();
341     VkDevice device = gpu->device();
342 
343     SkASSERT(gpu);
344 
345     if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
346         return GrBackendTexture();
347     }
348 
349     VkFormat format;
350     SkAssertResult(backendFormat.asVkFormat(&format));
351 
352     VkResult err;
353 
354     VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
355     hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
356     hwbFormatProps.pNext = nullptr;
357 
358     VkAndroidHardwareBufferPropertiesANDROID hwbProps;
359     hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
360     hwbProps.pNext = &hwbFormatProps;
361 
362     err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer, &hwbProps));
363     if (VK_SUCCESS != err) {
364         return GrBackendTexture();
365     }
366 
367     VkExternalFormatANDROID externalFormat;
368     externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
369     externalFormat.pNext = nullptr;
370     externalFormat.externalFormat = 0;  // If this is zero it is as if we aren't using this struct.
371 
372     const GrVkYcbcrConversionInfo* ycbcrConversion = backendFormat.getVkYcbcrConversionInfo();
373     if (!ycbcrConversion) {
374         return GrBackendTexture();
375     }
376 
377     if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
378         // TODO: We should not assume the transfer features here and instead should have a way for
379         // Ganesh's tracking of intenral images to report whether or not they support transfers.
380         SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
381                  SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
382                  SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
383         SkASSERT(!ycbcrConversion->isValid());
384     } else {
385         SkASSERT(ycbcrConversion->isValid());
386         // We have an external only format
387         SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures));
388         SkASSERT(format == VK_FORMAT_UNDEFINED);
389         SkASSERT(hwbFormatProps.externalFormat == ycbcrConversion->fExternalFormat);
390         externalFormat.externalFormat = hwbFormatProps.externalFormat;
391     }
392     SkASSERT(format == hwbFormatProps.format);
393 
394     const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
395             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,                 // sType
396             &externalFormat,                                                     // pNext
397             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,  // handleTypes
398     };
399     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
400     if (format != VK_FORMAT_UNDEFINED) {
401         usageFlags = usageFlags |
402                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
403                 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
404         if (isRenderable) {
405             usageFlags = usageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
406         }
407     }
408 
409     // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have
410     // to use linear. Add better linear support throughout Ganesh.
411     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
412 
413     VkImageCreateFlags flags = isProtectedContent ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
414 
415     const VkImageCreateInfo imageCreateInfo = {
416         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
417         &externalMemoryImageInfo,                    // pNext
418         flags,                                       // VkImageCreateFlags
419         VK_IMAGE_TYPE_2D,                            // VkImageType
420         format,                                      // VkFormat
421         { (uint32_t)width, (uint32_t)height, 1 },    // VkExtent3D
422         1,                                           // mipLevels
423         1,                                           // arrayLayers
424         VK_SAMPLE_COUNT_1_BIT,                       // samples
425         tiling,                                      // VkImageTiling
426         usageFlags,                                  // VkImageUsageFlags
427         VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
428         0,                                           // queueFamilyCount
429         nullptr,                                     // pQueueFamilyIndices
430         VK_IMAGE_LAYOUT_UNDEFINED,                   // initialLayout
431     };
432 
433     VkImage image;
434     err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image));
435     if (VK_SUCCESS != err) {
436         return GrBackendTexture();
437     }
438 
439     VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
440     phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
441     phyDevMemProps.pNext = nullptr;
442 
443     uint32_t typeIndex = 0;
444     bool foundHeap = false;
445     VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps));
446     uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
447     for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
448         if (hwbProps.memoryTypeBits & (1 << i)) {
449             const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
450             uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
451                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
452             if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
453                 typeIndex = i;
454                 foundHeap = true;
455             }
456         }
457     }
458     if (!foundHeap) {
459         VK_CALL(DestroyImage(device, image, nullptr));
460         return GrBackendTexture();
461     }
462 
463     VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
464     hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
465     hwbImportInfo.pNext = nullptr;
466     hwbImportInfo.buffer = hardwareBuffer;
467 
468     VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
469     dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
470     dedicatedAllocInfo.pNext = &hwbImportInfo;
471     dedicatedAllocInfo.image = image;
472     dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
473 
474     VkMemoryAllocateInfo allocInfo = {
475         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
476         &dedicatedAllocInfo,                         // pNext
477         hwbProps.allocationSize,                     // allocationSize
478         typeIndex,                                   // memoryTypeIndex
479     };
480 
481     VkDeviceMemory memory;
482 
483     err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory));
484     if (VK_SUCCESS != err) {
485         VK_CALL(DestroyImage(device, image, nullptr));
486         return GrBackendTexture();
487     }
488 
489     VkBindImageMemoryInfo bindImageInfo;
490     bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
491     bindImageInfo.pNext = nullptr;
492     bindImageInfo.image = image;
493     bindImageInfo.memory = memory;
494     bindImageInfo.memoryOffset = 0;
495 
496     err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo));
497     if (VK_SUCCESS != err) {
498         VK_CALL(DestroyImage(device, image, nullptr));
499         VK_CALL(FreeMemory(device, memory, nullptr));
500         return GrBackendTexture();
501     }
502 
503     skgpu::VulkanAlloc alloc;
504     alloc.fMemory = memory;
505     alloc.fOffset = 0;
506     alloc.fSize = hwbProps.allocationSize;
507     alloc.fFlags = 0;
508 
509     GrVkImageInfo imageInfo;
510     imageInfo.fImage = image;
511     imageInfo.fAlloc = alloc;
512     imageInfo.fImageTiling = tiling;
513     imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
514     imageInfo.fFormat = format;
515     imageInfo.fLevelCount = 1;
516     // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not
517     // support that extension. Or if we know the source of the AHardwareBuffer is not from a
518     // "foreign" device we can leave them as external.
519     imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
520     imageInfo.fProtected = isProtectedContent ? GrProtected::kYes : GrProtected::kNo;
521     imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
522     imageInfo.fSharingMode = imageCreateInfo.sharingMode;
523 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
524     imageInfo.fPartOfSwapchainOrAndroidWindow = fromAndroidWindow;
525 #endif
526 
527     *deleteProc = delete_vk_image;
528     *updateProc = update_vk_image;
529     *imageCtx = new VulkanCleanupHelper(gpu, image, memory);
530 
531     return GrBackendTexture(width, height, imageInfo);
532 }
533 #endif // SK_VULKAN
534 
535 #ifdef SK_GL
can_import_protected_content_eglimpl()536 static bool can_import_protected_content_eglimpl() {
537     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
538     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
539     size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
540     size_t extsLen = strlen(exts);
541     bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
542     bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
543     bool atEnd = (cropExtLen+1) < extsLen
544                   && !strcmp(" " PROT_CONTENT_EXT_STR,
545                   exts + extsLen - (cropExtLen+1));
546     bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
547     return equal || atStart || atEnd || inMiddle;
548 }
549 #endif // SK_GL
550 
can_import_protected_content(GrDirectContext * dContext)551 static bool can_import_protected_content(GrDirectContext* dContext) {
552     if (GrBackendApi::kOpenGL == dContext->backend()) {
553 #ifdef SK_GL
554         // Only compute whether the extension is present once the first time this
555         // function is called.
556         static bool hasIt = can_import_protected_content_eglimpl();
557         return hasIt;
558 #endif // SK_GL
559     } else if (GrBackendApi::kVulkan == dContext->backend()) {
560 #ifdef SK_VULKAN
561         return static_cast<GrVkGpu*>(dContext->priv().getGpu())->protectedContext();
562 #endif // SK_VULKAN
563     }
564     return false;
565 }
566 
MakeBackendTexture(GrDirectContext * dContext,AHardwareBuffer * hardwareBuffer,int width,int height,DeleteImageProc * deleteProc,UpdateImageProc * updateProc,TexImageCtx * imageCtx,bool isProtectedContent,const GrBackendFormat & backendFormat,bool isRenderable,bool fromAndroidWindow)567 GrBackendTexture MakeBackendTexture(GrDirectContext* dContext,
568                                     AHardwareBuffer* hardwareBuffer,
569                                     int width, int height,
570                                     DeleteImageProc* deleteProc,
571                                     UpdateImageProc* updateProc,
572                                     TexImageCtx* imageCtx,
573                                     bool isProtectedContent,
574                                     const GrBackendFormat& backendFormat,
575                                     bool isRenderable,
576                                     bool fromAndroidWindow) {
577     SkASSERT(dContext);
578     if (!dContext || dContext->abandoned()) {
579         return GrBackendTexture();
580     }
581     bool createProtectedImage = isProtectedContent && can_import_protected_content(dContext);
582 
583     if (GrBackendApi::kOpenGL == dContext->backend()) {
584 #ifdef SK_GL
585         return make_gl_backend_texture(dContext, hardwareBuffer, width, height, deleteProc,
586                                        updateProc, imageCtx, createProtectedImage, backendFormat,
587                                        isRenderable);
588 #else
589         return GrBackendTexture();
590 #endif // SK_GL
591     } else {
592         SkASSERT(GrBackendApi::kVulkan == dContext->backend());
593 #ifdef SK_VULKAN
594         return make_vk_backend_texture(dContext, hardwareBuffer, width, height, deleteProc,
595                                        updateProc, imageCtx, createProtectedImage, backendFormat,
596                                        isRenderable, fromAndroidWindow);
597 #else
598         return GrBackendTexture();
599 #endif // SK_VULKAN
600     }
601 }
602 
603 } // GrAHardwareBufferUtils
604 
605 #endif
606