blob: b7ca5bde83187b4e82bebdb182856ee9da7f0fb3 [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
192 SkASSERT(format == hwbFormatProps.format);
193 SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
194 SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
195 SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
196
197 const VkExternalMemoryImageCreateInfo externalMemoryImageInfo {
198 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
199 nullptr, // pNext
200 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
201 };
202 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
203 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
204 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
205
206 // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have
207 // to use linear. Add better linear support throughout Ganesh.
208 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
209
210 const VkImageCreateInfo imageCreateInfo = {
211 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
212 &externalMemoryImageInfo, // pNext
213 0, // VkImageCreateFlags
214 VK_IMAGE_TYPE_2D, // VkImageType
215 format, // VkFormat
216 { (uint32_t)width, (uint32_t)height, 1 }, // VkExtent3D
217 1, // mipLevels
218 1, // arrayLayers
219 VK_SAMPLE_COUNT_1_BIT, // samples
220 tiling, // VkImageTiling
221 usageFlags, // VkImageUsageFlags
222 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode
223 0, // queueFamilyCount
224 0, // pQueueFamilyIndices
225 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
226 };
227
228 VkImage image;
229 err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image));
230 if (VK_SUCCESS != err) {
231 return GrBackendTexture();
232 }
233
234 VkImageMemoryRequirementsInfo2 memReqsInfo;
235 memReqsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
236 memReqsInfo.pNext = nullptr;
237 memReqsInfo.image = image;
238
239 VkMemoryDedicatedRequirements dedicatedMemReqs;
240 dedicatedMemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
241 dedicatedMemReqs.pNext = nullptr;
242
243 VkMemoryRequirements2 memReqs;
244 memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
245 memReqs.pNext = &dedicatedMemReqs;
246
247 VK_CALL(GetImageMemoryRequirements2(device, &memReqsInfo, &memReqs));
248 SkASSERT(VK_TRUE == dedicatedMemReqs.requiresDedicatedAllocation);
249
250 VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
251 phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
252 phyDevMemProps.pNext = nullptr;
253
254 uint32_t typeIndex = 0;
255 uint32_t heapIndex = 0;
256 bool foundHeap = false;
257 VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps));
258 uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
259 for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
260 if (hwbProps.memoryTypeBits & (1 << i)) {
261 const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
262 uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
263 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
264 if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
265 typeIndex = i;
266 heapIndex = pdmp.memoryTypes[i].heapIndex;
267 foundHeap = true;
268 }
269 }
270 }
271 if (!foundHeap) {
272 VK_CALL(DestroyImage(device, image, nullptr));
273 return GrBackendTexture();
274 }
275
276 VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
277 hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
278 hwbImportInfo.pNext = nullptr;
279 hwbImportInfo.buffer = hardwareBuffer;
280
281 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
282 dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
283 dedicatedAllocInfo.pNext = &hwbImportInfo;
284 dedicatedAllocInfo.image = image;
285 dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
286
287 VkMemoryAllocateInfo allocInfo = {
288 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
289 &dedicatedAllocInfo, // pNext
290 hwbProps.allocationSize, // allocationSize
291 typeIndex, // memoryTypeIndex
292 };
293
294 VkDeviceMemory memory;
295
296 err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory));
297 if (VK_SUCCESS != err) {
298 VK_CALL(DestroyImage(device, image, nullptr));
299 return GrBackendTexture();
300 }
301
302 VkBindImageMemoryInfo bindImageInfo;
303 bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
304 bindImageInfo.pNext = nullptr;
305 bindImageInfo.image = image;
306 bindImageInfo.memory = memory;
307 bindImageInfo.memoryOffset = 0;
308
309 err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo));
310 if (VK_SUCCESS != err) {
311 VK_CALL(DestroyImage(device, image, nullptr));
312 VK_CALL(FreeMemory(device, memory, nullptr));
313 return GrBackendTexture();
314 }
315
316 GrVkImageInfo imageInfo;
317
318 imageInfo.fImage = image;
319 imageInfo.fAlloc = GrVkAlloc(memory, 0, hwbProps.allocationSize, 0);
320 imageInfo.fImageTiling = tiling;
321 imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
322 imageInfo.fFormat = format;
323 imageInfo.fLevelCount = 1;
324 // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not
325 // support that extension. Or if we know the source of the AHardwareBuffer is not from a
326 // "foreign" device we can leave them as external.
327 imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
328
329 *deleteProc = GrAHardwareBufferImageGenerator::DeleteVkImage;
330 *deleteCtx = new VulkanCleanupHelper(gpu, image, memory);
331
332 return GrBackendTexture(width, height, imageInfo);
333}
334#endif
335
Greg Daniel3860cfd2018-09-07 09:13:54 -0400336class GLCleanupHelper {
Greg Daniel9af948d2018-08-27 09:53:51 -0400337public:
Greg Daniel3860cfd2018-09-07 09:13:54 -0400338 GLCleanupHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display)
339 : fTexID(texID)
340 , fImage(image)
Greg Daniel9af948d2018-08-27 09:53:51 -0400341 , fDisplay(display) { }
Greg Daniel3860cfd2018-09-07 09:13:54 -0400342 ~GLCleanupHelper() {
343 glDeleteTextures(1, &fTexID);
Greg Danielf1251112018-08-27 09:55:03 -0400344 // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400345 eglDestroyImageKHR(fDisplay, fImage);
346 }
347private:
Greg Daniel3860cfd2018-09-07 09:13:54 -0400348 GrGLuint fTexID;
Greg Daniel9af948d2018-08-27 09:53:51 -0400349 EGLImageKHR fImage;
Greg Daniel3860cfd2018-09-07 09:13:54 -0400350 EGLDisplay fDisplay;
Greg Daniel9af948d2018-08-27 09:53:51 -0400351};
352
Greg Daniel3860cfd2018-09-07 09:13:54 -0400353void GrAHardwareBufferImageGenerator::DeleteGLTexture(void* context) {
354 GLCleanupHelper* cleanupHelper = static_cast<GLCleanupHelper*>(context);
Greg Daniel9af948d2018-08-27 09:53:51 -0400355 delete cleanupHelper;
356}
357
358static GrBackendTexture make_gl_backend_texture(
359 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400360 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400361 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400362 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400363 bool isProtectedContent,
364 const GrBackendFormat& backendFormat) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400365 while (GL_NO_ERROR != glGetError()) {} //clear GL errors
366
Stan Ilievc01b5c72018-08-28 10:18:19 -0400367 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
Greg Daniel9af948d2018-08-27 09:53:51 -0400368 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400369 isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
370 isProtectedContent ? EGL_TRUE : EGL_NONE,
Greg Daniel9af948d2018-08-27 09:53:51 -0400371 EGL_NONE };
372 EGLDisplay display = eglGetCurrentDisplay();
Greg Danielf1251112018-08-27 09:55:03 -0400373 // eglCreateImageKHR will add a ref to the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400374 EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
375 clientBuffer, attribs);
376 if (EGL_NO_IMAGE_KHR == image) {
377 SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
378 return GrBackendTexture();
379 }
380
381 GrGLuint texID;
382 glGenTextures(1, &texID);
383 if (!texID) {
384 eglDestroyImageKHR(display, image);
385 return GrBackendTexture();
386 }
387 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texID);
388 GLenum status = GL_NO_ERROR;
389 if ((status = glGetError()) != GL_NO_ERROR) {
390 SkDebugf("glBindTexture failed (%#x)", (int) status);
391 glDeleteTextures(1, &texID);
392 eglDestroyImageKHR(display, image);
393 return GrBackendTexture();
394 }
395 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
396 if ((status = glGetError()) != GL_NO_ERROR) {
397 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
398 glDeleteTextures(1, &texID);
399 eglDestroyImageKHR(display, image);
400 return GrBackendTexture();
401 }
402 context->resetContext(kTextureBinding_GrGLBackendState);
403
404 GrGLTextureInfo textureInfo;
Greg Daniel9af948d2018-08-27 09:53:51 -0400405 textureInfo.fID = texID;
Stan Iliev114b0912018-08-31 14:02:55 -0400406 SkASSERT(backendFormat.isValid());
407 textureInfo.fTarget = *backendFormat.getGLTarget();
408 textureInfo.fFormat = *backendFormat.getGLFormat();
Greg Daniel9af948d2018-08-27 09:53:51 -0400409
Greg Daniel3860cfd2018-09-07 09:13:54 -0400410 *deleteProc = GrAHardwareBufferImageGenerator::DeleteGLTexture;
411 *deleteCtx = new GLCleanupHelper(texID, image, display);
Greg Daniel9af948d2018-08-27 09:53:51 -0400412
413 return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo);
414}
415
416static GrBackendTexture make_backend_texture(
417 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400418 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400419 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400420 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400421 bool isProtectedContent,
422 const GrBackendFormat& backendFormat) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400423 if (context->abandoned()) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400424 return GrBackendTexture();
425 }
Stan Ilievc01b5c72018-08-28 10:18:19 -0400426 bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
Greg Daniel637c06a2018-09-12 09:44:25 -0400427
Greg Danielbdf12ad2018-10-12 09:31:11 -0400428 if (GrBackendApi::kOpenGL == context->contextPriv().getBackend()) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400429 return make_gl_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
430 deleteCtx, createProtectedImage, backendFormat);
431 } else {
Greg Danielbdf12ad2018-10-12 09:31:11 -0400432 SkASSERT(GrBackendApi::kVulkan == context->contextPriv().getBackend());
Greg Daniel637c06a2018-09-12 09:44:25 -0400433#ifdef SK_VULKAN
434 // Currently we don't support protected images on vulkan
435 SkASSERT(!createProtectedImage);
436 return make_vk_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
437 deleteCtx, createProtectedImage, backendFormat);
438#else
439 return GrBackendTexture();
440#endif
441 }
Greg Daniel9af948d2018-08-27 09:53:51 -0400442}
443
Greg Danielbdf12ad2018-10-12 09:31:11 -0400444GrBackendFormat get_backend_format(GrBackendApi backend, uint32_t bufferFormat) {
445 if (backend == GrBackendApi::kOpenGL) {
Stan Iliev114b0912018-08-31 14:02:55 -0400446 switch (bufferFormat) {
447 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
448 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
Stan Iliev733b2652018-10-08 16:15:37 -0400449 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
Stan Iliev114b0912018-08-31 14:02:55 -0400450 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
451 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
452 return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
453 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
454 return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
455 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
456 return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
Stan Iliev114b0912018-08-31 14:02:55 -0400457 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
458 return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
459 default:
460 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
461 }
Greg Danielbdf12ad2018-10-12 09:31:11 -0400462 } else if (backend == GrBackendApi::kVulkan) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400463 switch (bufferFormat) {
464 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
465 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
466 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
467 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
468 return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT);
469 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
470 return GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16);
471 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
472 return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32);
473 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
474 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
475 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
476 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
477 default:
478 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
479 }
Stan Iliev114b0912018-08-31 14:02:55 -0400480 }
481 return GrBackendFormat();
482}
483
Greg Daniel3860cfd2018-09-07 09:13:54 -0400484sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400485 if (context->abandoned()) {
Greg Daniel3860cfd2018-09-07 09:13:54 -0400486 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -0400487 }
488
Stan Iliev7e910df2017-06-02 10:29:21 -0400489 GrPixelConfig pixelConfig;
Stan Iliev114b0912018-08-31 14:02:55 -0400490 GrBackendFormat backendFormat = get_backend_format(context->contextPriv().getBackend(),
491 fBufferFormat);
492 if (!context->contextPriv().caps()->getConfigFromBackendFormat(
493 backendFormat, this->getInfo().colorType(), &pixelConfig)) {
Greg Daniel3860cfd2018-09-07 09:13:54 -0400494 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -0400495 }
496
Greg Danielf1251112018-08-27 09:55:03 -0400497 int width = this->getInfo().width();
498 int height = this->getInfo().height();
Greg Daniel9af948d2018-08-27 09:53:51 -0400499
Greg Danielf1251112018-08-27 09:55:03 -0400500 GrSurfaceDesc desc;
501 desc.fWidth = width;
502 desc.fHeight = height;
503 desc.fConfig = pixelConfig;
Greg Daniel9af948d2018-08-27 09:53:51 -0400504
Greg Danielf1251112018-08-27 09:55:03 -0400505 GrTextureType textureType = GrTextureType::k2D;
Greg Danielbdf12ad2018-10-12 09:31:11 -0400506 if (context->contextPriv().getBackend() == GrBackendApi::kOpenGL) {
Greg Danielf1251112018-08-27 09:55:03 -0400507 textureType = GrTextureType::kExternal;
Stan Iliev7e910df2017-06-02 10:29:21 -0400508 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500509
Greg Danielf1251112018-08-27 09:55:03 -0400510 auto proxyProvider = context->contextPriv().proxyProvider();
511
512 AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
513 AHardwareBuffer_acquire(hardwareBuffer);
514
Stan Ilievc01b5c72018-08-28 10:18:19 -0400515 const bool isProtectedContent = fIsProtectedContent;
Greg Danielf1251112018-08-27 09:55:03 -0400516
Greg Daniel3860cfd2018-09-07 09:13:54 -0400517 sk_sp<GrTextureProxy> texProxy = proxyProvider->createLazyProxy(
518 [context, hardwareBuffer, width, height, pixelConfig, isProtectedContent, backendFormat]
Greg Danielf1251112018-08-27 09:55:03 -0400519 (GrResourceProvider* resourceProvider) {
520 if (!resourceProvider) {
521 AHardwareBuffer_release(hardwareBuffer);
522 return sk_sp<GrTexture>();
523 }
524
Greg Danielf1251112018-08-27 09:55:03 -0400525 DeleteImageProc deleteImageProc = nullptr;
526 DeleteImageCtx deleteImageCtx = nullptr;
527
528 GrBackendTexture backendTex = make_backend_texture(context, hardwareBuffer,
529 width, height, pixelConfig,
530 &deleteImageProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400531 &deleteImageCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400532 isProtectedContent,
533 backendFormat);
Greg Danielf1251112018-08-27 09:55:03 -0400534 if (!backendTex.isValid()) {
535 return sk_sp<GrTexture>();
536 }
537 SkASSERT(deleteImageProc && deleteImageCtx);
538
539 backendTex.fConfig = pixelConfig;
Greg Daniel3860cfd2018-09-07 09:13:54 -0400540 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex);
Greg Danielf1251112018-08-27 09:55:03 -0400541 if (!tex) {
Greg Danielf1251112018-08-27 09:55:03 -0400542 deleteImageProc(deleteImageCtx);
543 return sk_sp<GrTexture>();
544 }
545
Greg Daniel637c06a2018-09-12 09:44:25 -0400546 if (deleteImageProc) {
547 sk_sp<GrReleaseProcHelper> releaseProcHelper(
548 new GrReleaseProcHelper(deleteImageProc, deleteImageCtx));
549 tex->setRelease(releaseProcHelper);
550 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400551
Greg Danielf1251112018-08-27 09:55:03 -0400552 return tex;
553 },
Greg Daniel4065d452018-11-16 15:43:41 -0500554 backendFormat, desc, fSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
Greg Danielf1251112018-08-27 09:55:03 -0400555 SkBudgeted::kNo);
556
Greg Daniel3860cfd2018-09-07 09:13:54 -0400557 if (!texProxy) {
Greg Danielf1251112018-08-27 09:55:03 -0400558 AHardwareBuffer_release(hardwareBuffer);
Greg Danielf1251112018-08-27 09:55:03 -0400559 }
Greg Daniel3860cfd2018-09-07 09:13:54 -0400560 return texProxy;
561}
562
563sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
564 GrContext* context, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
565 sk_sp<GrTextureProxy> texProxy = this->makeProxy(context);
566 if (!texProxy) {
567 return nullptr;
568 }
569
570 if (0 == origin.fX && 0 == origin.fY &&
571 info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
572 // If the caller wants the full texture we're done. The caller will handle making a copy for
573 // mip maps if that is required.
574 return texProxy;
575 }
576 // Otherwise, make a copy for the requested subset.
577 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
578
579 GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
580
581 return GrSurfaceProxy::Copy(context, texProxy.get(), mipMapped, subset, SkBudgeted::kYes);
Stan Iliev7e910df2017-06-02 10:29:21 -0400582}
Stan Iliev7e910df2017-06-02 10:29:21 -0400583
584bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
585 if (nullptr == context) {
586 return false; //CPU backend is not supported, because hardware buffer can be swizzled
587 }
Greg Danielbdf12ad2018-10-12 09:31:11 -0400588 return GrBackendApi::kOpenGL == context->contextPriv().getBackend() ||
589 GrBackendApi::kVulkan == context->contextPriv().getBackend();
Stan Iliev7e910df2017-06-02 10:29:21 -0400590}
591
592#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK