Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
VkHardwareBufferTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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// This is a GPU-backend specific test. It relies on static initializers to work
9
11
12#if defined(SK_GANESH) && defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26 && defined(SK_VULKAN)
13
21#include "include/gpu/GrTypes.h"
36#include "src/gpu/ganesh/SkGr.h"
39#include "tests/Test.h"
42
44#include <cinttypes>
45
46#include <EGL/egl.h>
47#include <EGL/eglext.h>
48#include <GLES/gl.h>
49#include <GLES/glext.h>
50
51static const int DEV_W = 16, DEV_H = 16;
52
53class BaseTestHelper {
54public:
55 virtual ~BaseTestHelper() {}
56
57 virtual bool init(skiatest::Reporter* reporter) = 0;
58
59 virtual void cleanup() = 0;
60 // This is used to release a surface back to the external queue in vulkan
61 virtual void releaseSurfaceToExternal(SkSurface*) = 0;
62 virtual void releaseImage() = 0;
63
64 virtual sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
66 virtual sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
68
69 virtual void doClientSync() = 0;
70 virtual bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) = 0;
71 virtual bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
73
74 virtual void makeCurrent() = 0;
75
76 virtual GrDirectContext* directContext() = 0;
77
78 int getFdHandle() { return fFdHandle; }
79
80protected:
81 BaseTestHelper() {}
82
83 int fFdHandle = 0;
84};
85
86#ifdef SK_GL
87class EGLTestHelper : public BaseTestHelper {
88public:
89 EGLTestHelper(const GrContextOptions& options) : fFactory(options) {}
90
91 ~EGLTestHelper() override {}
92
93 void releaseImage() override {
94 this->makeCurrent();
95 if (!fGLCtx) {
96 return;
97 }
98 if (EGL_NO_IMAGE_KHR != fImage) {
99 fGLCtx->destroyEGLImage(fImage);
100 fImage = EGL_NO_IMAGE_KHR;
101 }
102 if (fTexID) {
103 GR_GL_CALL(fGLCtx->gl(), DeleteTextures(1, &fTexID));
104 fTexID = 0;
105 }
106 }
107
108 void releaseSurfaceToExternal(SkSurface*) override {}
109
110 void cleanup() override {
111 this->releaseImage();
112 }
113
114 bool init(skiatest::Reporter* reporter) override;
115
116 sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
117 AHardwareBuffer* buffer) override;
118 sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
119 AHardwareBuffer* buffer) override;
120
121 void doClientSync() override;
122 bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) override;
123 bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
124 sk_sp<SkSurface>) override;
125
126 void makeCurrent() override { fGLCtx->makeCurrent(); }
127
128 GrDirectContext* directContext() override { return fDirectContext; }
129
130private:
131 bool importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer);
132
133 typedef EGLClientBuffer (*EGLGetNativeClientBufferANDROIDProc)(const struct AHardwareBuffer*);
134 typedef EGLImageKHR (*EGLCreateImageKHRProc)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer,
135 const EGLint*);
136 typedef void (*EGLImageTargetTexture2DOESProc)(EGLenum, void*);
137 EGLGetNativeClientBufferANDROIDProc fEGLGetNativeClientBufferANDROID;
138 EGLCreateImageKHRProc fEGLCreateImageKHR;
139 EGLImageTargetTexture2DOESProc fEGLImageTargetTexture2DOES;
140
141 PFNEGLCREATESYNCKHRPROC fEGLCreateSyncKHR;
142 PFNEGLWAITSYNCKHRPROC fEGLWaitSyncKHR;
143 PFNEGLGETSYNCATTRIBKHRPROC fEGLGetSyncAttribKHR;
144 PFNEGLDUPNATIVEFENCEFDANDROIDPROC fEGLDupNativeFenceFDANDROID;
145 PFNEGLDESTROYSYNCKHRPROC fEGLDestroySyncKHR;
146
147 EGLImageKHR fImage = EGL_NO_IMAGE_KHR;
148 GrGLuint fTexID = 0;
149
151 sk_gpu_test::ContextInfo fGLESContextInfo;
152
153 sk_gpu_test::GLTestContext* fGLCtx = nullptr;
154 GrDirectContext* fDirectContext = nullptr;
155};
156
157bool EGLTestHelper::init(skiatest::Reporter* reporter) {
158 fGLESContextInfo = fFactory.getContextInfo(skgpu::ContextType::kGLES);
159 fDirectContext = fGLESContextInfo.directContext();
160 fGLCtx = fGLESContextInfo.glContext();
161 if (!fDirectContext || !fGLCtx) {
162 return false;
163 }
164
165 if (kGLES_GrGLStandard != fGLCtx->gl()->fStandard) {
166 return false;
167 }
168
169 // Confirm we have egl and the needed extensions
170 if (!fGLCtx->gl()->hasExtension("EGL_KHR_image") ||
171 !fGLCtx->gl()->hasExtension("EGL_ANDROID_get_native_client_buffer") ||
172 !fGLCtx->gl()->hasExtension("GL_OES_EGL_image_external") ||
173 !fGLCtx->gl()->hasExtension("GL_OES_EGL_image") ||
174 !fGLCtx->gl()->hasExtension("EGL_KHR_fence_sync") ||
175 !fGLCtx->gl()->hasExtension("EGL_ANDROID_native_fence_sync")) {
176 return false;
177 }
178
179 fEGLGetNativeClientBufferANDROID =
180 (EGLGetNativeClientBufferANDROIDProc) eglGetProcAddress("eglGetNativeClientBufferANDROID");
181 if (!fEGLGetNativeClientBufferANDROID) {
182 ERRORF(reporter, "Failed to get the eglGetNativeClientBufferAndroid proc");
183 return false;
184 }
185
186 fEGLCreateImageKHR = (EGLCreateImageKHRProc) eglGetProcAddress("eglCreateImageKHR");
187 if (!fEGLCreateImageKHR) {
188 ERRORF(reporter, "Failed to get the proc eglCreateImageKHR");
189 return false;
190 }
191
192 fEGLImageTargetTexture2DOES =
193 (EGLImageTargetTexture2DOESProc) eglGetProcAddress("glEGLImageTargetTexture2DOES");
194 if (!fEGLImageTargetTexture2DOES) {
195 ERRORF(reporter, "Failed to get the proc EGLImageTargetTexture2DOES");
196 return false;
197 }
198
199 fEGLCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
200 if (!fEGLCreateSyncKHR) {
201 ERRORF(reporter, "Failed to get the proc eglCreateSyncKHR");
202 return false;
203
204 }
205 fEGLWaitSyncKHR = (PFNEGLWAITSYNCKHRPROC) eglGetProcAddress("eglWaitSyncKHR");
206 if (!fEGLWaitSyncKHR) {
207 ERRORF(reporter, "Failed to get the proc eglWaitSyncKHR");
208 return false;
209
210 }
211 fEGLGetSyncAttribKHR = (PFNEGLGETSYNCATTRIBKHRPROC) eglGetProcAddress("eglGetSyncAttribKHR");
212 if (!fEGLGetSyncAttribKHR) {
213 ERRORF(reporter, "Failed to get the proc eglGetSyncAttribKHR");
214 return false;
215
216 }
217 fEGLDupNativeFenceFDANDROID =
218 (PFNEGLDUPNATIVEFENCEFDANDROIDPROC) eglGetProcAddress("eglDupNativeFenceFDANDROID");
219 if (!fEGLDupNativeFenceFDANDROID) {
220 ERRORF(reporter, "Failed to get the proc eglDupNativeFenceFDANDROID");
221 return false;
222
223 }
224 fEGLDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
225 if (!fEGLDestroySyncKHR) {
226 ERRORF(reporter, "Failed to get the proc eglDestroySyncKHR");
227 return false;
228
229 }
230
231 return true;
232}
233
234bool EGLTestHelper::importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer) {
235 while (fGLCtx->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {}
236
237 EGLClientBuffer eglClientBuffer = fEGLGetNativeClientBufferANDROID(buffer);
238 EGLint eglAttribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
239 EGL_NONE };
240 EGLDisplay eglDisplay = eglGetCurrentDisplay();
241 fImage = fEGLCreateImageKHR(eglDisplay, EGL_NO_CONTEXT,
242 EGL_NATIVE_BUFFER_ANDROID,
243 eglClientBuffer, eglAttribs);
244 if (EGL_NO_IMAGE_KHR == fImage) {
245 SkDebugf("Could not create EGL image, err = (%#x)\n", (int) eglGetError() );
246 return false;
247 }
248
249 GR_GL_CALL(fGLCtx->gl(), GenTextures(1, &fTexID));
250 if (!fTexID) {
251 ERRORF(reporter, "Failed to create GL Texture");
252 return false;
253 }
254 GR_GL_CALL_NOERRCHECK(fGLCtx->gl(), BindTexture(GR_GL_TEXTURE_2D, fTexID));
255 if (fGLCtx->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
256 ERRORF(reporter, "Failed to bind GL Texture");
257 return false;
258 }
259
260 fEGLImageTargetTexture2DOES(GL_TEXTURE_2D, fImage);
261 if (GrGLenum error = fGLCtx->gl()->fFunctions.fGetError(); error != GR_GL_NO_ERROR) {
262 ERRORF(reporter, "EGLImageTargetTexture2DOES failed (%#x)", (int) error);
263 return false;
264 }
265
266 fDirectContext->resetContext(kTextureBinding_GrGLBackendState);
267 return true;
268}
269
270sk_sp<SkImage> EGLTestHelper::importHardwareBufferForRead(skiatest::Reporter* reporter,
272 if (!this->importHardwareBuffer(reporter, buffer)) {
273 return nullptr;
274 }
275 GrGLTextureInfo textureInfo;
276 textureInfo.fTarget = GR_GL_TEXTURE_2D;
277 textureInfo.fID = fTexID;
278 textureInfo.fFormat = GR_GL_RGBA8;
279
280 auto backendTex = GrBackendTextures::MakeGL(DEV_W, DEV_H, skgpu::Mipmapped::kNo, textureInfo);
281 REPORTER_ASSERT(reporter, backendTex.isValid());
282
284 backendTex,
288 nullptr);
289
290 if (!image) {
291 ERRORF(reporter, "Failed to make wrapped GL SkImage");
292 return nullptr;
293 }
294
295 return image;
296}
297
298sk_sp<SkSurface> EGLTestHelper::importHardwareBufferForWrite(skiatest::Reporter* reporter,
300 if (!this->importHardwareBuffer(reporter, buffer)) {
301 return nullptr;
302 }
303 GrGLTextureInfo textureInfo;
304 textureInfo.fTarget = GR_GL_TEXTURE_2D;
305 textureInfo.fID = fTexID;
306 textureInfo.fFormat = GR_GL_RGBA8;
307
308 auto backendTex = GrBackendTextures::MakeGL(DEV_W, DEV_H, skgpu::Mipmapped::kNo, textureInfo);
309 REPORTER_ASSERT(reporter, backendTex.isValid());
310
312 backendTex,
314 0,
316 nullptr,
317 nullptr);
318
319 if (!surface) {
320 ERRORF(reporter, "Failed to make wrapped GL SkSurface");
321 return nullptr;
322 }
323
324 return surface;
325}
326
327bool EGLTestHelper::flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter,
330
331 EGLDisplay eglDisplay = eglGetCurrentDisplay();
332 EGLSyncKHR eglsync = fEGLCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
333 if (EGL_NO_SYNC_KHR == eglsync) {
334 ERRORF(reporter, "Failed to create EGLSync for EGL_SYNC_NATIVE_FENCE_ANDROID\n");
335 return false;
336 }
337
338 GR_GL_CALL(fGLCtx->gl(), Flush());
339 fFdHandle = fEGLDupNativeFenceFDANDROID(eglDisplay, eglsync);
340
341 EGLint result = fEGLDestroySyncKHR(eglDisplay, eglsync);
342 if (EGL_TRUE != result) {
343 ERRORF(reporter, "Failed to delete EGLSync, error: %d\n", result);
344 return false;
345 }
346
347 return true;
348}
349
350bool EGLTestHelper::importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
352 EGLDisplay eglDisplay = eglGetCurrentDisplay();
353 EGLint attr[] = {
354 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fdHandle,
355 EGL_NONE
356 };
357 EGLSyncKHR eglsync = fEGLCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attr);
358 if (EGL_NO_SYNC_KHR == eglsync) {
360 "Failed to create EGLSync when importing EGL_SYNC_NATIVE_FENCE_FD_ANDROID\n");
361 return false;
362 }
363 EGLint result = fEGLWaitSyncKHR(eglDisplay, eglsync, 0);
364 if (EGL_TRUE != result) {
365 ERRORF(reporter, "Failed called to eglWaitSyncKHR, error: %d\n", result);
366 // Don't return false yet, try to delete the sync first
367 }
368 result = fEGLDestroySyncKHR(eglDisplay, eglsync);
369 if (EGL_TRUE != result) {
370 ERRORF(reporter, "Failed to delete EGLSync, error: %d\n", result);
371 return false;
372 }
373 return true;
374}
375
376void EGLTestHelper::doClientSync() {
377 this->directContext()->flush();
378 this->directContext()->submit(GrSyncCpu::kYes);
379}
380#endif // SK_GL
381
382#define DECLARE_VK_PROC(name) PFN_vk##name fVk##name
383
384#define ACQUIRE_INST_VK_PROC(name) \
385 do { \
386 fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fBackendContext.fInstance,\
387 VK_NULL_HANDLE)); \
388 if (fVk##name == nullptr) { \
389 ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
390 return false; \
391 } \
392 } while(false)
393
394#define ACQUIRE_DEVICE_VK_PROC(name) \
395 do { \
396 fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \
397 if (fVk##name == nullptr) { \
398 ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
399 return false; \
400 } \
401 } while(false)
402
403class VulkanTestHelper : public BaseTestHelper {
404public:
405 VulkanTestHelper() {}
406
407 ~VulkanTestHelper() override {}
408
409 void releaseImage() override {
410 if (VK_NULL_HANDLE == fDevice) {
411 return;
412 }
413 if (fImage != VK_NULL_HANDLE) {
414 fVkDestroyImage(fDevice, fImage, nullptr);
415 fImage = VK_NULL_HANDLE;
416 }
417
418 if (fMemory != VK_NULL_HANDLE) {
419 fVkFreeMemory(fDevice, fMemory, nullptr);
420 fMemory = VK_NULL_HANDLE;
421 }
422 }
423
424 void releaseSurfaceToExternal(SkSurface* surface) override {
427 fDirectContext->flush(surface, {}, &newState);
428 }
429
430 void cleanup() override {
431 fDirectContext.reset();
432 this->releaseImage();
433 if (fSignalSemaphore != VK_NULL_HANDLE) {
434 fVkDestroySemaphore(fDevice, fSignalSemaphore, nullptr);
435 fSignalSemaphore = VK_NULL_HANDLE;
436 }
437 fBackendContext.fMemoryAllocator.reset();
438 if (fDevice != VK_NULL_HANDLE) {
439 fVkDeviceWaitIdle(fDevice);
440 fVkDestroyDevice(fDevice, nullptr);
441 fDevice = VK_NULL_HANDLE;
442 }
443#ifdef SK_ENABLE_VK_LAYERS
444 if (fDebugCallback != VK_NULL_HANDLE) {
445 fDestroyDebugCallback(fBackendContext.fInstance, fDebugCallback, nullptr);
446 }
447#endif
448 if (fBackendContext.fInstance != VK_NULL_HANDLE) {
449 fVkDestroyInstance(fBackendContext.fInstance, nullptr);
450 fBackendContext.fInstance = VK_NULL_HANDLE;
451 }
452
453 delete fExtensions;
454
455 sk_gpu_test::FreeVulkanFeaturesStructs(fFeatures);
456 delete fFeatures;
457 }
458
459 bool init(skiatest::Reporter* reporter) override;
460
461 void doClientSync() override {
462 if (!fDirectContext) {
463 return;
464 }
465
466 fDirectContext->submit(GrSyncCpu::kYes);
467 }
468
469 bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) override;
470 bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
471 sk_sp<SkSurface>) override;
472
473 sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
474 AHardwareBuffer* buffer) override;
475
476 sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
477 AHardwareBuffer* buffer) override;
478
479 void makeCurrent() override {}
480
481 GrDirectContext* directContext() override { return fDirectContext.get(); }
482
483private:
484 bool checkOptimalHardwareBuffer(skiatest::Reporter* reporter);
485
486 bool importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer, bool forWrite,
487 GrVkImageInfo* outImageInfo);
488
489 bool setupSemaphoreForSignaling(skiatest::Reporter* reporter, GrBackendSemaphore*);
490 bool exportSemaphore(skiatest::Reporter* reporter, const GrBackendSemaphore&);
491
492 DECLARE_VK_PROC(DestroyInstance);
493 DECLARE_VK_PROC(DeviceWaitIdle);
494 DECLARE_VK_PROC(DestroyDevice);
495
496 DECLARE_VK_PROC(GetPhysicalDeviceExternalSemaphoreProperties);
497 DECLARE_VK_PROC(GetPhysicalDeviceImageFormatProperties2);
498 DECLARE_VK_PROC(GetPhysicalDeviceMemoryProperties2);
499
500 DECLARE_VK_PROC(GetAndroidHardwareBufferPropertiesANDROID);
501
502 DECLARE_VK_PROC(CreateImage);
503 DECLARE_VK_PROC(GetImageMemoryRequirements2);
504 DECLARE_VK_PROC(DestroyImage);
505
506 DECLARE_VK_PROC(AllocateMemory);
507 DECLARE_VK_PROC(BindImageMemory2);
508 DECLARE_VK_PROC(FreeMemory);
509
510 DECLARE_VK_PROC(CreateSemaphore);
511 DECLARE_VK_PROC(GetSemaphoreFdKHR);
512 DECLARE_VK_PROC(ImportSemaphoreFdKHR);
513 DECLARE_VK_PROC(DestroySemaphore);
514
515 VkImage fImage = VK_NULL_HANDLE;
516 VkDeviceMemory fMemory = VK_NULL_HANDLE;
517
518 skgpu::VulkanExtensions* fExtensions = nullptr;
519 VkPhysicalDeviceFeatures2* fFeatures = nullptr;
520 VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
521 PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugCallback = nullptr;
522
523 // We hold on to the semaphore so we can delete once the GPU is done.
524 VkSemaphore fSignalSemaphore = VK_NULL_HANDLE;
525
526 VkDevice fDevice = VK_NULL_HANDLE;
527
528 GrVkBackendContext fBackendContext;
529 sk_sp<GrDirectContext> fDirectContext;
530};
531
532bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
534 if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
535 return false;
536 }
537
538 fExtensions = new skgpu::VulkanExtensions();
539 fFeatures = new VkPhysicalDeviceFeatures2;
540 memset(fFeatures, 0, sizeof(VkPhysicalDeviceFeatures2));
542 fFeatures->pNext = nullptr;
543
544 fBackendContext.fInstance = VK_NULL_HANDLE;
545 fBackendContext.fDevice = VK_NULL_HANDLE;
546
547 if (!sk_gpu_test::CreateVkBackendContext(instProc, &fBackendContext, fExtensions,
548 fFeatures, &fDebugCallback)) {
549 return false;
550 }
551 fDevice = fBackendContext.fDevice;
552 auto getProc = fBackendContext.fGetProc;
553
554 if (fDebugCallback != VK_NULL_HANDLE) {
555 fDestroyDebugCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(
556 fBackendContext.fInstance, "vkDestroyDebugReportCallbackEXT");
557 }
558
559 ACQUIRE_INST_VK_PROC(DestroyInstance);
560 ACQUIRE_INST_VK_PROC(DeviceWaitIdle);
561 ACQUIRE_INST_VK_PROC(DestroyDevice);
562
564 2)) {
565 return false;
566 }
567 if (!fExtensions->hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1)) {
568 return false;
569 }
570 if (!fExtensions->hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
571 return false;
572 }
573 if (!fExtensions->hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1)) {
574 // return false;
575 }
576
577 ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties2);
578 ACQUIRE_INST_VK_PROC(GetPhysicalDeviceImageFormatProperties2);
579 ACQUIRE_INST_VK_PROC(GetPhysicalDeviceExternalSemaphoreProperties);
580
581 ACQUIRE_DEVICE_VK_PROC(GetAndroidHardwareBufferPropertiesANDROID);
582
583 ACQUIRE_DEVICE_VK_PROC(CreateImage);
584 ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements2);
585 ACQUIRE_DEVICE_VK_PROC(DestroyImage);
586
587 ACQUIRE_DEVICE_VK_PROC(AllocateMemory);
588 ACQUIRE_DEVICE_VK_PROC(BindImageMemory2);
589 ACQUIRE_DEVICE_VK_PROC(FreeMemory);
590
591 ACQUIRE_DEVICE_VK_PROC(CreateSemaphore);
592 ACQUIRE_DEVICE_VK_PROC(GetSemaphoreFdKHR);
593 ACQUIRE_DEVICE_VK_PROC(ImportSemaphoreFdKHR);
594 ACQUIRE_DEVICE_VK_PROC(DestroySemaphore);
595
596 fDirectContext = GrDirectContexts::MakeVulkan(fBackendContext);
597 REPORTER_ASSERT(reporter, fDirectContext.get());
598 if (!fDirectContext) {
599 return false;
600 }
601
602 return this->checkOptimalHardwareBuffer(reporter);
603}
604
605bool VulkanTestHelper::checkOptimalHardwareBuffer(skiatest::Reporter* reporter) {
606 VkResult err;
607
608 VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
609 externalImageFormatInfo.sType =
611 externalImageFormatInfo.pNext = nullptr;
612 externalImageFormatInfo.handleType =
614 //externalImageFormatInfo.handType = 0x80;
615
616 // We will create the hardware buffer with gpu sampled so these usages should all be valid
620 VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
622 imageFormatInfo.pNext = &externalImageFormatInfo;
623 imageFormatInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
624 imageFormatInfo.type = VK_IMAGE_TYPE_2D;
625 imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
626 imageFormatInfo.usage = usageFlags;
627 imageFormatInfo.flags = 0;
628
631 hwbUsage.pNext = nullptr;
632
633 VkExternalImageFormatProperties externalImgFormatProps;
635 externalImgFormatProps.pNext = &hwbUsage;
636
637 VkImageFormatProperties2 imgFormProps;
639 imgFormProps.pNext = &externalImgFormatProps;
640
641 err = fVkGetPhysicalDeviceImageFormatProperties2(fBackendContext.fPhysicalDevice,
642 &imageFormatInfo, &imgFormProps);
643 if (VK_SUCCESS != err) {
644 ERRORF(reporter, "vkGetPhysicalDeviceImageFormatProperites failed, err: %d", err);
645 return false;
646 }
647
648 const VkImageFormatProperties& imageFormatProperties = imgFormProps.imageFormatProperties;
649 REPORTER_ASSERT(reporter, DEV_W <= imageFormatProperties.maxExtent.width);
650 REPORTER_ASSERT(reporter, DEV_H <= imageFormatProperties.maxExtent.height);
651
652 const VkExternalMemoryProperties& externalImageFormatProps =
653 externalImgFormatProps.externalMemoryProperties;
655 externalImageFormatProps.externalMemoryFeatures));
657 externalImageFormatProps.externalMemoryFeatures));
658
659 REPORTER_ASSERT(reporter, SkToBool(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE &
661
662 return true;
663}
664
665bool VulkanTestHelper::importHardwareBuffer(skiatest::Reporter* reporter,
667 bool forWrite,
668 GrVkImageInfo* outImageInfo) {
669 VkResult err;
670
673 hwbFormatProps.pNext = nullptr;
674
677 hwbProps.pNext = &hwbFormatProps;
678
679 err = fVkGetAndroidHardwareBufferPropertiesANDROID(fDevice, buffer, &hwbProps);
680 if (VK_SUCCESS != err) {
681 ERRORF(reporter, "GetAndroidHardwareBufferPropertiesAndroid failed, err: %d", err);
682 return false;
683 }
684
690 if (forWrite) {
693
694 }
695
696 bool useExternalFormat = VK_FORMAT_UNDEFINED == hwbFormatProps.format;
697 const VkExternalFormatANDROID externalFormatInfo {
699 nullptr, // pNext
700 useExternalFormat ? hwbFormatProps.externalFormat : 0, // externalFormat
701 };
702
703 const VkExternalMemoryImageCreateInfo externalMemoryImageInfo {
705 &externalFormatInfo, // pNext
707 };
708
712 if (forWrite) {
714 }
715
716 const VkImageCreateInfo imageCreateInfo = {
718 &externalMemoryImageInfo, // pNext
719 0, // VkImageCreateFlags
720 VK_IMAGE_TYPE_2D, // VkImageType
721 hwbFormatProps.format, // VkFormat
722 { DEV_W, DEV_H, 1 }, // VkExtent3D
723 1, // mipLevels
724 1, // arrayLayers
725 VK_SAMPLE_COUNT_1_BIT, // samples
726 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling
727 usageFlags, // VkImageUsageFlags
728 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode
729 0, // queueFamilyCount
730 0, // pQueueFamilyIndices
731 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
732 };
733
734 err = fVkCreateImage(fDevice, &imageCreateInfo, nullptr, &fImage);
735 if (VK_SUCCESS != err) {
736 ERRORF(reporter, "Create Image failed, err: %d", err);
737 return false;
738 }
739
742 phyDevMemProps.pNext = nullptr;
743
744 uint32_t typeIndex = 0;
745 uint32_t heapIndex = 0;
746 bool foundHeap = false;
747 fVkGetPhysicalDeviceMemoryProperties2(fBackendContext.fPhysicalDevice, &phyDevMemProps);
748 uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
749 for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
750 if (hwbProps.memoryTypeBits & (1 << i)) {
751 const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
752 uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
754 if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
755 typeIndex = i;
756 heapIndex = pdmp.memoryTypes[i].heapIndex;
757 REPORTER_ASSERT(reporter, heapIndex < pdmp.memoryHeapCount);
758 foundHeap = true;
759 }
760 }
761 }
762
763 // Fallback to align with GrAHardwareBufferUtils
764 if (!foundHeap && hwbProps.memoryTypeBits) {
765 typeIndex = ffs(hwbProps.memoryTypeBits) - 1;
766 foundHeap = true;
767 }
768
769 if (!foundHeap) {
770 ERRORF(reporter, "Failed to find valid heap for imported memory");
771 return false;
772 }
773
776 hwbImportInfo.pNext = nullptr;
777 hwbImportInfo.buffer = buffer;
778
779 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
781 dedicatedAllocInfo.pNext = &hwbImportInfo;
782 dedicatedAllocInfo.image = fImage;
783 dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
784
785 VkMemoryAllocateInfo allocInfo = {
787 &dedicatedAllocInfo, // pNext
788 hwbProps.allocationSize, // allocationSize
789 typeIndex, // memoryTypeIndex
790 };
791
792 err = fVkAllocateMemory(fDevice, &allocInfo, nullptr, &fMemory);
793 if (VK_SUCCESS != err) {
794 ERRORF(reporter, "AllocateMemory failed for imported buffer, err: %d", err);
795 return false;
796 }
797
798 VkBindImageMemoryInfo bindImageInfo;
800 bindImageInfo.pNext = nullptr;
801 bindImageInfo.image = fImage;
802 bindImageInfo.memory = fMemory;
803 bindImageInfo.memoryOffset = 0;
804
805 err = fVkBindImageMemory2(fDevice, 1, &bindImageInfo);
806 if (VK_SUCCESS != err) {
807 ERRORF(reporter, "BindImageMemory failed for imported buffer, err: %d", err);
808 return false;
809 }
810
811 skgpu::VulkanAlloc alloc;
812 alloc.fMemory = fMemory;
813 alloc.fOffset = 0;
814 alloc.fSize = hwbProps.allocationSize;
815 alloc.fFlags = 0;
816
817 outImageInfo->fImage = fImage;
818 outImageInfo->fAlloc = alloc;
821 outImageInfo->fFormat = VK_FORMAT_R8G8B8A8_UNORM;
822 outImageInfo->fImageUsageFlags = usageFlags;
823 outImageInfo->fLevelCount = 1;
825 return true;
826}
827
828sk_sp<SkImage> VulkanTestHelper::importHardwareBufferForRead(skiatest::Reporter* reporter,
830 GrVkImageInfo imageInfo;
831 if (!this->importHardwareBuffer(reporter, buffer, false, &imageInfo)) {
832 return nullptr;
833 }
834
835 auto backendTex = GrBackendTextures::MakeVk(DEV_W, DEV_H, imageInfo);
836
837 sk_sp<SkImage> wrappedImage = SkImages::BorrowTextureFrom(fDirectContext.get(),
838 backendTex,
842 nullptr);
843
844 if (!wrappedImage.get()) {
845 ERRORF(reporter, "Failed to create wrapped Vulkan SkImage");
846 return nullptr;
847 }
848
849 return wrappedImage;
850}
851
852bool VulkanTestHelper::flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter,
854 this->releaseSurfaceToExternal(surface.get());
855 surface.reset();
856 GrBackendSemaphore semaphore;
857 if (!this->setupSemaphoreForSignaling(reporter, &semaphore)) {
858 return false;
859 }
862 info.fSignalSemaphores = &semaphore;
863 GrSemaphoresSubmitted submitted = fDirectContext->flush(info);
864 fDirectContext->submit();
865 if (GrSemaphoresSubmitted::kNo == submitted) {
866 ERRORF(reporter, "Failing call to flush on GrDirectContext");
867 return false;
868 }
869 SkASSERT(semaphore.isInitialized());
870 if (!this->exportSemaphore(reporter, semaphore)) {
871 return false;
872 }
873 return true;
874}
875
876bool VulkanTestHelper::setupSemaphoreForSignaling(skiatest::Reporter* reporter,
877 GrBackendSemaphore* beSemaphore) {
878 // Query supported info
881 exSemInfo.pNext = nullptr;
883
886 exSemProps.pNext = nullptr;
887
888 fVkGetPhysicalDeviceExternalSemaphoreProperties(fBackendContext.fPhysicalDevice, &exSemInfo,
889 &exSemProps);
890
893 ERRORF(reporter, "HANDLE_TYPE_SYNC_FD not listed as exportFromImportedHandleTypes");
894 return false;
895 }
896 if (!SkToBool(exSemProps.compatibleHandleTypes &
898 ERRORF(reporter, "HANDLE_TYPE_SYNC_FD not listed as compatibleHandleTypes");
899 return false;
900 }
901 if (!SkToBool(exSemProps.externalSemaphoreFeatures &
905 ERRORF(reporter, "HANDLE_TYPE_SYNC_FD doesn't support export and import feature");
906 return false;
907 }
908
911 exportInfo.pNext = nullptr;
913
914 VkSemaphoreCreateInfo semaphoreInfo;
916 semaphoreInfo.pNext = &exportInfo;
917 semaphoreInfo.flags = 0;
918
919 VkSemaphore semaphore;
920 VkResult err = fVkCreateSemaphore(fDevice, &semaphoreInfo, nullptr, &semaphore);
921 if (VK_SUCCESS != err) {
922 ERRORF(reporter, "Failed to create signal semaphore, err: %d", err);
923 return false;
924 }
925 *beSemaphore = GrBackendSemaphores::MakeVk(semaphore);
926 return true;
927}
928
929bool VulkanTestHelper::exportSemaphore(skiatest::Reporter* reporter,
930 const GrBackendSemaphore& beSemaphore) {
931 VkSemaphore semaphore = GrBackendSemaphores::GetVkSemaphore(beSemaphore);
932 if (VK_NULL_HANDLE == semaphore) {
933 ERRORF(reporter, "Invalid vulkan handle in export call");
934 return false;
935 }
936
937 VkSemaphoreGetFdInfoKHR getFdInfo;
939 getFdInfo.pNext = nullptr;
940 getFdInfo.semaphore = semaphore;
942
943 VkResult err = fVkGetSemaphoreFdKHR(fDevice, &getFdInfo, &fFdHandle);
944 if (VK_SUCCESS != err) {
945 ERRORF(reporter, "Failed to export signal semaphore, err: %d", err);
946 return false;
947 }
948 fSignalSemaphore = semaphore;
949 return true;
950}
951
952bool VulkanTestHelper::importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
954 VkSemaphoreCreateInfo semaphoreInfo;
956 semaphoreInfo.pNext = nullptr;
957 semaphoreInfo.flags = 0;
958
959 VkSemaphore semaphore;
960 VkResult err = fVkCreateSemaphore(fDevice, &semaphoreInfo, nullptr, &semaphore);
961 if (VK_SUCCESS != err) {
962 ERRORF(reporter, "Failed to create import semaphore, err: %d", err);
963 return false;
964 }
965
968 importInfo.pNext = nullptr;
969 importInfo.semaphore = semaphore;
972 importInfo.fd = fdHandle;
973
974 err = fVkImportSemaphoreFdKHR(fDevice, &importInfo);
975 if (VK_SUCCESS != err) {
976 ERRORF(reporter, "Failed to import semaphore, err: %d", err);
977 return false;
978 }
979
980 GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(semaphore);
981 if (!surface->wait(1, &beSemaphore)) {
982 ERRORF(reporter, "Failed to add wait semaphore to surface");
983 fVkDestroySemaphore(fDevice, semaphore, nullptr);
984 return false;
985 }
986 return true;
987}
988
989sk_sp<SkSurface> VulkanTestHelper::importHardwareBufferForWrite(skiatest::Reporter* reporter,
991 GrVkImageInfo imageInfo;
992 if (!this->importHardwareBuffer(reporter, buffer, true, &imageInfo)) {
993 return nullptr;
994 }
995
996 auto backendTex = GrBackendTextures::MakeVk(DEV_W, DEV_H, imageInfo);
997
999 backendTex,
1001 0,
1003 nullptr,
1004 nullptr);
1005
1006 if (!surface.get()) {
1007 ERRORF(reporter, "Failed to create wrapped Vulkan SkSurface");
1008 return nullptr;
1009 }
1010
1011 return surface;
1012}
1013
1014static SkPMColor get_src_color(int x, int y) {
1015 SkASSERT(x >= 0 && x < DEV_W);
1016 SkASSERT(y >= 0 && y < DEV_H);
1017
1018 U8CPU r = x;
1019 U8CPU g = y;
1020 U8CPU b = 0xc;
1021
1022 U8CPU a = 0xff;
1023 switch ((x+y) % 5) {
1024 case 0:
1025 a = 0xff;
1026 break;
1027 case 1:
1028 a = 0x80;
1029 break;
1030 case 2:
1031 a = 0xCC;
1032 break;
1033 case 4:
1034 a = 0x01;
1035 break;
1036 case 3:
1037 a = 0x00;
1038 break;
1039 }
1040 a = 0xff;
1041 return SkPremultiplyARGBInline(a, r, g, b);
1042}
1043
1044static SkBitmap make_src_bitmap() {
1045 static SkBitmap bmp;
1046 if (bmp.isNull()) {
1048 intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
1049 for (int y = 0; y < DEV_H; ++y) {
1050 for (int x = 0; x < DEV_W; ++x) {
1051 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(
1052 pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
1053 *pixel = get_src_color(x, y);
1054 }
1055 }
1056 }
1057 return bmp;
1058}
1059
1060static bool check_read(skiatest::Reporter* reporter, const SkBitmap& srcBitmap,
1061 const SkBitmap& dstBitmap) {
1062 bool result = true;
1063 for (int y = 0; y < DEV_H && result; ++y) {
1064 for (int x = 0; x < DEV_W && result; ++x) {
1065 const uint32_t srcPixel = *srcBitmap.getAddr32(x, y);
1066 const uint32_t dstPixel = *dstBitmap.getAddr32(x, y);
1067 if (srcPixel != dstPixel) {
1068 ERRORF(reporter, "Expected readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
1069 x, y, srcPixel, dstPixel);
1070 result = false;
1071 } /*else {
1072 ERRORF(reporter, "Got good readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
1073 x, y, srcPixel, dstPixel);
1074
1075 }*/
1076 }
1077 }
1078 return result;
1079}
1080
1081static void cleanup_resources(BaseTestHelper* srcHelper, BaseTestHelper* dstHelper,
1083 if (srcHelper) {
1084 srcHelper->cleanup();
1085 }
1086 if (dstHelper) {
1087 dstHelper->cleanup();
1088 }
1089 if (buffer) {
1090 AHardwareBuffer_release(buffer);
1091 }
1092}
1093
1094enum class SrcType {
1095 kCPU,
1096 kEGL,
1097 kVulkan,
1098};
1099
1100enum class DstType {
1101 kEGL,
1102 kVulkan,
1103};
1104
1106 SrcType srcType, DstType dstType, bool shareSyncs) {
1107 if (SrcType::kCPU == srcType && shareSyncs) {
1108 // We don't currently test this since we don't do any syncs in this case.
1109 return;
1110 }
1111 std::unique_ptr<BaseTestHelper> srcHelper;
1112 std::unique_ptr<BaseTestHelper> dstHelper;
1113 AHardwareBuffer* buffer = nullptr;
1114 if (SrcType::kVulkan == srcType) {
1115 srcHelper.reset(new VulkanTestHelper());
1116 } else if (SrcType::kEGL == srcType) {
1117#ifdef SK_GL
1118 srcHelper.reset(new EGLTestHelper(options));
1119#else
1120 SkASSERTF(false, "SrcType::kEGL used without OpenGL support.");
1121#endif
1122 }
1123 if (srcHelper) {
1124 if (!srcHelper->init(reporter)) {
1125 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1126 return;
1127 }
1128 }
1129
1130 if (DstType::kVulkan == dstType) {
1131 dstHelper.reset(new VulkanTestHelper());
1132 } else {
1133#ifdef SK_GL
1134 SkASSERT(DstType::kEGL == dstType);
1135 dstHelper.reset(new EGLTestHelper(options));
1136#else
1137 SkASSERTF(false, "DstType::kEGL used without OpenGL support.");
1138#endif
1139 }
1140 if (dstHelper) {
1141 if (!dstHelper->init(reporter)) {
1142 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1143 return;
1144 }
1145 }
1146
1147 ///////////////////////////////////////////////////////////////////////////
1148 // Setup SkBitmaps
1149 ///////////////////////////////////////////////////////////////////////////
1150
1151 SkBitmap srcBitmap = make_src_bitmap();
1152 SkBitmap dstBitmapSurface;
1153 dstBitmapSurface.allocN32Pixels(DEV_W, DEV_H);
1154 SkBitmap dstBitmapFinal;
1155 dstBitmapFinal.allocN32Pixels(DEV_W, DEV_H);
1156
1157 ///////////////////////////////////////////////////////////////////////////
1158 // Setup AHardwareBuffer
1159 ///////////////////////////////////////////////////////////////////////////
1160
1161 AHardwareBuffer_Desc hwbDesc;
1162 hwbDesc.width = DEV_W;
1163 hwbDesc.height = DEV_H;
1164 hwbDesc.layers = 1;
1165 if (SrcType::kCPU == srcType) {
1166 hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
1167 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
1168 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
1169 } else {
1170 hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
1171 AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
1172 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
1173 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
1174 }
1175 hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
1176 // The following three are not used in the allocate
1177 hwbDesc.stride = 0;
1178 hwbDesc.rfu0= 0;
1179 hwbDesc.rfu1= 0;
1180
1181 if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
1182 ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
1183 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1184 return;
1185 }
1186
1187 if (SrcType::kCPU == srcType) {
1188 // Get actual desc for allocated buffer so we know the stride for uploading cpu data.
1189 AHardwareBuffer_describe(buffer, &hwbDesc);
1190
1191 uint32_t* bufferAddr;
1192 if (AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
1193 reinterpret_cast<void**>(&bufferAddr))) {
1194 ERRORF(reporter, "Failed to lock hardware buffer");
1195 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1196 return;
1197 }
1198
1199 int bbp = srcBitmap.bytesPerPixel();
1200 uint32_t* src = (uint32_t*)srcBitmap.getPixels();
1201 uint32_t* dst = bufferAddr;
1202 for (int y = 0; y < DEV_H; ++y) {
1203 memcpy(dst, src, DEV_W * bbp);
1204 src += DEV_W;
1205 dst += hwbDesc.stride;
1206 }
1207
1208 for (int y = 0; y < DEV_H; ++y) {
1209 for (int x = 0; x < DEV_W; ++x) {
1210 const uint32_t srcPixel = *srcBitmap.getAddr32(x, y);
1211 uint32_t dstPixel = bufferAddr[y * hwbDesc.stride + x];
1212 if (srcPixel != dstPixel) {
1213 ERRORF(reporter, "CPU HWB Expected readpix (%d, %d) value 0x%08x, got 0x%08x.",
1214 x, y, srcPixel, dstPixel);
1215 }
1216 }
1217 }
1218
1219 AHardwareBuffer_unlock(buffer, nullptr);
1220
1221 } else {
1222 srcHelper->makeCurrent();
1223 sk_sp<SkSurface> surface = srcHelper->importHardwareBufferForWrite(reporter, buffer);
1224
1225 if (!surface) {
1226 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1227 return;
1228 }
1229
1230 sk_sp<SkImage> srcBmpImage = SkImages::RasterFromBitmap(srcBitmap);
1231 surface->getCanvas()->drawImage(srcBmpImage, 0, 0);
1232
1233 // If we are testing sharing of syncs, don't do a read here since it forces sychronization
1234 // to occur.
1235 if (!shareSyncs) {
1236 bool readResult = surface->readPixels(dstBitmapSurface, 0, 0);
1237 if (!readResult) {
1238 ERRORF(reporter, "Read Pixels on surface failed");
1239 surface.reset();
1240 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1241 return;
1242 }
1243 REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, dstBitmapSurface));
1244 }
1245
1246 ///////////////////////////////////////////////////////////////////////////
1247 // Cleanup GL/EGL and add syncs
1248 ///////////////////////////////////////////////////////////////////////////
1249
1250 if (shareSyncs) {
1251 if (!srcHelper->flushSurfaceAndSignalSemaphore(reporter, std::move(surface))) {
1252 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1253 return;
1254 }
1255 } else {
1256 srcHelper->releaseSurfaceToExternal(surface.get());
1257 srcHelper->doClientSync();
1258 surface.reset();
1259 srcHelper->releaseImage();
1260 }
1261 }
1262
1263 ///////////////////////////////////////////////////////////////////////////
1264 // Import the HWB into backend and draw it to a surface
1265 ///////////////////////////////////////////////////////////////////////////
1266
1267 dstHelper->makeCurrent();
1268 sk_sp<SkImage> wrappedImage = dstHelper->importHardwareBufferForRead(reporter, buffer);
1269
1270 if (!wrappedImage) {
1271 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1272 return;
1273 }
1274
1275 auto direct = dstHelper->directContext();
1276
1277 // Make SkSurface to render wrapped HWB into.
1279 kPremul_SkAlphaType, nullptr);
1280
1282 direct, skgpu::Budgeted::kNo, imageInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr, false);
1283 if (!dstSurf.get()) {
1284 ERRORF(reporter, "Failed to create destination SkSurface");
1285 wrappedImage.reset();
1286 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1287 return;
1288 }
1289
1290 if (shareSyncs) {
1291 if (!dstHelper->importAndWaitOnSemaphore(reporter, srcHelper->getFdHandle(), dstSurf)) {
1292 wrappedImage.reset();
1293 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1294 return;
1295 }
1296 }
1297 dstSurf->getCanvas()->drawImage(wrappedImage, 0, 0);
1298
1299 bool readResult = dstSurf->readPixels(dstBitmapFinal, 0, 0);
1300 if (!readResult) {
1301 ERRORF(reporter, "Read Pixels failed");
1302 wrappedImage.reset();
1303 dstSurf.reset();
1304 dstHelper->doClientSync();
1305 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1306 return;
1307 }
1308
1309 REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, dstBitmapFinal));
1310
1311 dstSurf.reset();
1312 wrappedImage.reset();
1313 dstHelper->doClientSync();
1314 cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
1315}
1316
1317DEF_GANESH_TEST(VulkanHardwareBuffer_CPU_Vulkan, reporter, options, CtsEnforcement::kApiLevel_T) {
1318 run_test(reporter, options, SrcType::kCPU, DstType::kVulkan, false);
1319}
1320
1321DEF_GANESH_TEST(VulkanHardwareBuffer_Vulkan_Vulkan,
1322 reporter,
1323 options,
1325 run_test(reporter, options, SrcType::kVulkan, DstType::kVulkan, false);
1326}
1327
1328DEF_GANESH_TEST(VulkanHardwareBuffer_Vulkan_Vulkan_Syncs,
1329 reporter,
1330 options,
1332 run_test(reporter, options, SrcType::kVulkan, DstType::kVulkan, true);
1333}
1334
1335#if defined(SK_GL)
1336DEF_GANESH_TEST(VulkanHardwareBuffer_EGL_Vulkan, reporter, options, CtsEnforcement::kApiLevel_T) {
1337 run_test(reporter, options, SrcType::kEGL, DstType::kVulkan, false);
1338}
1339
1340DEF_GANESH_TEST(VulkanHardwareBuffer_CPU_EGL, reporter, options, CtsEnforcement::kApiLevel_T) {
1341 run_test(reporter, options, SrcType::kCPU, DstType::kEGL, false);
1342}
1343
1344DEF_GANESH_TEST(VulkanHardwareBuffer_EGL_EGL, reporter, options, CtsEnforcement::kApiLevel_T) {
1345 run_test(reporter, options, SrcType::kEGL, DstType::kEGL, false);
1346}
1347
1348DEF_GANESH_TEST(VulkanHardwareBuffer_Vulkan_EGL, reporter, options, CtsEnforcement::kApiLevel_T) {
1349 run_test(reporter, options, SrcType::kVulkan, DstType::kEGL, false);
1350}
1351
1352DEF_GANESH_TEST(VulkanHardwareBuffer_EGL_EGL_Syncs,
1353 reporter,
1354 options,
1356 run_test(reporter, options, SrcType::kEGL, DstType::kEGL, true);
1357}
1358
1359DEF_GANESH_TEST(VulkanHardwareBuffer_Vulkan_EGL_Syncs,
1360 reporter,
1361 options,
1363 run_test(reporter, options, SrcType::kVulkan, DstType::kEGL, true);
1364}
1365
1366DEF_GANESH_TEST(VulkanHardwareBuffer_EGL_Vulkan_Syncs,
1367 reporter,
1368 options,
1370 run_test(reporter, options, SrcType::kEGL, DstType::kVulkan, true);
1371}
1372#endif
1373
1374#endif // defined(SK_GANESH) && defined(SK_BUILD_FOR_ANDROID) &&
1375 // __ANDROID_API__ >= 26 && defined(SK_VULKAN)
1376
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
static const int DEV_H
static const int DEV_W
reporter
struct AHardwareBuffer AHardwareBuffer
#define GR_GL_RGBA8
#define GR_GL_TEXTURE_2D
#define GR_GL_NO_ERROR
unsigned int GrGLuint
Definition GrGLTypes.h:113
@ kGLES_GrGLStandard
Definition GrGLTypes.h:22
unsigned int GrGLenum
Definition GrGLTypes.h:102
#define GR_GL_CALL_NOERRCHECK(IFACE, X)
Definition GrGLUtil.h:389
#define GR_GL_CALL(IFACE, X)
Definition GrGLUtil.h:381
static bool check_read(skiatest::Reporter *reporter, const SkBitmap &bitmap)
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
GrSemaphoresSubmitted
Definition GrTypes.h:229
@ kTextureBinding_GrGLBackendState
Definition GrTypes.h:159
static SkPMColor get_src_color(int x, int y)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkASSERTF(cond, fmt,...)
Definition SkAssert.h:117
unsigned U8CPU
Definition SkCPUTypes.h:18
static SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
uint32_t SkPMColor
Definition SkColor.h:205
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
#define DEF_GANESH_TEST(name, reporter, options, ctsEnforcement)
Definition Test.h:393
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
#define ERRORF(r,...)
Definition Test.h:293
#define ACQUIRE_INST_VK_PROC(name)
size_t rowBytes() const
Definition SkBitmap.h:238
bool isNull() const
Definition SkBitmap.h:219
void * getPixels() const
Definition SkBitmap.h:283
int bytesPerPixel() const
Definition SkBitmap.h:187
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition SkBitmap.cpp:232
uint32_t * getAddr32(int x, int y) const
Definition SkBitmap.h:1260
T * get() const
Definition SkRefCnt.h:303
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
@ kVulkan
Definition embedder.h:86
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
static bool b
struct MyStruct a[10]
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
double y
double x
SK_API GrBackendSemaphore MakeVk(VkSemaphore semaphore)
SK_API VkSemaphore GetVkSemaphore(const GrBackendSemaphore &)
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
SK_API GrBackendTexture MakeVk(int width, int height, const GrVkImageInfo &, std::string_view label={})
SK_API sk_sp< GrDirectContext > MakeVulkan(const GrVkBackendContext &, const GrContextOptions &)
SK_API sk_sp< SkImage > RasterFromBitmap(const SkBitmap &bitmap)
SK_API sk_sp< SkImage > BorrowTextureFrom(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
void makeCurrent(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE handle)
Definition wrappers.h:22
dst
Definition cp.py:12
SK_API MutableTextureState MakeVulkan(VkImageLayout layout, uint32_t queueFamilyIndex)
SK_API void FlushAndSubmit(sk_sp< SkSurface >)
void run_test(skiatest::Reporter *reporter, Context *context, SkISize surfaceSize, SkISize recordingSize, SkISize replayOffset, DrawCallback draw, const std::vector< Expectation > &expectations)
void Flush(SkSurface *surface)
Definition GpuTools.h:25
init(device_serial, adb_binary)
Definition _adb_path.py:12
size_t fNumSemaphores
Definition GrTypes.h:217
GrGLenum fFormat
Definition GrGLTypes.h:183
GrGLenum fTarget
Definition GrGLTypes.h:181
VkImage fImage
Definition GrVkTypes.h:26
skgpu::VulkanAlloc fAlloc
Definition GrVkTypes.h:27
uint32_t fCurrentQueueFamily
Definition GrVkTypes.h:34
VkFormat fFormat
Definition GrVkTypes.h:30
uint32_t fLevelCount
Definition GrVkTypes.h:33
VkImageLayout fImageLayout
Definition GrVkTypes.h:29
VkImageUsageFlags fImageUsageFlags
Definition GrVkTypes.h:31
VkImageTiling fImageTiling
Definition GrVkTypes.h:28
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
VkStructureType sType
VkDeviceSize memoryOffset
VkDeviceMemory memory
VkExternalSemaphoreHandleTypeFlags handleTypes
uint32_t height
uint32_t width
VkExternalMemoryProperties externalMemoryProperties
VkExternalMemoryFeatureFlags externalMemoryFeatures
VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures
VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes
VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes
VkImageFormatProperties imageFormatProperties
VkSemaphoreImportFlags flags
VkExternalSemaphoreHandleTypeFlagBits handleType
uint32_t heapIndex
VkMemoryPropertyFlags propertyFlags
VkExternalMemoryHandleTypeFlagBits handleType
VkExternalSemaphoreHandleTypeFlagBits handleType
VkPhysicalDeviceMemoryProperties memoryProperties
VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]
VkStructureType sType
VkSemaphoreCreateFlags flags
VkExternalSemaphoreHandleTypeFlagBits handleType
VkStructureType sType
VkDeviceSize fSize
Definition VulkanTypes.h:40
VkDeviceMemory fMemory
Definition VulkanTypes.h:38
VkDeviceSize fOffset
Definition VulkanTypes.h:39
#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME
void(VKAPI_PTR * PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator)
@ VK_FORMAT_FEATURE_TRANSFER_DST_BIT
@ VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
@ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
@ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_SHARING_MODE_EXCLUSIVE
@ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VkFlags VkImageUsageFlags
#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME
#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME
@ VK_IMAGE_TILING_OPTIMAL
@ VK_SEMAPHORE_IMPORT_TEMPORARY_BIT
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_SAMPLED_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
@ VK_SAMPLE_COUNT_1_BIT
@ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
@ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT
@ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT
#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME
@ VK_IMAGE_TYPE_2D
@ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT
@ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT
VkResult
@ VK_SUCCESS
#define VK_NULL_HANDLE
Definition vulkan_core.h:46
#define VK_QUEUE_FAMILY_EXTERNAL
@ VK_FORMAT_R8G8B8A8_UNORM
@ VK_FORMAT_UNDEFINED
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
@ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
@ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO
@ VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID
@ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
@ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
@ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID
@ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2
@ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2
@ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO
@ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR
@ VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR
@ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
@ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2
@ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID
@ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
@ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO
@ VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID
@ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
SrcType
Definition xfermodes.cpp:29