• 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/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