Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2017 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 
     15 #include "GrAHardwareBufferImageGenerator.h"
     16 
     17 #include <android/hardware_buffer.h>
     18 
     19 #include "GrBackendSurface.h"
     20 #include "GrContext.h"
     21 #include "GrContextPriv.h"
     22 #include "GrProxyProvider.h"
     23 #include "GrResourceCache.h"
     24 #include "GrResourceProvider.h"
     25 #include "GrResourceProviderPriv.h"
     26 #include "GrTexture.h"
     27 #include "GrTextureProxy.h"
     28 #include "SkMessageBus.h"
     29 #include "gl/GrGLDefines.h"
     30 #include "gl/GrGLTypes.h"
     31 
     32 #include <EGL/egl.h>
     33 #include <EGL/eglext.h>
     34 #include <GLES/gl.h>
     35 #include <GLES/glext.h>
     36 
     37 #ifdef SK_VULKAN
     38 #include "vk/GrVkExtensions.h"
     39 #include "vk/GrVkGpu.h"
     40 #endif
     41 
     42 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
     43 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
     44 
     45 static bool can_import_protected_content_eglimpl() {
     46     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     47     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
     48     size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
     49     size_t extsLen = strlen(exts);
     50     bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
     51     bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
     52     bool atEnd = (cropExtLen+1) < extsLen
     53                   && !strcmp(" " PROT_CONTENT_EXT_STR,
     54                   exts + extsLen - (cropExtLen+1));
     55     bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
     56     return equal || atStart || atEnd || inMiddle;
     57 }
     58 
     59 static bool can_import_protected_content(GrContext* context) {
     60     if (GrBackendApi::kOpenGL == context->backend()) {
     61         // Only compute whether the extension is present once the first time this
     62         // function is called.
     63         static bool hasIt = can_import_protected_content_eglimpl();
     64         return hasIt;
     65     }
     66     return false;
     67 }
     68 
     69 std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
     70         AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
     71         GrSurfaceOrigin surfaceOrigin) {
     72     AHardwareBuffer_Desc bufferDesc;
     73     AHardwareBuffer_describe(graphicBuffer, &bufferDesc);
     74     SkColorType colorType;
     75     switch (bufferDesc.format) {
     76     case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
     77     case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
     78         colorType = kRGBA_8888_SkColorType;
     79         break;
     80     case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
     81         colorType = kRGBA_F16_SkColorType;
     82         break;
     83     case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
     84         colorType = kRGB_565_SkColorType;
     85         break;
     86     case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
     87         colorType = kRGB_888x_SkColorType;
     88         break;
     89     case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
     90         colorType = kRGBA_1010102_SkColorType;
     91         break;
     92     default:
     93         // Given that we only use this texture as a source, colorType will not impact how Skia uses
     94         // the texture.  The only potential affect this is anticipated to have is that for some
     95         // format types if we are not bound as an OES texture we may get invalid results for SKP
     96         // capture if we read back the texture.
     97         colorType = kRGBA_8888_SkColorType;
     98         break;
     99     }
    100     SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
    101                                          alphaType, std::move(colorSpace));
    102     bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
    103     return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(
    104             info, graphicBuffer, alphaType, createProtectedImage,
    105             bufferDesc.format, surfaceOrigin));
    106 }
    107 
    108 GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
    109         AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent,
    110         uint32_t bufferFormat, GrSurfaceOrigin surfaceOrigin)
    111     : INHERITED(info)
    112     , fHardwareBuffer(hardwareBuffer)
    113     , fBufferFormat(bufferFormat)
    114     , fIsProtectedContent(isProtectedContent)
    115     , fSurfaceOrigin(surfaceOrigin) {
    116     AHardwareBuffer_acquire(fHardwareBuffer);
    117 }
    118 
    119 GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
    120     AHardwareBuffer_release(fHardwareBuffer);
    121 }
    122 
    123 ///////////////////////////////////////////////////////////////////////////////////////////////////
    124 
    125 #ifdef SK_VULKAN
    126 
    127 class VulkanCleanupHelper {
    128 public:
    129     VulkanCleanupHelper(GrVkGpu* gpu, VkImage image, VkDeviceMemory memory)
    130         : fDevice(gpu->device())
    131         , fImage(image)
    132         , fMemory(memory)
    133         , fDestroyImage(gpu->vkInterface()->fFunctions.fDestroyImage)
    134         , fFreeMemory(gpu->vkInterface()->fFunctions.fFreeMemory) {}
    135     ~VulkanCleanupHelper() {
    136         fDestroyImage(fDevice, fImage, nullptr);
    137         fFreeMemory(fDevice, fMemory, nullptr);
    138     }
    139 private:
    140     VkDevice           fDevice;
    141     VkImage            fImage;
    142     VkDeviceMemory     fMemory;
    143     PFN_vkDestroyImage fDestroyImage;
    144     PFN_vkFreeMemory   fFreeMemory;
    145 };
    146 
    147 void GrAHardwareBufferImageGenerator::DeleteVkImage(void* context) {
    148     VulkanCleanupHelper* cleanupHelper = static_cast<VulkanCleanupHelper*>(context);
    149     delete cleanupHelper;
    150 }
    151 
    152 #define VK_CALL(X) gpu->vkInterface()->fFunctions.f##X;
    153 
    154 static GrBackendTexture make_vk_backend_texture(
    155         GrContext* context, AHardwareBuffer* hardwareBuffer,
    156         int width, int height, GrPixelConfig config,
    157         GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
    158         GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
    159         bool isProtectedContent,
    160         const GrBackendFormat& backendFormat) {
    161     SkASSERT(context->backend() == GrBackendApi::kVulkan);
    162     GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());
    163 
    164     VkPhysicalDevice physicalDevice = gpu->physicalDevice();
    165     VkDevice device = gpu->device();
    166 
    167     SkASSERT(gpu);
    168 
    169     if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
    170         return GrBackendTexture();
    171     }
    172 
    173     SkASSERT(backendFormat.getVkFormat());
    174     VkFormat format = *backendFormat.getVkFormat();
    175 
    176     VkResult err;
    177 
    178     VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
    179     hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
    180     hwbFormatProps.pNext = nullptr;
    181 
    182     VkAndroidHardwareBufferPropertiesANDROID hwbProps;
    183     hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
    184     hwbProps.pNext = &hwbFormatProps;
    185 
    186     err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer, &hwbProps));
    187     if (VK_SUCCESS != err) {
    188         return GrBackendTexture();
    189     }
    190 
    191     VkExternalFormatANDROID externalFormat;
    192     externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
    193     externalFormat.pNext = nullptr;
    194     externalFormat.externalFormat = 0;  // If this is zero it is as if we aren't using this struct.
    195 
    196     const GrVkYcbcrConversionInfo* ycbcrConversion = backendFormat.getVkYcbcrConversionInfo();
    197     if (!ycbcrConversion) {
    198         return GrBackendTexture();
    199     }
    200 
    201     if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
    202         // TODO: We should not assume the transfer features here and instead should have a way for
    203         // Ganesh's tracking of intenral images to report whether or not they support transfers.
    204         SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
    205                  SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
    206                  SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
    207         SkASSERT(!ycbcrConversion->isValid());
    208     } else {
    209         SkASSERT(ycbcrConversion->isValid());
    210         // We have an external only format
    211         SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures));
    212         SkASSERT(format == VK_FORMAT_UNDEFINED);
    213         SkASSERT(hwbFormatProps.externalFormat == ycbcrConversion->fExternalFormat);
    214         externalFormat.externalFormat = hwbFormatProps.externalFormat;
    215     }
    216     SkASSERT(format == hwbFormatProps.format);
    217 
    218     const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
    219             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,                 // sType
    220             &externalFormat,                                                     // pNext
    221             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,  // handleTypes
    222     };
    223     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    224     if (format != VK_FORMAT_UNDEFINED) {
    225         usageFlags = usageFlags |
    226                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
    227                 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    228     }
    229 
    230     // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have
    231     // to use linear. Add better linear support throughout Ganesh.
    232     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
    233 
    234     const VkImageCreateInfo imageCreateInfo = {
    235         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
    236         &externalMemoryImageInfo,                    // pNext
    237         0,                                           // VkImageCreateFlags
    238         VK_IMAGE_TYPE_2D,                            // VkImageType
    239         format,                                      // VkFormat
    240         { (uint32_t)width, (uint32_t)height, 1 },    // VkExtent3D
    241         1,                                           // mipLevels
    242         1,                                           // arrayLayers
    243         VK_SAMPLE_COUNT_1_BIT,                       // samples
    244         tiling,                                      // VkImageTiling
    245         usageFlags,                                  // VkImageUsageFlags
    246         VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
    247         0,                                           // queueFamilyCount
    248         0,                                           // pQueueFamilyIndices
    249         VK_IMAGE_LAYOUT_UNDEFINED,                   // initialLayout
    250     };
    251 
    252     VkImage image;
    253     err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image));
    254     if (VK_SUCCESS != err) {
    255         return GrBackendTexture();
    256     }
    257 
    258     VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
    259     phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
    260     phyDevMemProps.pNext = nullptr;
    261 
    262     uint32_t typeIndex = 0;
    263     uint32_t heapIndex = 0;
    264     bool foundHeap = false;
    265     VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps));
    266     uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
    267     for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
    268         if (hwbProps.memoryTypeBits & (1 << i)) {
    269             const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
    270             uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
    271                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
    272             if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
    273                 typeIndex = i;
    274                 heapIndex = pdmp.memoryTypes[i].heapIndex;
    275                 foundHeap = true;
    276             }
    277         }
    278     }
    279     if (!foundHeap) {
    280         VK_CALL(DestroyImage(device, image, nullptr));
    281         return GrBackendTexture();
    282     }
    283 
    284     VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
    285     hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
    286     hwbImportInfo.pNext = nullptr;
    287     hwbImportInfo.buffer = hardwareBuffer;
    288 
    289     VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
    290     dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
    291     dedicatedAllocInfo.pNext = &hwbImportInfo;
    292     dedicatedAllocInfo.image = image;
    293     dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
    294 
    295     VkMemoryAllocateInfo allocInfo = {
    296         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
    297         &dedicatedAllocInfo,                         // pNext
    298         hwbProps.allocationSize,                     // allocationSize
    299         typeIndex,                                   // memoryTypeIndex
    300     };
    301 
    302     VkDeviceMemory memory;
    303 
    304     err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory));
    305     if (VK_SUCCESS != err) {
    306         VK_CALL(DestroyImage(device, image, nullptr));
    307         return GrBackendTexture();
    308     }
    309 
    310     VkBindImageMemoryInfo bindImageInfo;
    311     bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
    312     bindImageInfo.pNext = nullptr;
    313     bindImageInfo.image = image;
    314     bindImageInfo.memory = memory;
    315     bindImageInfo.memoryOffset = 0;
    316 
    317     err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo));
    318     if (VK_SUCCESS != err) {
    319         VK_CALL(DestroyImage(device, image, nullptr));
    320         VK_CALL(FreeMemory(device, memory, nullptr));
    321         return GrBackendTexture();
    322     }
    323 
    324     GrVkImageInfo imageInfo;
    325 
    326     imageInfo.fImage = image;
    327     imageInfo.fAlloc = GrVkAlloc(memory, 0, hwbProps.allocationSize, 0);
    328     imageInfo.fImageTiling = tiling;
    329     imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    330     imageInfo.fFormat = format;
    331     imageInfo.fLevelCount = 1;
    332     // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not
    333     // support that extension. Or if we know the source of the AHardwareBuffer is not from a
    334     // "foreign" device we can leave them as external.
    335     imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
    336     imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
    337 
    338     *deleteProc = GrAHardwareBufferImageGenerator::DeleteVkImage;
    339     *deleteCtx = new VulkanCleanupHelper(gpu, image, memory);
    340 
    341     return GrBackendTexture(width, height, imageInfo);
    342 }
    343 #endif
    344 
    345 class GLCleanupHelper {
    346 public:
    347     GLCleanupHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display)
    348         : fTexID(texID)
    349         , fImage(image)
    350         , fDisplay(display) { }
    351     ~GLCleanupHelper() {
    352         glDeleteTextures(1, &fTexID);
    353         // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
    354         eglDestroyImageKHR(fDisplay, fImage);
    355     }
    356 private:
    357     GrGLuint    fTexID;
    358     EGLImageKHR fImage;
    359     EGLDisplay  fDisplay;
    360 };
    361 
    362 void GrAHardwareBufferImageGenerator::DeleteGLTexture(void* context) {
    363     GLCleanupHelper* cleanupHelper = static_cast<GLCleanupHelper*>(context);
    364     delete cleanupHelper;
    365 }
    366 
    367 static GrBackendTexture make_gl_backend_texture(
    368         GrContext* context, AHardwareBuffer* hardwareBuffer,
    369         int width, int height, GrPixelConfig config,
    370         GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
    371         GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
    372         bool isProtectedContent,
    373         const GrBackendFormat& backendFormat) {
    374     while (GL_NO_ERROR != glGetError()) {} //clear GL errors
    375 
    376     EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
    377     EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
    378                          isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
    379                          isProtectedContent ? EGL_TRUE : EGL_NONE,
    380                          EGL_NONE };
    381     EGLDisplay display = eglGetCurrentDisplay();
    382     // eglCreateImageKHR will add a ref to the AHardwareBuffer
    383     EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
    384                                           clientBuffer, attribs);
    385     if (EGL_NO_IMAGE_KHR == image) {
    386         SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
    387         return GrBackendTexture();
    388     }
    389 
    390     GrGLuint texID;
    391     glGenTextures(1, &texID);
    392     if (!texID) {
    393         eglDestroyImageKHR(display, image);
    394         return GrBackendTexture();
    395     }
    396     glBindTexture(GL_TEXTURE_EXTERNAL_OES, texID);
    397     GLenum status = GL_NO_ERROR;
    398     if ((status = glGetError()) != GL_NO_ERROR) {
    399         SkDebugf("glBindTexture failed (%#x)", (int) status);
    400         glDeleteTextures(1, &texID);
    401         eglDestroyImageKHR(display, image);
    402         return GrBackendTexture();
    403     }
    404     glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
    405     if ((status = glGetError()) != GL_NO_ERROR) {
    406         SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
    407         glDeleteTextures(1, &texID);
    408         eglDestroyImageKHR(display, image);
    409         return GrBackendTexture();
    410     }
    411     context->resetContext(kTextureBinding_GrGLBackendState);
    412 
    413     GrGLTextureInfo textureInfo;
    414     textureInfo.fID = texID;
    415     SkASSERT(backendFormat.isValid());
    416     textureInfo.fTarget = *backendFormat.getGLTarget();
    417     textureInfo.fFormat = *backendFormat.getGLFormat();
    418 
    419     *deleteProc = GrAHardwareBufferImageGenerator::DeleteGLTexture;
    420     *deleteCtx = new GLCleanupHelper(texID, image, display);
    421 
    422     return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo);
    423 }
    424 
    425 static GrBackendTexture make_backend_texture(
    426         GrContext* context, AHardwareBuffer* hardwareBuffer,
    427         int width, int height, GrPixelConfig config,
    428         GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
    429         GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
    430         bool isProtectedContent,
    431         const GrBackendFormat& backendFormat) {
    432     if (context->abandoned()) {
    433         return GrBackendTexture();
    434     }
    435     bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
    436 
    437     if (GrBackendApi::kOpenGL == context->backend()) {
    438         return make_gl_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
    439                                        deleteCtx, createProtectedImage, backendFormat);
    440     } else {
    441         SkASSERT(GrBackendApi::kVulkan == context->backend());
    442 #ifdef SK_VULKAN
    443         // Currently we don't support protected images on vulkan
    444         SkASSERT(!createProtectedImage);
    445         return make_vk_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
    446                                        deleteCtx, createProtectedImage, backendFormat);
    447 #else
    448         return GrBackendTexture();
    449 #endif
    450     }
    451 }
    452 
    453 GrBackendFormat get_backend_format(GrContext* context, AHardwareBuffer* hardwareBuffer,
    454                                    GrBackendApi backend, uint32_t bufferFormat) {
    455     if (backend == GrBackendApi::kOpenGL) {
    456         switch (bufferFormat) {
    457             //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
    458             case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
    459             case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
    460                 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
    461             case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
    462                 return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
    463             case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
    464                 return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
    465             case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
    466                 return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
    467             case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
    468                 return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
    469             default:
    470                 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
    471         }
    472     } else if (backend == GrBackendApi::kVulkan) {
    473 #ifdef SK_VULKAN
    474         switch (bufferFormat) {
    475             case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
    476                 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
    477             case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
    478                 return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT);
    479             case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
    480                 return GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16);
    481             case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
    482                 return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32);
    483             case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
    484                 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
    485             case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
    486                 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
    487             default: {
    488                 GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());
    489                 SkASSERT(gpu);
    490                 VkDevice device = gpu->device();
    491 
    492                 if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
    493                     return GrBackendFormat();
    494                 }
    495                 VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
    496                 hwbFormatProps.sType =
    497                         VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
    498                 hwbFormatProps.pNext = nullptr;
    499 
    500                 VkAndroidHardwareBufferPropertiesANDROID hwbProps;
    501                 hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
    502                 hwbProps.pNext = &hwbFormatProps;
    503 
    504                 VkResult err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer,
    505                                                                           &hwbProps));
    506                 if (VK_SUCCESS != err) {
    507                     return GrBackendFormat();
    508                 }
    509 
    510                 if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
    511                     return GrBackendFormat();
    512                 }
    513 
    514                 GrVkYcbcrConversionInfo ycbcrConversion;
    515                 ycbcrConversion.fYcbcrModel = hwbFormatProps.suggestedYcbcrModel;
    516                 ycbcrConversion.fYcbcrRange = hwbFormatProps.suggestedYcbcrRange;
    517                 ycbcrConversion.fXChromaOffset = hwbFormatProps.suggestedXChromaOffset;
    518                 ycbcrConversion.fYChromaOffset = hwbFormatProps.suggestedYChromaOffset;
    519                 ycbcrConversion.fForceExplicitReconstruction = VK_FALSE;
    520                 ycbcrConversion.fExternalFormat = hwbFormatProps.externalFormat;
    521                 ycbcrConversion.fExternalFormatFeatures = hwbFormatProps.formatFeatures;
    522                 if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT &
    523                     hwbFormatProps.formatFeatures) {
    524                     ycbcrConversion.fChromaFilter = VK_FILTER_LINEAR;
    525                 } else {
    526                     ycbcrConversion.fChromaFilter = VK_FILTER_NEAREST;
    527                 }
    528 
    529                 return GrBackendFormat::MakeVk(ycbcrConversion);
    530             }
    531         }
    532 #else
    533         return GrBackendFormat();
    534 #endif
    535     }
    536     return GrBackendFormat();
    537 }
    538 
    539 sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
    540     if (context->abandoned()) {
    541         return nullptr;
    542     }
    543 
    544     GrBackendFormat backendFormat = get_backend_format(context, fHardwareBuffer,
    545                                                        context->backend(),
    546                                                        fBufferFormat);
    547     GrPixelConfig pixelConfig = context->contextPriv().caps()->getConfigFromBackendFormat(
    548             backendFormat, this->getInfo().colorType());
    549 
    550     if (pixelConfig == kUnknown_GrPixelConfig) {
    551         return nullptr;
    552     }
    553 
    554     int width = this->getInfo().width();
    555     int height = this->getInfo().height();
    556 
    557     GrSurfaceDesc desc;
    558     desc.fWidth = width;
    559     desc.fHeight = height;
    560     desc.fConfig = pixelConfig;
    561 
    562     GrTextureType textureType = GrTextureType::k2D;
    563     if (context->backend() == GrBackendApi::kOpenGL) {
    564         textureType = GrTextureType::kExternal;
    565     } else if (context->backend() == GrBackendApi::kVulkan) {
    566         const VkFormat* format = backendFormat.getVkFormat();
    567         SkASSERT(format);
    568         if (*format == VK_FORMAT_UNDEFINED) {
    569             textureType = GrTextureType::kExternal;
    570         }
    571     }
    572 
    573     auto proxyProvider = context->contextPriv().proxyProvider();
    574 
    575     AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
    576     AHardwareBuffer_acquire(hardwareBuffer);
    577 
    578     const bool isProtectedContent = fIsProtectedContent;
    579 
    580     sk_sp<GrTextureProxy> texProxy = proxyProvider->createLazyProxy(
    581             [context, hardwareBuffer, width, height, pixelConfig, isProtectedContent,
    582              backendFormat](GrResourceProvider* resourceProvider) {
    583                 if (!resourceProvider) {
    584                     AHardwareBuffer_release(hardwareBuffer);
    585                     return sk_sp<GrTexture>();
    586                 }
    587 
    588                 DeleteImageProc deleteImageProc = nullptr;
    589                 DeleteImageCtx deleteImageCtx = nullptr;
    590 
    591                 GrBackendTexture backendTex = make_backend_texture(context, hardwareBuffer,
    592                                                                    width, height, pixelConfig,
    593                                                                    &deleteImageProc,
    594                                                                    &deleteImageCtx,
    595                                                                    isProtectedContent,
    596                                                                    backendFormat);
    597                 if (!backendTex.isValid()) {
    598                     return sk_sp<GrTexture>();
    599                 }
    600                 SkASSERT(deleteImageProc && deleteImageCtx);
    601 
    602                 backendTex.fConfig = pixelConfig;
    603                 // We make this texture cacheable to avoid recreating a GrTexture every time this
    604                 // is invoked. We know the owning SkIamge will send an invalidation message when the
    605                 // image is destroyed, so the texture will be removed at that time.
    606                 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(
    607                         backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kYes, kRead_GrIOType);
    608                 if (!tex) {
    609                     deleteImageProc(deleteImageCtx);
    610                     return sk_sp<GrTexture>();
    611                 }
    612 
    613                 if (deleteImageProc) {
    614                     sk_sp<GrReleaseProcHelper> releaseProcHelper(
    615                             new GrReleaseProcHelper(deleteImageProc, deleteImageCtx));
    616                     tex->setRelease(releaseProcHelper);
    617                 }
    618 
    619                 return tex;
    620             },
    621             backendFormat, desc, fSurfaceOrigin, GrMipMapped::kNo,
    622             GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo);
    623 
    624     if (!texProxy) {
    625         AHardwareBuffer_release(hardwareBuffer);
    626     }
    627     return texProxy;
    628 }
    629 
    630 sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
    631         GrContext* context, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
    632     sk_sp<GrTextureProxy> texProxy = this->makeProxy(context);
    633     if (!texProxy) {
    634         return nullptr;
    635     }
    636 
    637     if (0 == origin.fX && 0 == origin.fY &&
    638         info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
    639         // If the caller wants the full texture we're done. The caller will handle making a copy for
    640         // mip maps if that is required.
    641         return texProxy;
    642     }
    643     // Otherwise, make a copy for the requested subset.
    644     SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
    645 
    646     GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
    647 
    648     return GrSurfaceProxy::Copy(context, texProxy.get(), mipMapped, subset, SkBackingFit::kExact,
    649                                 SkBudgeted::kYes);
    650 }
    651 
    652 bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
    653     if (nullptr == context) {
    654         return false; //CPU backend is not supported, because hardware buffer can be swizzled
    655     }
    656     return GrBackendApi::kOpenGL == context->backend() ||
    657            GrBackendApi::kVulkan == context->backend();
    658 }
    659 
    660 #endif //SK_BUILD_FOR_ANDROID_FRAMEWORK
    661