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/GrContext.h"
23 #include "include/gpu/gl/GrGLTypes.h"
24 #include "src/gpu/GrContextPriv.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(GrContext * context,AHardwareBuffer * hardwareBuffer,uint32_t bufferFormat,bool requireKnownFormat)63 GrBackendFormat GetBackendFormat(GrContext* context, AHardwareBuffer* hardwareBuffer,
64                                  uint32_t bufferFormat, bool requireKnownFormat) {
65     GrBackendApi backend = context->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*>(context->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(GrContext* grContext);
173 
174 private:
175     GrGLuint    fTexID;
176     EGLImageKHR fImage;
177     EGLDisplay  fDisplay;
178     GrGLuint    fTexTarget;
179 };
180 
rebind(GrContext * grContext)181 void GLTextureHelper::rebind(GrContext* grContext) {
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     grContext->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,GrContext * grContext)202 void update_gl_texture(void* context, GrContext* grContext) {
203     GLTextureHelper* cleanupHelper = static_cast<GLTextureHelper*>(context);
204     cleanupHelper->rebind(grContext);
205 }
206 
make_gl_backend_texture(GrContext * context,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         GrContext* context, 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     context->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,GrContext * grContext)297 void update_vk_image(void* context, GrContext* grContext) {
298     // no op
299 }
300 
make_vk_backend_texture(GrContext * context,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         GrContext* context, 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(context->backend() == GrBackendApi::kVulkan);
311     GrVkGpu* gpu = static_cast<GrVkGpu*>(context->priv().getGpu());
312 
313     VkPhysicalDevice physicalDevice = gpu->physicalDevice();
314     VkDevice device = gpu->device();
315 
316     SkASSERT(gpu);
317 
318     if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
319         return GrBackendTexture();
320     }
321 
322     VkFormat format;
323     SkAssertResult(backendFormat.asVkFormat(&format));
324 
325     VkResult err;
326 
327     VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
328     hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
329     hwbFormatProps.pNext = nullptr;
330 
331     VkAndroidHardwareBufferPropertiesANDROID hwbProps;
332     hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
333     hwbProps.pNext = &hwbFormatProps;
334 
335     err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer, &hwbProps));
336     if (VK_SUCCESS != err) {
337         return GrBackendTexture();
338     }
339 
340     VkExternalFormatANDROID externalFormat;
341     externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
342     externalFormat.pNext = nullptr;
343     externalFormat.externalFormat = 0;  // If this is zero it is as if we aren't using this struct.
344 
345     const GrVkYcbcrConversionInfo* ycbcrConversion = backendFormat.getVkYcbcrConversionInfo();
346     if (!ycbcrConversion) {
347         return GrBackendTexture();
348     }
349 
350     if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
351         // TODO: We should not assume the transfer features here and instead should have a way for
352         // Ganesh's tracking of intenral images to report whether or not they support transfers.
353         SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
354                  SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
355                  SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
356         SkASSERT(!ycbcrConversion->isValid());
357     } else {
358         SkASSERT(ycbcrConversion->isValid());
359         // We have an external only format
360         SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures));
361         SkASSERT(format == VK_FORMAT_UNDEFINED);
362         SkASSERT(hwbFormatProps.externalFormat == ycbcrConversion->fExternalFormat);
363         externalFormat.externalFormat = hwbFormatProps.externalFormat;
364     }
365     SkASSERT(format == hwbFormatProps.format);
366 
367     const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
368             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,                 // sType
369             &externalFormat,                                                     // pNext
370             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,  // handleTypes
371     };
372     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
373     if (format != VK_FORMAT_UNDEFINED) {
374         usageFlags = usageFlags |
375                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
376                 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
377         if (isRenderable) {
378             usageFlags = usageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
379         }
380     }
381 
382     // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have
383     // to use linear. Add better linear support throughout Ganesh.
384     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
385 
386     const VkImageCreateInfo imageCreateInfo = {
387         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
388         &externalMemoryImageInfo,                    // pNext
389         0,                                           // VkImageCreateFlags
390         VK_IMAGE_TYPE_2D,                            // VkImageType
391         format,                                      // VkFormat
392         { (uint32_t)width, (uint32_t)height, 1 },    // VkExtent3D
393         1,                                           // mipLevels
394         1,                                           // arrayLayers
395         VK_SAMPLE_COUNT_1_BIT,                       // samples
396         tiling,                                      // VkImageTiling
397         usageFlags,                                  // VkImageUsageFlags
398         VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
399         0,                                           // queueFamilyCount
400         0,                                           // pQueueFamilyIndices
401         VK_IMAGE_LAYOUT_UNDEFINED,                   // initialLayout
402     };
403 
404     VkImage image;
405     err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image));
406     if (VK_SUCCESS != err) {
407         return GrBackendTexture();
408     }
409 
410     VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
411     phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
412     phyDevMemProps.pNext = nullptr;
413 
414     uint32_t typeIndex = 0;
415     uint32_t heapIndex = 0;
416     bool foundHeap = false;
417     VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps));
418     uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
419     for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
420         if (hwbProps.memoryTypeBits & (1 << i)) {
421             const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
422             uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
423                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
424             if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
425                 typeIndex = i;
426                 heapIndex = pdmp.memoryTypes[i].heapIndex;
427                 foundHeap = true;
428             }
429         }
430     }
431     if (!foundHeap) {
432         VK_CALL(DestroyImage(device, image, nullptr));
433         return GrBackendTexture();
434     }
435 
436     VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
437     hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
438     hwbImportInfo.pNext = nullptr;
439     hwbImportInfo.buffer = hardwareBuffer;
440 
441     VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
442     dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
443     dedicatedAllocInfo.pNext = &hwbImportInfo;
444     dedicatedAllocInfo.image = image;
445     dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
446 
447     VkMemoryAllocateInfo allocInfo = {
448         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
449         &dedicatedAllocInfo,                         // pNext
450         hwbProps.allocationSize,                     // allocationSize
451         typeIndex,                                   // memoryTypeIndex
452     };
453 
454     VkDeviceMemory memory;
455 
456     err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory));
457     if (VK_SUCCESS != err) {
458         VK_CALL(DestroyImage(device, image, nullptr));
459         return GrBackendTexture();
460     }
461 
462     VkBindImageMemoryInfo bindImageInfo;
463     bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
464     bindImageInfo.pNext = nullptr;
465     bindImageInfo.image = image;
466     bindImageInfo.memory = memory;
467     bindImageInfo.memoryOffset = 0;
468 
469     err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo));
470     if (VK_SUCCESS != err) {
471         VK_CALL(DestroyImage(device, image, nullptr));
472         VK_CALL(FreeMemory(device, memory, nullptr));
473         return GrBackendTexture();
474     }
475 
476     GrVkImageInfo imageInfo;
477 
478     imageInfo.fImage = image;
479     imageInfo.fAlloc = GrVkAlloc(memory, 0, hwbProps.allocationSize, 0);
480     imageInfo.fImageTiling = tiling;
481     imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
482     imageInfo.fFormat = format;
483     imageInfo.fLevelCount = 1;
484     // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not
485     // support that extension. Or if we know the source of the AHardwareBuffer is not from a
486     // "foreign" device we can leave them as external.
487     imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
488     imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
489 
490     *deleteProc = delete_vk_image;
491     *updateProc = update_vk_image;
492     *imageCtx = new VulkanCleanupHelper(gpu, image, memory);
493 
494     return GrBackendTexture(width, height, imageInfo);
495 }
496 #endif
497 
can_import_protected_content_eglimpl()498 static bool can_import_protected_content_eglimpl() {
499     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
500     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
501     size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
502     size_t extsLen = strlen(exts);
503     bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
504     bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
505     bool atEnd = (cropExtLen+1) < extsLen
506                   && !strcmp(" " PROT_CONTENT_EXT_STR,
507                   exts + extsLen - (cropExtLen+1));
508     bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
509     return equal || atStart || atEnd || inMiddle;
510 }
511 
can_import_protected_content(GrContext * context)512 static bool can_import_protected_content(GrContext* context) {
513     if (GrBackendApi::kOpenGL == context->backend()) {
514         // Only compute whether the extension is present once the first time this
515         // function is called.
516         static bool hasIt = can_import_protected_content_eglimpl();
517         return hasIt;
518     }
519     return false;
520 }
521 
MakeBackendTexture(GrContext * context,AHardwareBuffer * hardwareBuffer,int width,int height,DeleteImageProc * deleteProc,UpdateImageProc * updateProc,TexImageCtx * imageCtx,bool isProtectedContent,const GrBackendFormat & backendFormat,bool isRenderable)522 GrBackendTexture MakeBackendTexture(GrContext* context, AHardwareBuffer* hardwareBuffer,
523                                     int width, int height,
524                                     DeleteImageProc* deleteProc,
525                                     UpdateImageProc* updateProc,
526                                     TexImageCtx* imageCtx,
527                                     bool isProtectedContent,
528                                     const GrBackendFormat& backendFormat,
529                                     bool isRenderable) {
530     if (context->abandoned()) {
531         return GrBackendTexture();
532     }
533     bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
534 
535     if (GrBackendApi::kOpenGL == context->backend()) {
536         return make_gl_backend_texture(context, hardwareBuffer, width, height, deleteProc,
537                                        updateProc, imageCtx, createProtectedImage, backendFormat,
538                                        isRenderable);
539     } else {
540         SkASSERT(GrBackendApi::kVulkan == context->backend());
541 #ifdef SK_VULKAN
542         // Currently we don't support protected images on vulkan
543         SkASSERT(!createProtectedImage);
544         return make_vk_backend_texture(context, hardwareBuffer, width, height, deleteProc,
545                                        updateProc, imageCtx, createProtectedImage, backendFormat,
546                                        isRenderable);
547 #else
548         return GrBackendTexture();
549 #endif
550     }
551 }
552 
553 } // GrAHardwareBufferUtils
554 
555 #endif
556 
557