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