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 "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 "GrAHardwareBufferUtils.h" 15 16 #include <android/hardware_buffer.h> 17 18 #include "GrContext.h" 19 #include "GrContextPriv.h" 20 #include "gl/GrGLDefines.h" 21 #include "gl/GrGLTypes.h" 22 23 #ifdef SK_VULKAN 24 #include "vk/GrVkCaps.h" 25 #include "vk/GrVkGpu.h" 26 #endif 27 28 #include <EGL/egl.h> 29 #include <EGL/eglext.h> 30 #include <GLES/gl.h> 31 #include <GLES/glext.h> 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 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 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.fExternalFormatFeatures = 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 GLCleanupHelper { 161 public: 162 GLCleanupHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display) 163 : fTexID(texID) 164 , fImage(image) 165 , fDisplay(display) { } 166 ~GLCleanupHelper() { 167 glDeleteTextures(1, &fTexID); 168 // eglDestroyImageKHR will remove a ref from the AHardwareBuffer 169 eglDestroyImageKHR(fDisplay, fImage); 170 } 171 private: 172 GrGLuint fTexID; 173 EGLImageKHR fImage; 174 EGLDisplay fDisplay; 175 }; 176 177 void delete_gl_texture(void* context) { 178 GLCleanupHelper* cleanupHelper = static_cast<GLCleanupHelper*>(context); 179 delete cleanupHelper; 180 } 181 182 static GrBackendTexture make_gl_backend_texture( 183 GrContext* context, AHardwareBuffer* hardwareBuffer, 184 int width, int height, 185 DeleteImageProc* deleteProc, 186 DeleteImageCtx* deleteCtx, 187 bool isProtectedContent, 188 const GrBackendFormat& backendFormat, 189 bool isRenderable) { 190 while (GL_NO_ERROR != glGetError()) {} //clear GL errors 191 192 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer); 193 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 194 isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE, 195 isProtectedContent ? EGL_TRUE : EGL_NONE, 196 EGL_NONE }; 197 EGLDisplay display = eglGetCurrentDisplay(); 198 // eglCreateImageKHR will add a ref to the AHardwareBuffer 199 EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, 200 clientBuffer, attribs); 201 if (EGL_NO_IMAGE_KHR == image) { 202 SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() ); 203 return GrBackendTexture(); 204 } 205 206 GrGLuint texID; 207 glGenTextures(1, &texID); 208 if (!texID) { 209 eglDestroyImageKHR(display, image); 210 return GrBackendTexture(); 211 } 212 213 GrGLuint target = isRenderable ? GR_GL_TEXTURE_2D : GR_GL_TEXTURE_EXTERNAL; 214 215 glBindTexture(target, texID); 216 GLenum status = GL_NO_ERROR; 217 if ((status = glGetError()) != GL_NO_ERROR) { 218 SkDebugf("glBindTexture failed (%#x)", (int) status); 219 glDeleteTextures(1, &texID); 220 eglDestroyImageKHR(display, image); 221 return GrBackendTexture(); 222 } 223 glEGLImageTargetTexture2DOES(target, image); 224 if ((status = glGetError()) != GL_NO_ERROR) { 225 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status); 226 glDeleteTextures(1, &texID); 227 eglDestroyImageKHR(display, image); 228 return GrBackendTexture(); 229 } 230 context->resetContext(kTextureBinding_GrGLBackendState); 231 232 GrGLTextureInfo textureInfo; 233 textureInfo.fID = texID; 234 SkASSERT(backendFormat.isValid()); 235 textureInfo.fTarget = target; 236 textureInfo.fFormat = *backendFormat.getGLFormat(); 237 238 *deleteProc = delete_gl_texture; 239 *deleteCtx = new GLCleanupHelper(texID, image, display); 240 241 return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo); 242 } 243 244 #ifdef SK_VULKAN 245 class VulkanCleanupHelper { 246 public: 247 VulkanCleanupHelper(GrVkGpu* gpu, VkImage image, VkDeviceMemory memory) 248 : fDevice(gpu->device()) 249 , fImage(image) 250 , fMemory(memory) 251 , fDestroyImage(gpu->vkInterface()->fFunctions.fDestroyImage) 252 , fFreeMemory(gpu->vkInterface()->fFunctions.fFreeMemory) {} 253 ~VulkanCleanupHelper() { 254 fDestroyImage(fDevice, fImage, nullptr); 255 fFreeMemory(fDevice, fMemory, nullptr); 256 } 257 private: 258 VkDevice fDevice; 259 VkImage fImage; 260 VkDeviceMemory fMemory; 261 PFN_vkDestroyImage fDestroyImage; 262 PFN_vkFreeMemory fFreeMemory; 263 }; 264 265 void delete_vk_image(void* context) { 266 VulkanCleanupHelper* cleanupHelper = static_cast<VulkanCleanupHelper*>(context); 267 delete cleanupHelper; 268 } 269 270 static GrBackendTexture make_vk_backend_texture( 271 GrContext* context, AHardwareBuffer* hardwareBuffer, 272 int width, int height, 273 DeleteImageProc* deleteProc, 274 DeleteImageCtx* deleteCtx, 275 bool isProtectedContent, 276 const GrBackendFormat& backendFormat, 277 bool isRenderable) { 278 SkASSERT(context->backend() == GrBackendApi::kVulkan); 279 GrVkGpu* gpu = static_cast<GrVkGpu*>(context->priv().getGpu()); 280 281 VkPhysicalDevice physicalDevice = gpu->physicalDevice(); 282 VkDevice device = gpu->device(); 283 284 SkASSERT(gpu); 285 286 if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) { 287 return GrBackendTexture(); 288 } 289 290 SkASSERT(backendFormat.getVkFormat()); 291 VkFormat format = *backendFormat.getVkFormat(); 292 293 VkResult err; 294 295 VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps; 296 hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; 297 hwbFormatProps.pNext = nullptr; 298 299 VkAndroidHardwareBufferPropertiesANDROID hwbProps; 300 hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; 301 hwbProps.pNext = &hwbFormatProps; 302 303 err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer, &hwbProps)); 304 if (VK_SUCCESS != err) { 305 return GrBackendTexture(); 306 } 307 308 VkExternalFormatANDROID externalFormat; 309 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; 310 externalFormat.pNext = nullptr; 311 externalFormat.externalFormat = 0; // If this is zero it is as if we aren't using this struct. 312 313 const GrVkYcbcrConversionInfo* ycbcrConversion = backendFormat.getVkYcbcrConversionInfo(); 314 if (!ycbcrConversion) { 315 return GrBackendTexture(); 316 } 317 318 if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) { 319 // TODO: We should not assume the transfer features here and instead should have a way for 320 // Ganesh's tracking of intenral images to report whether or not they support transfers. 321 SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) && 322 SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) && 323 SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures)); 324 SkASSERT(!ycbcrConversion->isValid()); 325 } else { 326 SkASSERT(ycbcrConversion->isValid()); 327 // We have an external only format 328 SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures)); 329 SkASSERT(format == VK_FORMAT_UNDEFINED); 330 SkASSERT(hwbFormatProps.externalFormat == ycbcrConversion->fExternalFormat); 331 externalFormat.externalFormat = hwbFormatProps.externalFormat; 332 } 333 SkASSERT(format == hwbFormatProps.format); 334 335 const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{ 336 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType 337 &externalFormat, // pNext 338 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes 339 }; 340 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; 341 if (format != VK_FORMAT_UNDEFINED) { 342 usageFlags = usageFlags | 343 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 344 VK_IMAGE_USAGE_TRANSFER_DST_BIT; 345 if (isRenderable) { 346 usageFlags = usageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 347 } 348 } 349 350 // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have 351 // to use linear. Add better linear support throughout Ganesh. 352 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; 353 354 const VkImageCreateInfo imageCreateInfo = { 355 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType 356 &externalMemoryImageInfo, // pNext 357 0, // VkImageCreateFlags 358 VK_IMAGE_TYPE_2D, // VkImageType 359 format, // VkFormat 360 { (uint32_t)width, (uint32_t)height, 1 }, // VkExtent3D 361 1, // mipLevels 362 1, // arrayLayers 363 VK_SAMPLE_COUNT_1_BIT, // samples 364 tiling, // VkImageTiling 365 usageFlags, // VkImageUsageFlags 366 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode 367 0, // queueFamilyCount 368 0, // pQueueFamilyIndices 369 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout 370 }; 371 372 VkImage image; 373 err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image)); 374 if (VK_SUCCESS != err) { 375 return GrBackendTexture(); 376 } 377 378 VkPhysicalDeviceMemoryProperties2 phyDevMemProps; 379 phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; 380 phyDevMemProps.pNext = nullptr; 381 382 uint32_t typeIndex = 0; 383 uint32_t heapIndex = 0; 384 bool foundHeap = false; 385 VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps)); 386 uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount; 387 for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) { 388 if (hwbProps.memoryTypeBits & (1 << i)) { 389 const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties; 390 uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags & 391 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 392 if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { 393 typeIndex = i; 394 heapIndex = pdmp.memoryTypes[i].heapIndex; 395 foundHeap = true; 396 } 397 } 398 } 399 if (!foundHeap) { 400 VK_CALL(DestroyImage(device, image, nullptr)); 401 return GrBackendTexture(); 402 } 403 404 VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo; 405 hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; 406 hwbImportInfo.pNext = nullptr; 407 hwbImportInfo.buffer = hardwareBuffer; 408 409 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo; 410 dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; 411 dedicatedAllocInfo.pNext = &hwbImportInfo; 412 dedicatedAllocInfo.image = image; 413 dedicatedAllocInfo.buffer = VK_NULL_HANDLE; 414 415 VkMemoryAllocateInfo allocInfo = { 416 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType 417 &dedicatedAllocInfo, // pNext 418 hwbProps.allocationSize, // allocationSize 419 typeIndex, // memoryTypeIndex 420 }; 421 422 VkDeviceMemory memory; 423 424 err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory)); 425 if (VK_SUCCESS != err) { 426 VK_CALL(DestroyImage(device, image, nullptr)); 427 return GrBackendTexture(); 428 } 429 430 VkBindImageMemoryInfo bindImageInfo; 431 bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; 432 bindImageInfo.pNext = nullptr; 433 bindImageInfo.image = image; 434 bindImageInfo.memory = memory; 435 bindImageInfo.memoryOffset = 0; 436 437 err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo)); 438 if (VK_SUCCESS != err) { 439 VK_CALL(DestroyImage(device, image, nullptr)); 440 VK_CALL(FreeMemory(device, memory, nullptr)); 441 return GrBackendTexture(); 442 } 443 444 GrVkImageInfo imageInfo; 445 446 imageInfo.fImage = image; 447 imageInfo.fAlloc = GrVkAlloc(memory, 0, hwbProps.allocationSize, 0); 448 imageInfo.fImageTiling = tiling; 449 imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; 450 imageInfo.fFormat = format; 451 imageInfo.fLevelCount = 1; 452 // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not 453 // support that extension. Or if we know the source of the AHardwareBuffer is not from a 454 // "foreign" device we can leave them as external. 455 imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL; 456 imageInfo.fYcbcrConversionInfo = *ycbcrConversion; 457 458 *deleteProc = delete_vk_image; 459 *deleteCtx = new VulkanCleanupHelper(gpu, image, memory); 460 461 return GrBackendTexture(width, height, imageInfo); 462 } 463 #endif 464 465 static bool can_import_protected_content_eglimpl() { 466 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 467 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); 468 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR); 469 size_t extsLen = strlen(exts); 470 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts); 471 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1); 472 bool atEnd = (cropExtLen+1) < extsLen 473 && !strcmp(" " PROT_CONTENT_EXT_STR, 474 exts + extsLen - (cropExtLen+1)); 475 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " "); 476 return equal || atStart || atEnd || inMiddle; 477 } 478 479 static bool can_import_protected_content(GrContext* context) { 480 if (GrBackendApi::kOpenGL == context->backend()) { 481 // Only compute whether the extension is present once the first time this 482 // function is called. 483 static bool hasIt = can_import_protected_content_eglimpl(); 484 return hasIt; 485 } 486 return false; 487 } 488 489 GrBackendTexture MakeBackendTexture(GrContext* context, AHardwareBuffer* hardwareBuffer, 490 int width, int height, 491 DeleteImageProc* deleteProc, 492 DeleteImageCtx* deleteCtx, 493 bool isProtectedContent, 494 const GrBackendFormat& backendFormat, 495 bool isRenderable) { 496 if (context->abandoned()) { 497 return GrBackendTexture(); 498 } 499 bool createProtectedImage = isProtectedContent && can_import_protected_content(context); 500 501 if (GrBackendApi::kOpenGL == context->backend()) { 502 return make_gl_backend_texture(context, hardwareBuffer, width, height, deleteProc, 503 deleteCtx, createProtectedImage, backendFormat, 504 isRenderable); 505 } else { 506 SkASSERT(GrBackendApi::kVulkan == context->backend()); 507 #ifdef SK_VULKAN 508 // Currently we don't support protected images on vulkan 509 SkASSERT(!createProtectedImage); 510 return make_vk_backend_texture(context, hardwareBuffer, width, height, deleteProc, 511 deleteCtx, createProtectedImage, backendFormat, 512 isRenderable); 513 #else 514 return GrBackendTexture(); 515 #endif 516 } 517 } 518 519 } // GrAHardwareBufferUtils 520 521 #endif 522 523