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