blob: 8b86721c7c10f0c9e2221404bf7004fdb0bebcda [file] [log] [blame]
Stan Iliev7e910df2017-06-02 10:29:21 -04001/*
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 */
Stan Iliev7e910df2017-06-02 10:29:21 -04007
Greg Daniel54bfb182018-11-20 17:12:36 -05008#include "SkTypes.h"
Derek Sollenberger7a869872017-06-27 15:37:25 -04009
10#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -040011#define GL_GLEXT_PROTOTYPES
12#define EGL_EGLEXT_PROTOTYPES
Greg Daniel54bfb182018-11-20 17:12:36 -050013
14#include "vk/GrVkVulkan.h"
15
Stan Iliev7e910df2017-06-02 10:29:21 -040016#include "GrAHardwareBufferImageGenerator.h"
17
Derek Sollenberger7a869872017-06-27 15:37:25 -040018#include <android/hardware_buffer.h>
19
Stan Iliev7e910df2017-06-02 10:29:21 -040020#include "GrBackendSurface.h"
21#include "GrContext.h"
22#include "GrContextPriv.h"
Robert Phillipsadbe1322018-01-17 13:35:46 -050023#include "GrProxyProvider.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040024#include "GrResourceCache.h"
Robert Phillips00018282017-06-15 15:35:16 -040025#include "GrResourceProvider.h"
Greg Daniel637c06a2018-09-12 09:44:25 -040026#include "GrResourceProviderPriv.h"
Robert Phillips847d4c52017-06-13 18:21:44 -040027#include "GrTexture.h"
Robert Phillipsade9f612017-06-16 07:32:43 -040028#include "GrTextureProxy.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040029#include "SkMessageBus.h"
Greg Danielf1251112018-08-27 09:55:03 -040030#include "gl/GrGLDefines.h"
31#include "gl/GrGLTypes.h"
Stan Iliev7e910df2017-06-02 10:29:21 -040032
33#include <EGL/egl.h>
34#include <EGL/eglext.h>
35#include <GLES/gl.h>
36#include <GLES/glext.h>
37
Greg Daniel637c06a2018-09-12 09:44:25 -040038#ifdef SK_VULKAN
39#include "vk/GrVkExtensions.h"
40#include "vk/GrVkGpu.h"
41#endif
42
Stan Ilievc01b5c72018-08-28 10:18:19 -040043#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
44#define EGL_PROTECTED_CONTENT_EXT 0x32C0
45
46static bool can_import_protected_content_eglimpl() {
47 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
48 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
49 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
50 size_t extsLen = strlen(exts);
51 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
52 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
53 bool atEnd = (cropExtLen+1) < extsLen
54 && !strcmp(" " PROT_CONTENT_EXT_STR,
55 exts + extsLen - (cropExtLen+1));
56 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
57 return equal || atStart || atEnd || inMiddle;
58}
59
60static bool can_import_protected_content(GrContext* context) {
Greg Danielbdf12ad2018-10-12 09:31:11 -040061 if (GrBackendApi::kOpenGL == context->contextPriv().getBackend()) {
Stan Ilievc01b5c72018-08-28 10:18:19 -040062 // Only compute whether the extension is present once the first time this
63 // function is called.
64 static bool hasIt = can_import_protected_content_eglimpl();
65 return hasIt;
66 }
67 return false;
68}
69
Stan Iliev7e910df2017-06-02 10:29:21 -040070std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
Stan Iliev505dd572018-09-13 14:20:03 -040071 AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
72 GrSurfaceOrigin surfaceOrigin) {
Stan Iliev7e910df2017-06-02 10:29:21 -040073 AHardwareBuffer_Desc bufferDesc;
74 AHardwareBuffer_describe(graphicBuffer, &bufferDesc);
75 SkColorType colorType;
76 switch (bufferDesc.format) {
77 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
Stan Iliev733b2652018-10-08 16:15:37 -040078 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
Stan Iliev7e910df2017-06-02 10:29:21 -040079 colorType = kRGBA_8888_SkColorType;
80 break;
81 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
82 colorType = kRGBA_F16_SkColorType;
83 break;
84 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
85 colorType = kRGB_565_SkColorType;
86 break;
Stan Iliev114b0912018-08-31 14:02:55 -040087 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
88 colorType = kRGB_888x_SkColorType;
89 break;
90 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
91 colorType = kRGBA_1010102_SkColorType;
92 break;
Stan Iliev7e910df2017-06-02 10:29:21 -040093 default:
Stan Iliev114b0912018-08-31 14:02:55 -040094 // Given that we only use this texture as a source, colorType will not impact how Skia uses
95 // the texture. The only potential affect this is anticipated to have is that for some
96 // format types if we are not bound as an OES texture we may get invalid results for SKP
97 // capture if we read back the texture.
98 colorType = kRGBA_8888_SkColorType;
99 break;
Stan Iliev7e910df2017-06-02 10:29:21 -0400100 }
101 SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
102 alphaType, std::move(colorSpace));
Stan Ilievc01b5c72018-08-28 10:18:19 -0400103 bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
Stan Iliev505dd572018-09-13 14:20:03 -0400104 return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(
105 info, graphicBuffer, alphaType, createProtectedImage,
106 bufferDesc.format, surfaceOrigin));
Stan Iliev7e910df2017-06-02 10:29:21 -0400107}
108
109GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
Stan Iliev114b0912018-08-31 14:02:55 -0400110 AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent,
Stan Iliev505dd572018-09-13 14:20:03 -0400111 uint32_t bufferFormat, GrSurfaceOrigin surfaceOrigin)
Stan Iliev7e910df2017-06-02 10:29:21 -0400112 : INHERITED(info)
Stan Ilievc01b5c72018-08-28 10:18:19 -0400113 , fHardwareBuffer(hardwareBuffer)
Stan Iliev114b0912018-08-31 14:02:55 -0400114 , fBufferFormat(bufferFormat)
Stan Iliev505dd572018-09-13 14:20:03 -0400115 , fIsProtectedContent(isProtectedContent)
116 , fSurfaceOrigin(surfaceOrigin) {
Greg Danielf1251112018-08-27 09:55:03 -0400117 AHardwareBuffer_acquire(fHardwareBuffer);
118}
119
Stan Iliev7e910df2017-06-02 10:29:21 -0400120GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
Greg Danielf1251112018-08-27 09:55:03 -0400121 AHardwareBuffer_release(fHardwareBuffer);
Stan Iliev7e910df2017-06-02 10:29:21 -0400122}
123
Stan Iliev7e910df2017-06-02 10:29:21 -0400124///////////////////////////////////////////////////////////////////////////////////////////////////
125
Greg Daniel637c06a2018-09-12 09:44:25 -0400126#ifdef SK_VULKAN
127
128class VulkanCleanupHelper {
129public:
130 VulkanCleanupHelper(GrVkGpu* gpu, VkImage image, VkDeviceMemory memory)
131 : fDevice(gpu->device())
132 , fImage(image)
133 , fMemory(memory)
134 , fDestroyImage(gpu->vkInterface()->fFunctions.fDestroyImage)
135 , fFreeMemory(gpu->vkInterface()->fFunctions.fFreeMemory) {}
136 ~VulkanCleanupHelper() {
137 fDestroyImage(fDevice, fImage, nullptr);
138 fFreeMemory(fDevice, fMemory, nullptr);
139 }
140private:
141 VkDevice fDevice;
142 VkImage fImage;
143 VkDeviceMemory fMemory;
144 PFN_vkDestroyImage fDestroyImage;
145 PFN_vkFreeMemory fFreeMemory;
146};
147
148void GrAHardwareBufferImageGenerator::DeleteVkImage(void* context) {
149 VulkanCleanupHelper* cleanupHelper = static_cast<VulkanCleanupHelper*>(context);
150 delete cleanupHelper;
151}
152
153#define VK_CALL(X) gpu->vkInterface()->fFunctions.f##X;
154
155static GrBackendTexture make_vk_backend_texture(
156 GrContext* context, AHardwareBuffer* hardwareBuffer,
157 int width, int height, GrPixelConfig config,
158 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
159 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
160 bool isProtectedContent,
161 const GrBackendFormat& backendFormat) {
Greg Danielbdf12ad2018-10-12 09:31:11 -0400162 SkASSERT(context->contextPriv().getBackend() == GrBackendApi::kVulkan);
Greg Daniel637c06a2018-09-12 09:44:25 -0400163 GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());
164
165 VkPhysicalDevice physicalDevice = gpu->physicalDevice();
166 VkDevice device = gpu->device();
167
168 SkASSERT(gpu);
169
170 if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
171 return GrBackendTexture();
172 }
173
174 SkASSERT(backendFormat.getVkFormat());
175 VkFormat format = *backendFormat.getVkFormat();
176
177 VkResult err;
178
179 VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
180 hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
181 hwbFormatProps.pNext = nullptr;
182
183 VkAndroidHardwareBufferPropertiesANDROID hwbProps;
184 hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
185 hwbProps.pNext = &hwbFormatProps;
186
187 err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer, &hwbProps));
188 if (VK_SUCCESS != err) {
189 return GrBackendTexture();
190 }
191
Greg Daniel14c55c22018-12-04 11:25:03 -0500192 VkExternalFormatANDROID externalFormat;
193 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
194 externalFormat.pNext = nullptr;
195 externalFormat.externalFormat = 0; // If this is zero it is as if we aren't using this struct.
Greg Daniel637c06a2018-09-12 09:44:25 -0400196
Greg Daniel14c55c22018-12-04 11:25:03 -0500197 const GrVkYcbcrConversionInfo* ycbcrConversion = backendFormat.getVkYcbcrConversionInfo();
198 if (!ycbcrConversion) {
199 return GrBackendTexture();
200 }
201
202 if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) {
203 // TODO: We should not assume the transfer features here and instead should have a way for
204 // Ganesh's tracking of intenral images to report whether or not they support transfers.
205 SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
206 SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
207 SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
208 SkASSERT(!ycbcrConversion->isValid());
209 } else {
210 SkASSERT(ycbcrConversion->isValid());
211 // We have an external only format
212 SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures));
213 SkASSERT(format == VK_FORMAT_UNDEFINED);
214 SkASSERT(hwbFormatProps.externalFormat == ycbcrConversion->fExternalFormat);
215 externalFormat.externalFormat = hwbFormatProps.externalFormat;
216 }
217 SkASSERT(format == hwbFormatProps.format);
218
219 const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
220 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
221 &externalFormat, // pNext
222 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
Greg Daniel637c06a2018-09-12 09:44:25 -0400223 };
Greg Daniel14c55c22018-12-04 11:25:03 -0500224 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
225 if (format != VK_FORMAT_UNDEFINED) {
226 usageFlags = usageFlags |
227 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
228 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
229 }
Greg Daniel637c06a2018-09-12 09:44:25 -0400230
231 // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have
232 // to use linear. Add better linear support throughout Ganesh.
233 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
234
235 const VkImageCreateInfo imageCreateInfo = {
236 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
237 &externalMemoryImageInfo, // pNext
238 0, // VkImageCreateFlags
239 VK_IMAGE_TYPE_2D, // VkImageType
240 format, // VkFormat
241 { (uint32_t)width, (uint32_t)height, 1 }, // VkExtent3D
242 1, // mipLevels
243 1, // arrayLayers
244 VK_SAMPLE_COUNT_1_BIT, // samples
245 tiling, // VkImageTiling
246 usageFlags, // VkImageUsageFlags
247 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode
248 0, // queueFamilyCount
249 0, // pQueueFamilyIndices
250 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
251 };
252
253 VkImage image;
254 err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image));
255 if (VK_SUCCESS != err) {
256 return GrBackendTexture();
257 }
258
Greg Daniel637c06a2018-09-12 09:44:25 -0400259 VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
260 phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
261 phyDevMemProps.pNext = nullptr;
262
263 uint32_t typeIndex = 0;
264 uint32_t heapIndex = 0;
265 bool foundHeap = false;
266 VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps));
267 uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
268 for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
269 if (hwbProps.memoryTypeBits & (1 << i)) {
270 const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
271 uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
272 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
273 if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
274 typeIndex = i;
275 heapIndex = pdmp.memoryTypes[i].heapIndex;
276 foundHeap = true;
277 }
278 }
279 }
280 if (!foundHeap) {
281 VK_CALL(DestroyImage(device, image, nullptr));
282 return GrBackendTexture();
283 }
284
285 VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
286 hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
287 hwbImportInfo.pNext = nullptr;
288 hwbImportInfo.buffer = hardwareBuffer;
289
290 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
291 dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
292 dedicatedAllocInfo.pNext = &hwbImportInfo;
293 dedicatedAllocInfo.image = image;
294 dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
295
296 VkMemoryAllocateInfo allocInfo = {
297 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
298 &dedicatedAllocInfo, // pNext
299 hwbProps.allocationSize, // allocationSize
300 typeIndex, // memoryTypeIndex
301 };
302
303 VkDeviceMemory memory;
304
305 err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory));
306 if (VK_SUCCESS != err) {
307 VK_CALL(DestroyImage(device, image, nullptr));
308 return GrBackendTexture();
309 }
310
311 VkBindImageMemoryInfo bindImageInfo;
312 bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
313 bindImageInfo.pNext = nullptr;
314 bindImageInfo.image = image;
315 bindImageInfo.memory = memory;
316 bindImageInfo.memoryOffset = 0;
317
318 err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo));
319 if (VK_SUCCESS != err) {
320 VK_CALL(DestroyImage(device, image, nullptr));
321 VK_CALL(FreeMemory(device, memory, nullptr));
322 return GrBackendTexture();
323 }
324
325 GrVkImageInfo imageInfo;
326
327 imageInfo.fImage = image;
328 imageInfo.fAlloc = GrVkAlloc(memory, 0, hwbProps.allocationSize, 0);
329 imageInfo.fImageTiling = tiling;
330 imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
331 imageInfo.fFormat = format;
332 imageInfo.fLevelCount = 1;
333 // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not
334 // support that extension. Or if we know the source of the AHardwareBuffer is not from a
335 // "foreign" device we can leave them as external.
336 imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
Greg Daniel14c55c22018-12-04 11:25:03 -0500337 imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
Greg Daniel637c06a2018-09-12 09:44:25 -0400338
339 *deleteProc = GrAHardwareBufferImageGenerator::DeleteVkImage;
340 *deleteCtx = new VulkanCleanupHelper(gpu, image, memory);
341
342 return GrBackendTexture(width, height, imageInfo);
343}
344#endif
345
Greg Daniel3860cfd2018-09-07 09:13:54 -0400346class GLCleanupHelper {
Greg Daniel9af948d2018-08-27 09:53:51 -0400347public:
Greg Daniel3860cfd2018-09-07 09:13:54 -0400348 GLCleanupHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display)
349 : fTexID(texID)
350 , fImage(image)
Greg Daniel9af948d2018-08-27 09:53:51 -0400351 , fDisplay(display) { }
Greg Daniel3860cfd2018-09-07 09:13:54 -0400352 ~GLCleanupHelper() {
353 glDeleteTextures(1, &fTexID);
Greg Danielf1251112018-08-27 09:55:03 -0400354 // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400355 eglDestroyImageKHR(fDisplay, fImage);
356 }
357private:
Greg Daniel3860cfd2018-09-07 09:13:54 -0400358 GrGLuint fTexID;
Greg Daniel9af948d2018-08-27 09:53:51 -0400359 EGLImageKHR fImage;
Greg Daniel3860cfd2018-09-07 09:13:54 -0400360 EGLDisplay fDisplay;
Greg Daniel9af948d2018-08-27 09:53:51 -0400361};
362
Greg Daniel3860cfd2018-09-07 09:13:54 -0400363void GrAHardwareBufferImageGenerator::DeleteGLTexture(void* context) {
364 GLCleanupHelper* cleanupHelper = static_cast<GLCleanupHelper*>(context);
Greg Daniel9af948d2018-08-27 09:53:51 -0400365 delete cleanupHelper;
366}
367
368static GrBackendTexture make_gl_backend_texture(
369 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400370 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400371 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400372 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400373 bool isProtectedContent,
374 const GrBackendFormat& backendFormat) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400375 while (GL_NO_ERROR != glGetError()) {} //clear GL errors
376
Stan Ilievc01b5c72018-08-28 10:18:19 -0400377 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
Greg Daniel9af948d2018-08-27 09:53:51 -0400378 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400379 isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
380 isProtectedContent ? EGL_TRUE : EGL_NONE,
Greg Daniel9af948d2018-08-27 09:53:51 -0400381 EGL_NONE };
382 EGLDisplay display = eglGetCurrentDisplay();
Greg Danielf1251112018-08-27 09:55:03 -0400383 // eglCreateImageKHR will add a ref to the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400384 EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
385 clientBuffer, attribs);
386 if (EGL_NO_IMAGE_KHR == image) {
387 SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
388 return GrBackendTexture();
389 }
390
391 GrGLuint texID;
392 glGenTextures(1, &texID);
393 if (!texID) {
394 eglDestroyImageKHR(display, image);
395 return GrBackendTexture();
396 }
397 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texID);
398 GLenum status = GL_NO_ERROR;
399 if ((status = glGetError()) != GL_NO_ERROR) {
400 SkDebugf("glBindTexture failed (%#x)", (int) status);
401 glDeleteTextures(1, &texID);
402 eglDestroyImageKHR(display, image);
403 return GrBackendTexture();
404 }
405 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
406 if ((status = glGetError()) != GL_NO_ERROR) {
407 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
408 glDeleteTextures(1, &texID);
409 eglDestroyImageKHR(display, image);
410 return GrBackendTexture();
411 }
412 context->resetContext(kTextureBinding_GrGLBackendState);
413
414 GrGLTextureInfo textureInfo;
Greg Daniel9af948d2018-08-27 09:53:51 -0400415 textureInfo.fID = texID;
Stan Iliev114b0912018-08-31 14:02:55 -0400416 SkASSERT(backendFormat.isValid());
417 textureInfo.fTarget = *backendFormat.getGLTarget();
418 textureInfo.fFormat = *backendFormat.getGLFormat();
Greg Daniel9af948d2018-08-27 09:53:51 -0400419
Greg Daniel3860cfd2018-09-07 09:13:54 -0400420 *deleteProc = GrAHardwareBufferImageGenerator::DeleteGLTexture;
421 *deleteCtx = new GLCleanupHelper(texID, image, display);
Greg Daniel9af948d2018-08-27 09:53:51 -0400422
423 return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo);
424}
425
426static GrBackendTexture make_backend_texture(
427 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400428 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400429 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400430 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400431 bool isProtectedContent,
432 const GrBackendFormat& backendFormat) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400433 if (context->abandoned()) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400434 return GrBackendTexture();
435 }
Stan Ilievc01b5c72018-08-28 10:18:19 -0400436 bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
Greg Daniel637c06a2018-09-12 09:44:25 -0400437
Greg Danielbdf12ad2018-10-12 09:31:11 -0400438 if (GrBackendApi::kOpenGL == context->contextPriv().getBackend()) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400439 return make_gl_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
440 deleteCtx, createProtectedImage, backendFormat);
441 } else {
Greg Danielbdf12ad2018-10-12 09:31:11 -0400442 SkASSERT(GrBackendApi::kVulkan == context->contextPriv().getBackend());
Greg Daniel637c06a2018-09-12 09:44:25 -0400443#ifdef SK_VULKAN
444 // Currently we don't support protected images on vulkan
445 SkASSERT(!createProtectedImage);
446 return make_vk_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
447 deleteCtx, createProtectedImage, backendFormat);
448#else
449 return GrBackendTexture();
450#endif
451 }
Greg Daniel9af948d2018-08-27 09:53:51 -0400452}
453
Greg Daniel14c55c22018-12-04 11:25:03 -0500454GrBackendFormat get_backend_format(GrContext* context, AHardwareBuffer* hardwareBuffer,
455 GrBackendApi backend, uint32_t bufferFormat) {
Greg Danielbdf12ad2018-10-12 09:31:11 -0400456 if (backend == GrBackendApi::kOpenGL) {
Stan Iliev114b0912018-08-31 14:02:55 -0400457 switch (bufferFormat) {
458 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
459 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
Stan Iliev733b2652018-10-08 16:15:37 -0400460 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
Stan Iliev114b0912018-08-31 14:02:55 -0400461 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
462 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
463 return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
464 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
465 return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
466 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
467 return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
Stan Iliev114b0912018-08-31 14:02:55 -0400468 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
469 return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
470 default:
471 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
472 }
Greg Danielbdf12ad2018-10-12 09:31:11 -0400473 } else if (backend == GrBackendApi::kVulkan) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400474 switch (bufferFormat) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400475 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);
Greg Daniel14c55c22018-12-04 11:25:03 -0500487 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 }
Greg Daniel637c06a2018-09-12 09:44:25 -0400531 }
Stan Iliev114b0912018-08-31 14:02:55 -0400532 }
533 return GrBackendFormat();
534}
535
Greg Daniel3860cfd2018-09-07 09:13:54 -0400536sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400537 if (context->abandoned()) {
Greg Daniel3860cfd2018-09-07 09:13:54 -0400538 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -0400539 }
540
Stan Iliev7e910df2017-06-02 10:29:21 -0400541 GrPixelConfig pixelConfig;
Greg Daniel14c55c22018-12-04 11:25:03 -0500542 GrBackendFormat backendFormat = get_backend_format(context, fHardwareBuffer,
543 context->contextPriv().getBackend(),
Stan Iliev114b0912018-08-31 14:02:55 -0400544 fBufferFormat);
545 if (!context->contextPriv().caps()->getConfigFromBackendFormat(
546 backendFormat, this->getInfo().colorType(), &pixelConfig)) {
Greg Daniel3860cfd2018-09-07 09:13:54 -0400547 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -0400548 }
549
Greg Danielf1251112018-08-27 09:55:03 -0400550 int width = this->getInfo().width();
551 int height = this->getInfo().height();
Greg Daniel9af948d2018-08-27 09:53:51 -0400552
Greg Danielf1251112018-08-27 09:55:03 -0400553 GrSurfaceDesc desc;
554 desc.fWidth = width;
555 desc.fHeight = height;
556 desc.fConfig = pixelConfig;
Greg Daniel9af948d2018-08-27 09:53:51 -0400557
Greg Danielf1251112018-08-27 09:55:03 -0400558 GrTextureType textureType = GrTextureType::k2D;
Greg Danielbdf12ad2018-10-12 09:31:11 -0400559 if (context->contextPriv().getBackend() == GrBackendApi::kOpenGL) {
Greg Danielf1251112018-08-27 09:55:03 -0400560 textureType = GrTextureType::kExternal;
Greg Daniel14c55c22018-12-04 11:25:03 -0500561 } else if (context->contextPriv().getBackend() == GrBackendApi::kVulkan) {
562 const VkFormat* format = backendFormat.getVkFormat();
563 SkASSERT(format);
564 if (*format == VK_FORMAT_UNDEFINED) {
565 textureType = GrTextureType::kExternal;
566 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400567 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500568
Greg Danielf1251112018-08-27 09:55:03 -0400569 auto proxyProvider = context->contextPriv().proxyProvider();
570
571 AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
572 AHardwareBuffer_acquire(hardwareBuffer);
573
Stan Ilievc01b5c72018-08-28 10:18:19 -0400574 const bool isProtectedContent = fIsProtectedContent;
Greg Danielf1251112018-08-27 09:55:03 -0400575
Greg Daniel3860cfd2018-09-07 09:13:54 -0400576 sk_sp<GrTextureProxy> texProxy = proxyProvider->createLazyProxy(
Brian Salomonc67c31c2018-12-06 10:00:03 -0500577 [context, hardwareBuffer, width, height, pixelConfig, isProtectedContent,
578 backendFormat](GrResourceProvider* resourceProvider) {
Greg Danielf1251112018-08-27 09:55:03 -0400579 if (!resourceProvider) {
580 AHardwareBuffer_release(hardwareBuffer);
581 return sk_sp<GrTexture>();
582 }
583
Greg Danielf1251112018-08-27 09:55:03 -0400584 DeleteImageProc deleteImageProc = nullptr;
585 DeleteImageCtx deleteImageCtx = nullptr;
586
587 GrBackendTexture backendTex = make_backend_texture(context, hardwareBuffer,
588 width, height, pixelConfig,
589 &deleteImageProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400590 &deleteImageCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400591 isProtectedContent,
592 backendFormat);
Greg Danielf1251112018-08-27 09:55:03 -0400593 if (!backendTex.isValid()) {
594 return sk_sp<GrTexture>();
595 }
596 SkASSERT(deleteImageProc && deleteImageCtx);
597
598 backendTex.fConfig = pixelConfig;
Brian Salomonc67c31c2018-12-06 10:00:03 -0500599 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(
600 backendTex, kBorrow_GrWrapOwnership, kRead_GrIOType);
Greg Danielf1251112018-08-27 09:55:03 -0400601 if (!tex) {
Greg Danielf1251112018-08-27 09:55:03 -0400602 deleteImageProc(deleteImageCtx);
603 return sk_sp<GrTexture>();
604 }
605
Greg Daniel637c06a2018-09-12 09:44:25 -0400606 if (deleteImageProc) {
607 sk_sp<GrReleaseProcHelper> releaseProcHelper(
608 new GrReleaseProcHelper(deleteImageProc, deleteImageCtx));
609 tex->setRelease(releaseProcHelper);
610 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400611
Greg Danielf1251112018-08-27 09:55:03 -0400612 return tex;
613 },
Brian Salomonc67c31c2018-12-06 10:00:03 -0500614 backendFormat, desc, fSurfaceOrigin, GrMipMapped::kNo,
615 GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo);
Greg Danielf1251112018-08-27 09:55:03 -0400616
Greg Daniel3860cfd2018-09-07 09:13:54 -0400617 if (!texProxy) {
Greg Danielf1251112018-08-27 09:55:03 -0400618 AHardwareBuffer_release(hardwareBuffer);
Greg Danielf1251112018-08-27 09:55:03 -0400619 }
Greg Daniel3860cfd2018-09-07 09:13:54 -0400620 return texProxy;
621}
622
623sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
624 GrContext* context, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
625 sk_sp<GrTextureProxy> texProxy = this->makeProxy(context);
626 if (!texProxy) {
627 return nullptr;
628 }
629
630 if (0 == origin.fX && 0 == origin.fY &&
631 info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
632 // If the caller wants the full texture we're done. The caller will handle making a copy for
633 // mip maps if that is required.
634 return texProxy;
635 }
636 // Otherwise, make a copy for the requested subset.
637 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
638
639 GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
640
641 return GrSurfaceProxy::Copy(context, texProxy.get(), mipMapped, subset, SkBudgeted::kYes);
Stan Iliev7e910df2017-06-02 10:29:21 -0400642}
Stan Iliev7e910df2017-06-02 10:29:21 -0400643
644bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
645 if (nullptr == context) {
646 return false; //CPU backend is not supported, because hardware buffer can be swizzled
647 }
Greg Danielbdf12ad2018-10-12 09:31:11 -0400648 return GrBackendApi::kOpenGL == context->contextPriv().getBackend() ||
649 GrBackendApi::kVulkan == context->contextPriv().getBackend();
Stan Iliev7e910df2017-06-02 10:29:21 -0400650}
651
652#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK