blob: 06b4131fe28338c18670c8faffbdb1ca9299a1b4 [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 */
7#include "SkTypes.h"
8
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
13#include "GrAHardwareBufferImageGenerator.h"
14
Derek Sollenberger7a869872017-06-27 15:37:25 -040015#include <android/hardware_buffer.h>
16
Stan Iliev7e910df2017-06-02 10:29:21 -040017#include "GrBackendSurface.h"
18#include "GrContext.h"
19#include "GrContextPriv.h"
Robert Phillipsadbe1322018-01-17 13:35:46 -050020#include "GrProxyProvider.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040021#include "GrResourceCache.h"
Robert Phillips00018282017-06-15 15:35:16 -040022#include "GrResourceProvider.h"
Greg Daniel637c06a2018-09-12 09:44:25 -040023#include "GrResourceProviderPriv.h"
Robert Phillips847d4c52017-06-13 18:21:44 -040024#include "GrTexture.h"
Robert Phillipsade9f612017-06-16 07:32:43 -040025#include "GrTextureProxy.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040026#include "SkMessageBus.h"
Greg Danielf1251112018-08-27 09:55:03 -040027#include "gl/GrGLDefines.h"
28#include "gl/GrGLTypes.h"
Stan Iliev7e910df2017-06-02 10:29:21 -040029
30#include <EGL/egl.h>
31#include <EGL/eglext.h>
32#include <GLES/gl.h>
33#include <GLES/glext.h>
34
Greg Daniel637c06a2018-09-12 09:44:25 -040035#ifdef SK_VULKAN
36#include "vk/GrVkExtensions.h"
37#include "vk/GrVkGpu.h"
38#endif
39
Stan Ilievc01b5c72018-08-28 10:18:19 -040040#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
41#define EGL_PROTECTED_CONTENT_EXT 0x32C0
42
43static bool can_import_protected_content_eglimpl() {
44 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
45 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
46 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
47 size_t extsLen = strlen(exts);
48 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
49 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
50 bool atEnd = (cropExtLen+1) < extsLen
51 && !strcmp(" " PROT_CONTENT_EXT_STR,
52 exts + extsLen - (cropExtLen+1));
53 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
54 return equal || atStart || atEnd || inMiddle;
55}
56
57static bool can_import_protected_content(GrContext* context) {
58 if (kOpenGL_GrBackend == context->contextPriv().getBackend()) {
59 // Only compute whether the extension is present once the first time this
60 // function is called.
61 static bool hasIt = can_import_protected_content_eglimpl();
62 return hasIt;
63 }
64 return false;
65}
66
Stan Iliev7e910df2017-06-02 10:29:21 -040067std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
68 AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
69 AHardwareBuffer_Desc bufferDesc;
70 AHardwareBuffer_describe(graphicBuffer, &bufferDesc);
71 SkColorType colorType;
72 switch (bufferDesc.format) {
73 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
74 colorType = kRGBA_8888_SkColorType;
75 break;
76 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
77 colorType = kRGBA_F16_SkColorType;
78 break;
79 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
80 colorType = kRGB_565_SkColorType;
81 break;
Stan Iliev114b0912018-08-31 14:02:55 -040082 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
83 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
84 colorType = kRGB_888x_SkColorType;
85 break;
86 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
87 colorType = kRGBA_1010102_SkColorType;
88 break;
Stan Iliev7e910df2017-06-02 10:29:21 -040089 default:
Stan Iliev114b0912018-08-31 14:02:55 -040090 // Given that we only use this texture as a source, colorType will not impact how Skia uses
91 // the texture. The only potential affect this is anticipated to have is that for some
92 // format types if we are not bound as an OES texture we may get invalid results for SKP
93 // capture if we read back the texture.
94 colorType = kRGBA_8888_SkColorType;
95 break;
Stan Iliev7e910df2017-06-02 10:29:21 -040096 }
97 SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
98 alphaType, std::move(colorSpace));
Stan Ilievc01b5c72018-08-28 10:18:19 -040099 bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
Stan Iliev7e910df2017-06-02 10:29:21 -0400100 return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(info, graphicBuffer,
Stan Iliev114b0912018-08-31 14:02:55 -0400101 alphaType, createProtectedImage, bufferDesc.format));
Stan Iliev7e910df2017-06-02 10:29:21 -0400102}
103
104GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
Stan Iliev114b0912018-08-31 14:02:55 -0400105 AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent,
106 uint32_t bufferFormat)
Stan Iliev7e910df2017-06-02 10:29:21 -0400107 : INHERITED(info)
Stan Ilievc01b5c72018-08-28 10:18:19 -0400108 , fHardwareBuffer(hardwareBuffer)
Stan Iliev114b0912018-08-31 14:02:55 -0400109 , fBufferFormat(bufferFormat)
Stan Ilievc01b5c72018-08-28 10:18:19 -0400110 , fIsProtectedContent(isProtectedContent) {
Greg Danielf1251112018-08-27 09:55:03 -0400111 AHardwareBuffer_acquire(fHardwareBuffer);
112}
113
Stan Iliev7e910df2017-06-02 10:29:21 -0400114GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
Greg Danielf1251112018-08-27 09:55:03 -0400115 AHardwareBuffer_release(fHardwareBuffer);
Stan Iliev7e910df2017-06-02 10:29:21 -0400116}
117
Stan Iliev7e910df2017-06-02 10:29:21 -0400118///////////////////////////////////////////////////////////////////////////////////////////////////
119
Greg Daniel637c06a2018-09-12 09:44:25 -0400120#ifdef SK_VULKAN
121
122class VulkanCleanupHelper {
123public:
124 VulkanCleanupHelper(GrVkGpu* gpu, VkImage image, VkDeviceMemory memory)
125 : fDevice(gpu->device())
126 , fImage(image)
127 , fMemory(memory)
128 , fDestroyImage(gpu->vkInterface()->fFunctions.fDestroyImage)
129 , fFreeMemory(gpu->vkInterface()->fFunctions.fFreeMemory) {}
130 ~VulkanCleanupHelper() {
131 fDestroyImage(fDevice, fImage, nullptr);
132 fFreeMemory(fDevice, fMemory, nullptr);
133 }
134private:
135 VkDevice fDevice;
136 VkImage fImage;
137 VkDeviceMemory fMemory;
138 PFN_vkDestroyImage fDestroyImage;
139 PFN_vkFreeMemory fFreeMemory;
140};
141
142void GrAHardwareBufferImageGenerator::DeleteVkImage(void* context) {
143 VulkanCleanupHelper* cleanupHelper = static_cast<VulkanCleanupHelper*>(context);
144 delete cleanupHelper;
145}
146
147#define VK_CALL(X) gpu->vkInterface()->fFunctions.f##X;
148
149static GrBackendTexture make_vk_backend_texture(
150 GrContext* context, AHardwareBuffer* hardwareBuffer,
151 int width, int height, GrPixelConfig config,
152 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
153 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
154 bool isProtectedContent,
155 const GrBackendFormat& backendFormat) {
156 SkASSERT(context->contextPriv().getBackend() == kVulkan_GrBackend);
157 GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());
158
159 VkPhysicalDevice physicalDevice = gpu->physicalDevice();
160 VkDevice device = gpu->device();
161
162 SkASSERT(gpu);
163
164 if (!gpu->vkCaps().supportsAndroidHWBExternalMemory()) {
165 return GrBackendTexture();
166 }
167
168 SkASSERT(backendFormat.getVkFormat());
169 VkFormat format = *backendFormat.getVkFormat();
170
171 VkResult err;
172
173 VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
174 hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
175 hwbFormatProps.pNext = nullptr;
176
177 VkAndroidHardwareBufferPropertiesANDROID hwbProps;
178 hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
179 hwbProps.pNext = &hwbFormatProps;
180
181 err = VK_CALL(GetAndroidHardwareBufferProperties(device, hardwareBuffer, &hwbProps));
182 if (VK_SUCCESS != err) {
183 return GrBackendTexture();
184 }
185
186 SkASSERT(format == hwbFormatProps.format);
187 SkASSERT(SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
188 SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
189 SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
190
191 const VkExternalMemoryImageCreateInfo externalMemoryImageInfo {
192 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
193 nullptr, // pNext
194 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
195 };
196 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
197 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
198 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
199
200 // TODO: Check the supported tilings vkGetPhysicalDeviceImageFormatProperties2 to see if we have
201 // to use linear. Add better linear support throughout Ganesh.
202 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
203
204 const VkImageCreateInfo imageCreateInfo = {
205 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
206 &externalMemoryImageInfo, // pNext
207 0, // VkImageCreateFlags
208 VK_IMAGE_TYPE_2D, // VkImageType
209 format, // VkFormat
210 { (uint32_t)width, (uint32_t)height, 1 }, // VkExtent3D
211 1, // mipLevels
212 1, // arrayLayers
213 VK_SAMPLE_COUNT_1_BIT, // samples
214 tiling, // VkImageTiling
215 usageFlags, // VkImageUsageFlags
216 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode
217 0, // queueFamilyCount
218 0, // pQueueFamilyIndices
219 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
220 };
221
222 VkImage image;
223 err = VK_CALL(CreateImage(device, &imageCreateInfo, nullptr, &image));
224 if (VK_SUCCESS != err) {
225 return GrBackendTexture();
226 }
227
228 VkImageMemoryRequirementsInfo2 memReqsInfo;
229 memReqsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
230 memReqsInfo.pNext = nullptr;
231 memReqsInfo.image = image;
232
233 VkMemoryDedicatedRequirements dedicatedMemReqs;
234 dedicatedMemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
235 dedicatedMemReqs.pNext = nullptr;
236
237 VkMemoryRequirements2 memReqs;
238 memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
239 memReqs.pNext = &dedicatedMemReqs;
240
241 VK_CALL(GetImageMemoryRequirements2(device, &memReqsInfo, &memReqs));
242 SkASSERT(VK_TRUE == dedicatedMemReqs.requiresDedicatedAllocation);
243
244 VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
245 phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
246 phyDevMemProps.pNext = nullptr;
247
248 uint32_t typeIndex = 0;
249 uint32_t heapIndex = 0;
250 bool foundHeap = false;
251 VK_CALL(GetPhysicalDeviceMemoryProperties2(physicalDevice, &phyDevMemProps));
252 uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
253 for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
254 if (hwbProps.memoryTypeBits & (1 << i)) {
255 const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
256 uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
257 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
258 if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
259 typeIndex = i;
260 heapIndex = pdmp.memoryTypes[i].heapIndex;
261 foundHeap = true;
262 }
263 }
264 }
265 if (!foundHeap) {
266 VK_CALL(DestroyImage(device, image, nullptr));
267 return GrBackendTexture();
268 }
269
270 VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
271 hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
272 hwbImportInfo.pNext = nullptr;
273 hwbImportInfo.buffer = hardwareBuffer;
274
275 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
276 dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
277 dedicatedAllocInfo.pNext = &hwbImportInfo;
278 dedicatedAllocInfo.image = image;
279 dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
280
281 VkMemoryAllocateInfo allocInfo = {
282 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
283 &dedicatedAllocInfo, // pNext
284 hwbProps.allocationSize, // allocationSize
285 typeIndex, // memoryTypeIndex
286 };
287
288 VkDeviceMemory memory;
289
290 err = VK_CALL(AllocateMemory(device, &allocInfo, nullptr, &memory));
291 if (VK_SUCCESS != err) {
292 VK_CALL(DestroyImage(device, image, nullptr));
293 return GrBackendTexture();
294 }
295
296 VkBindImageMemoryInfo bindImageInfo;
297 bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
298 bindImageInfo.pNext = nullptr;
299 bindImageInfo.image = image;
300 bindImageInfo.memory = memory;
301 bindImageInfo.memoryOffset = 0;
302
303 err = VK_CALL(BindImageMemory2(device, 1, &bindImageInfo));
304 if (VK_SUCCESS != err) {
305 VK_CALL(DestroyImage(device, image, nullptr));
306 VK_CALL(FreeMemory(device, memory, nullptr));
307 return GrBackendTexture();
308 }
309
310 GrVkImageInfo imageInfo;
311
312 imageInfo.fImage = image;
313 imageInfo.fAlloc = GrVkAlloc(memory, 0, hwbProps.allocationSize, 0);
314 imageInfo.fImageTiling = tiling;
315 imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
316 imageInfo.fFormat = format;
317 imageInfo.fLevelCount = 1;
318 // TODO: This should possibly be VK_QUEUE_FAMILY_FOREIGN_EXT but current Adreno devices do not
319 // support that extension. Or if we know the source of the AHardwareBuffer is not from a
320 // "foreign" device we can leave them as external.
321 imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
322
323 *deleteProc = GrAHardwareBufferImageGenerator::DeleteVkImage;
324 *deleteCtx = new VulkanCleanupHelper(gpu, image, memory);
325
326 return GrBackendTexture(width, height, imageInfo);
327}
328#endif
329
Greg Daniel3860cfd2018-09-07 09:13:54 -0400330class GLCleanupHelper {
Greg Daniel9af948d2018-08-27 09:53:51 -0400331public:
Greg Daniel3860cfd2018-09-07 09:13:54 -0400332 GLCleanupHelper(GrGLuint texID, EGLImageKHR image, EGLDisplay display)
333 : fTexID(texID)
334 , fImage(image)
Greg Daniel9af948d2018-08-27 09:53:51 -0400335 , fDisplay(display) { }
Greg Daniel3860cfd2018-09-07 09:13:54 -0400336 ~GLCleanupHelper() {
337 glDeleteTextures(1, &fTexID);
Greg Danielf1251112018-08-27 09:55:03 -0400338 // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400339 eglDestroyImageKHR(fDisplay, fImage);
340 }
341private:
Greg Daniel3860cfd2018-09-07 09:13:54 -0400342 GrGLuint fTexID;
Greg Daniel9af948d2018-08-27 09:53:51 -0400343 EGLImageKHR fImage;
Greg Daniel3860cfd2018-09-07 09:13:54 -0400344 EGLDisplay fDisplay;
Greg Daniel9af948d2018-08-27 09:53:51 -0400345};
346
Greg Daniel3860cfd2018-09-07 09:13:54 -0400347void GrAHardwareBufferImageGenerator::DeleteGLTexture(void* context) {
348 GLCleanupHelper* cleanupHelper = static_cast<GLCleanupHelper*>(context);
Greg Daniel9af948d2018-08-27 09:53:51 -0400349 delete cleanupHelper;
350}
351
352static GrBackendTexture make_gl_backend_texture(
353 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400354 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400355 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400356 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400357 bool isProtectedContent,
358 const GrBackendFormat& backendFormat) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400359 while (GL_NO_ERROR != glGetError()) {} //clear GL errors
360
Stan Ilievc01b5c72018-08-28 10:18:19 -0400361 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
Greg Daniel9af948d2018-08-27 09:53:51 -0400362 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400363 isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
364 isProtectedContent ? EGL_TRUE : EGL_NONE,
Greg Daniel9af948d2018-08-27 09:53:51 -0400365 EGL_NONE };
366 EGLDisplay display = eglGetCurrentDisplay();
Greg Danielf1251112018-08-27 09:55:03 -0400367 // eglCreateImageKHR will add a ref to the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400368 EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
369 clientBuffer, attribs);
370 if (EGL_NO_IMAGE_KHR == image) {
371 SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
372 return GrBackendTexture();
373 }
374
375 GrGLuint texID;
376 glGenTextures(1, &texID);
377 if (!texID) {
378 eglDestroyImageKHR(display, image);
379 return GrBackendTexture();
380 }
381 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texID);
382 GLenum status = GL_NO_ERROR;
383 if ((status = glGetError()) != GL_NO_ERROR) {
384 SkDebugf("glBindTexture failed (%#x)", (int) status);
385 glDeleteTextures(1, &texID);
386 eglDestroyImageKHR(display, image);
387 return GrBackendTexture();
388 }
389 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
390 if ((status = glGetError()) != GL_NO_ERROR) {
391 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
392 glDeleteTextures(1, &texID);
393 eglDestroyImageKHR(display, image);
394 return GrBackendTexture();
395 }
396 context->resetContext(kTextureBinding_GrGLBackendState);
397
398 GrGLTextureInfo textureInfo;
Greg Daniel9af948d2018-08-27 09:53:51 -0400399 textureInfo.fID = texID;
Stan Iliev114b0912018-08-31 14:02:55 -0400400 SkASSERT(backendFormat.isValid());
401 textureInfo.fTarget = *backendFormat.getGLTarget();
402 textureInfo.fFormat = *backendFormat.getGLFormat();
Greg Daniel9af948d2018-08-27 09:53:51 -0400403
Greg Daniel3860cfd2018-09-07 09:13:54 -0400404 *deleteProc = GrAHardwareBufferImageGenerator::DeleteGLTexture;
405 *deleteCtx = new GLCleanupHelper(texID, image, display);
Greg Daniel9af948d2018-08-27 09:53:51 -0400406
407 return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo);
408}
409
410static GrBackendTexture make_backend_texture(
411 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400412 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400413 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400414 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400415 bool isProtectedContent,
416 const GrBackendFormat& backendFormat) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400417 if (context->abandoned()) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400418 return GrBackendTexture();
419 }
Stan Ilievc01b5c72018-08-28 10:18:19 -0400420 bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
Greg Daniel637c06a2018-09-12 09:44:25 -0400421
422 if (kOpenGL_GrBackend == context->contextPriv().getBackend()) {
423 return make_gl_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
424 deleteCtx, createProtectedImage, backendFormat);
425 } else {
426 SkASSERT(kVulkan_GrBackend == context->contextPriv().getBackend());
427#ifdef SK_VULKAN
428 // Currently we don't support protected images on vulkan
429 SkASSERT(!createProtectedImage);
430 return make_vk_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
431 deleteCtx, createProtectedImage, backendFormat);
432#else
433 return GrBackendTexture();
434#endif
435 }
Greg Daniel9af948d2018-08-27 09:53:51 -0400436}
437
Stan Iliev114b0912018-08-31 14:02:55 -0400438GrBackendFormat get_backend_format(GrBackend backend, uint32_t bufferFormat) {
439 if (backend == kOpenGL_GrBackend) {
440 switch (bufferFormat) {
441 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
442 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
443 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
444 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
445 return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
446 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
447 return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
448 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
449 return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
450 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
451 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
452 return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
453 default:
454 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
455 }
Greg Daniel637c06a2018-09-12 09:44:25 -0400456 } else if (backend == kVulkan_GrBackend) {
457 switch (bufferFormat) {
458 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
459 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
460 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
461 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
462 return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT);
463 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
464 return GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16);
465 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
466 return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32);
467 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
468 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
469 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
470 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
471 default:
472 return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
473 }
Stan Iliev114b0912018-08-31 14:02:55 -0400474 }
475 return GrBackendFormat();
476}
477
Greg Daniel3860cfd2018-09-07 09:13:54 -0400478sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
Greg Daniel637c06a2018-09-12 09:44:25 -0400479 if (context->abandoned()) {
Greg Daniel3860cfd2018-09-07 09:13:54 -0400480 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -0400481 }
482
Stan Iliev7e910df2017-06-02 10:29:21 -0400483 GrPixelConfig pixelConfig;
Stan Iliev114b0912018-08-31 14:02:55 -0400484 GrBackendFormat backendFormat = get_backend_format(context->contextPriv().getBackend(),
485 fBufferFormat);
486 if (!context->contextPriv().caps()->getConfigFromBackendFormat(
487 backendFormat, this->getInfo().colorType(), &pixelConfig)) {
Greg Daniel3860cfd2018-09-07 09:13:54 -0400488 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -0400489 }
490
Greg Danielf1251112018-08-27 09:55:03 -0400491 int width = this->getInfo().width();
492 int height = this->getInfo().height();
Greg Daniel9af948d2018-08-27 09:53:51 -0400493
Greg Danielf1251112018-08-27 09:55:03 -0400494 GrSurfaceDesc desc;
495 desc.fWidth = width;
496 desc.fHeight = height;
497 desc.fConfig = pixelConfig;
Greg Daniel9af948d2018-08-27 09:53:51 -0400498
Greg Danielf1251112018-08-27 09:55:03 -0400499 GrTextureType textureType = GrTextureType::k2D;
500 if (context->contextPriv().getBackend() == kOpenGL_GrBackend) {
501 textureType = GrTextureType::kExternal;
Stan Iliev7e910df2017-06-02 10:29:21 -0400502 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500503
Greg Danielf1251112018-08-27 09:55:03 -0400504 auto proxyProvider = context->contextPriv().proxyProvider();
505
506 AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
507 AHardwareBuffer_acquire(hardwareBuffer);
508
Stan Ilievc01b5c72018-08-28 10:18:19 -0400509 const bool isProtectedContent = fIsProtectedContent;
Greg Danielf1251112018-08-27 09:55:03 -0400510
Greg Daniel3860cfd2018-09-07 09:13:54 -0400511 sk_sp<GrTextureProxy> texProxy = proxyProvider->createLazyProxy(
512 [context, hardwareBuffer, width, height, pixelConfig, isProtectedContent, backendFormat]
Greg Danielf1251112018-08-27 09:55:03 -0400513 (GrResourceProvider* resourceProvider) {
514 if (!resourceProvider) {
515 AHardwareBuffer_release(hardwareBuffer);
516 return sk_sp<GrTexture>();
517 }
518
Greg Danielf1251112018-08-27 09:55:03 -0400519 DeleteImageProc deleteImageProc = nullptr;
520 DeleteImageCtx deleteImageCtx = nullptr;
521
522 GrBackendTexture backendTex = make_backend_texture(context, hardwareBuffer,
523 width, height, pixelConfig,
524 &deleteImageProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400525 &deleteImageCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400526 isProtectedContent,
527 backendFormat);
Greg Danielf1251112018-08-27 09:55:03 -0400528 if (!backendTex.isValid()) {
529 return sk_sp<GrTexture>();
530 }
531 SkASSERT(deleteImageProc && deleteImageCtx);
532
533 backendTex.fConfig = pixelConfig;
Greg Daniel3860cfd2018-09-07 09:13:54 -0400534 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex);
Greg Danielf1251112018-08-27 09:55:03 -0400535 if (!tex) {
Greg Danielf1251112018-08-27 09:55:03 -0400536 deleteImageProc(deleteImageCtx);
537 return sk_sp<GrTexture>();
538 }
539
Greg Daniel637c06a2018-09-12 09:44:25 -0400540 if (deleteImageProc) {
541 sk_sp<GrReleaseProcHelper> releaseProcHelper(
542 new GrReleaseProcHelper(deleteImageProc, deleteImageCtx));
543 tex->setRelease(releaseProcHelper);
544 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400545
Greg Danielf1251112018-08-27 09:55:03 -0400546 return tex;
547 },
548 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, textureType, SkBackingFit::kExact,
549 SkBudgeted::kNo);
550
Greg Daniel3860cfd2018-09-07 09:13:54 -0400551 if (!texProxy) {
Greg Danielf1251112018-08-27 09:55:03 -0400552 AHardwareBuffer_release(hardwareBuffer);
Greg Danielf1251112018-08-27 09:55:03 -0400553 }
Greg Daniel3860cfd2018-09-07 09:13:54 -0400554 return texProxy;
555}
556
557sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
558 GrContext* context, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
559 sk_sp<GrTextureProxy> texProxy = this->makeProxy(context);
560 if (!texProxy) {
561 return nullptr;
562 }
563
564 if (0 == origin.fX && 0 == origin.fY &&
565 info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
566 // If the caller wants the full texture we're done. The caller will handle making a copy for
567 // mip maps if that is required.
568 return texProxy;
569 }
570 // Otherwise, make a copy for the requested subset.
571 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
572
573 GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
574
575 return GrSurfaceProxy::Copy(context, texProxy.get(), mipMapped, subset, SkBudgeted::kYes);
Stan Iliev7e910df2017-06-02 10:29:21 -0400576}
Stan Iliev7e910df2017-06-02 10:29:21 -0400577
578bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
579 if (nullptr == context) {
580 return false; //CPU backend is not supported, because hardware buffer can be swizzled
581 }
Greg Daniel637c06a2018-09-12 09:44:25 -0400582 return kOpenGL_GrBackend == context->contextPriv().getBackend() ||
583 kVulkan_GrBackend == context->contextPriv().getBackend();
Stan Iliev7e910df2017-06-02 10:29:21 -0400584}
585
586#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK