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