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