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