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