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