1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315 |
- /*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- // This is a GPU-backend specific test. It relies on static intializers to work
- #include "include/core/SkTypes.h"
- #if SK_SUPPORT_GPU && defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26 && defined(SK_VULKAN)
- #include "include/core/SkCanvas.h"
- #include "include/core/SkImage.h"
- #include "include/core/SkSurface.h"
- #include "include/gpu/GrBackendSemaphore.h"
- #include "include/gpu/GrContext.h"
- #include "include/gpu/vk/GrVkBackendContext.h"
- #include "include/gpu/vk/GrVkExtensions.h"
- #include "src/core/SkAutoMalloc.h"
- #include "src/gpu/GrContextPriv.h"
- #include "src/gpu/GrGpu.h"
- #include "src/gpu/GrProxyProvider.h"
- #include "src/gpu/SkGr.h"
- #include "src/gpu/gl/GrGLDefines.h"
- #include "src/gpu/gl/GrGLUtil.h"
- #include "tests/Test.h"
- #include "tools/gpu/GrContextFactory.h"
- #include "tools/gpu/vk/VkTestUtils.h"
- #include <android/hardware_buffer.h>
- #include <cinttypes>
- #include <EGL/egl.h>
- #include <EGL/eglext.h>
- #include <GLES/gl.h>
- #include <GLES/glext.h>
- static const int DEV_W = 16, DEV_H = 16;
- class BaseTestHelper {
- public:
- virtual ~BaseTestHelper() {}
- virtual bool init(skiatest::Reporter* reporter) = 0;
- virtual void cleanup() = 0;
- virtual void releaseImage() = 0;
- virtual sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) = 0;
- virtual sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) = 0;
- virtual void doClientSync() = 0;
- virtual bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) = 0;
- virtual bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
- sk_sp<SkSurface>) = 0;
- virtual void makeCurrent() = 0;
- virtual GrContext* grContext() = 0;
- int getFdHandle() { return fFdHandle; }
- protected:
- BaseTestHelper() {}
- int fFdHandle = 0;
- };
- class EGLTestHelper : public BaseTestHelper {
- public:
- EGLTestHelper(const GrContextOptions& options) : fFactory(options) {}
- ~EGLTestHelper() override {}
- void releaseImage() override {
- this->makeCurrent();
- if (!fGLCtx) {
- return;
- }
- if (EGL_NO_IMAGE_KHR != fImage) {
- fGLCtx->destroyEGLImage(fImage);
- fImage = EGL_NO_IMAGE_KHR;
- }
- if (fTexID) {
- GR_GL_CALL(fGLCtx->gl(), DeleteTextures(1, &fTexID));
- fTexID = 0;
- }
- }
- void cleanup() override {
- this->releaseImage();
- }
- bool init(skiatest::Reporter* reporter) override;
- sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) override;
- sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) override;
- void doClientSync() override;
- bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) override;
- bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
- sk_sp<SkSurface>) override;
- void makeCurrent() override { fGLCtx->makeCurrent(); }
- GrContext* grContext() override { return fGrContext; }
- private:
- bool importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer);
- typedef EGLClientBuffer (*EGLGetNativeClientBufferANDROIDProc)(const struct AHardwareBuffer*);
- typedef EGLImageKHR (*EGLCreateImageKHRProc)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer,
- const EGLint*);
- typedef void (*EGLImageTargetTexture2DOESProc)(EGLenum, void*);
- EGLGetNativeClientBufferANDROIDProc fEGLGetNativeClientBufferANDROID;
- EGLCreateImageKHRProc fEGLCreateImageKHR;
- EGLImageTargetTexture2DOESProc fEGLImageTargetTexture2DOES;
- PFNEGLCREATESYNCKHRPROC fEGLCreateSyncKHR;
- PFNEGLWAITSYNCKHRPROC fEGLWaitSyncKHR;
- PFNEGLGETSYNCATTRIBKHRPROC fEGLGetSyncAttribKHR;
- PFNEGLDUPNATIVEFENCEFDANDROIDPROC fEGLDupNativeFenceFDANDROID;
- PFNEGLDESTROYSYNCKHRPROC fEGLDestroySyncKHR;
- EGLImageKHR fImage = EGL_NO_IMAGE_KHR;
- GrGLuint fTexID = 0;
- sk_gpu_test::GrContextFactory fFactory;
- sk_gpu_test::ContextInfo fGLESContextInfo;
- sk_gpu_test::GLTestContext* fGLCtx = nullptr;
- GrContext* fGrContext = nullptr;
- };
- bool EGLTestHelper::init(skiatest::Reporter* reporter) {
- fGLESContextInfo = fFactory.getContextInfo(sk_gpu_test::GrContextFactory::kGLES_ContextType);
- fGrContext = fGLESContextInfo.grContext();
- fGLCtx = fGLESContextInfo.glContext();
- if (!fGrContext || !fGLCtx) {
- return false;
- }
- if (kGLES_GrGLStandard != fGLCtx->gl()->fStandard) {
- return false;
- }
- // Confirm we have egl and the needed extensions
- if (!fGLCtx->gl()->hasExtension("EGL_KHR_image") ||
- !fGLCtx->gl()->hasExtension("EGL_ANDROID_get_native_client_buffer") ||
- !fGLCtx->gl()->hasExtension("GL_OES_EGL_image_external") ||
- !fGLCtx->gl()->hasExtension("GL_OES_EGL_image") ||
- !fGLCtx->gl()->hasExtension("EGL_KHR_fence_sync") ||
- !fGLCtx->gl()->hasExtension("EGL_ANDROID_native_fence_sync")) {
- return false;
- }
- fEGLGetNativeClientBufferANDROID =
- (EGLGetNativeClientBufferANDROIDProc) eglGetProcAddress("eglGetNativeClientBufferANDROID");
- if (!fEGLGetNativeClientBufferANDROID) {
- ERRORF(reporter, "Failed to get the eglGetNativeClientBufferAndroid proc");
- return false;
- }
- fEGLCreateImageKHR = (EGLCreateImageKHRProc) eglGetProcAddress("eglCreateImageKHR");
- if (!fEGLCreateImageKHR) {
- ERRORF(reporter, "Failed to get the proc eglCreateImageKHR");
- return false;
- }
- fEGLImageTargetTexture2DOES =
- (EGLImageTargetTexture2DOESProc) eglGetProcAddress("glEGLImageTargetTexture2DOES");
- if (!fEGLImageTargetTexture2DOES) {
- ERRORF(reporter, "Failed to get the proc EGLImageTargetTexture2DOES");
- return false;
- }
- fEGLCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
- if (!fEGLCreateSyncKHR) {
- ERRORF(reporter, "Failed to get the proc eglCreateSyncKHR");
- return false;
- }
- fEGLWaitSyncKHR = (PFNEGLWAITSYNCKHRPROC) eglGetProcAddress("eglWaitSyncKHR");
- if (!fEGLWaitSyncKHR) {
- ERRORF(reporter, "Failed to get the proc eglWaitSyncKHR");
- return false;
- }
- fEGLGetSyncAttribKHR = (PFNEGLGETSYNCATTRIBKHRPROC) eglGetProcAddress("eglGetSyncAttribKHR");
- if (!fEGLGetSyncAttribKHR) {
- ERRORF(reporter, "Failed to get the proc eglGetSyncAttribKHR");
- return false;
- }
- fEGLDupNativeFenceFDANDROID =
- (PFNEGLDUPNATIVEFENCEFDANDROIDPROC) eglGetProcAddress("eglDupNativeFenceFDANDROID");
- if (!fEGLDupNativeFenceFDANDROID) {
- ERRORF(reporter, "Failed to get the proc eglDupNativeFenceFDANDROID");
- return false;
- }
- fEGLDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
- if (!fEGLDestroySyncKHR) {
- ERRORF(reporter, "Failed to get the proc eglDestroySyncKHR");
- return false;
- }
- return true;
- }
- bool EGLTestHelper::importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer) {
- GrGLClearErr(fGLCtx->gl());
- EGLClientBuffer eglClientBuffer = fEGLGetNativeClientBufferANDROID(buffer);
- EGLint eglAttribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE };
- EGLDisplay eglDisplay = eglGetCurrentDisplay();
- fImage = fEGLCreateImageKHR(eglDisplay, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID,
- eglClientBuffer, eglAttribs);
- if (EGL_NO_IMAGE_KHR == fImage) {
- SkDebugf("Could not create EGL image, err = (%#x)\n", (int) eglGetError() );
- return false;
- }
- GR_GL_CALL(fGLCtx->gl(), GenTextures(1, &fTexID));
- if (!fTexID) {
- ERRORF(reporter, "Failed to create GL Texture");
- return false;
- }
- GR_GL_CALL_NOERRCHECK(fGLCtx->gl(), BindTexture(GR_GL_TEXTURE_2D, fTexID));
- if (GR_GL_GET_ERROR(fGLCtx->gl()) != GR_GL_NO_ERROR) {
- ERRORF(reporter, "Failed to bind GL Texture");
- return false;
- }
- fEGLImageTargetTexture2DOES(GL_TEXTURE_2D, fImage);
- GLenum status = GL_NO_ERROR;
- if ((status = glGetError()) != GL_NO_ERROR) {
- ERRORF(reporter, "EGLImageTargetTexture2DOES failed (%#x)", (int) status);
- return false;
- }
- fGrContext->resetContext(kTextureBinding_GrGLBackendState);
- return true;
- }
- sk_sp<SkImage> EGLTestHelper::importHardwareBufferForRead(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) {
- if (!this->importHardwareBuffer(reporter, buffer)) {
- return nullptr;
- }
- GrGLTextureInfo textureInfo;
- textureInfo.fTarget = GR_GL_TEXTURE_2D;
- textureInfo.fID = fTexID;
- textureInfo.fFormat = GR_GL_RGBA8;
- GrBackendTexture backendTex(DEV_W, DEV_H, GrMipMapped::kNo, textureInfo);
- REPORTER_ASSERT(reporter, backendTex.isValid());
- sk_sp<SkImage> image = SkImage::MakeFromTexture(fGrContext,
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- kRGBA_8888_SkColorType,
- kPremul_SkAlphaType,
- nullptr);
- if (!image) {
- ERRORF(reporter, "Failed to make wrapped GL SkImage");
- return nullptr;
- }
- return image;
- }
- sk_sp<SkSurface> EGLTestHelper::importHardwareBufferForWrite(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) {
- if (!this->importHardwareBuffer(reporter, buffer)) {
- return nullptr;
- }
- GrGLTextureInfo textureInfo;
- textureInfo.fTarget = GR_GL_TEXTURE_2D;
- textureInfo.fID = fTexID;
- textureInfo.fFormat = GR_GL_RGBA8;
- GrBackendTexture backendTex(DEV_W, DEV_H, GrMipMapped::kNo, textureInfo);
- REPORTER_ASSERT(reporter, backendTex.isValid());
- sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(fGrContext,
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- 0,
- kRGBA_8888_SkColorType,
- nullptr, nullptr);
- if (!surface) {
- ERRORF(reporter, "Failed to make wrapped GL SkSurface");
- return nullptr;
- }
- return surface;
- }
- bool EGLTestHelper::flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter,
- sk_sp<SkSurface> surface) {
- EGLDisplay eglDisplay = eglGetCurrentDisplay();
- EGLSyncKHR eglsync = fEGLCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
- if (EGL_NO_SYNC_KHR == eglsync) {
- ERRORF(reporter, "Failed to create EGLSync for EGL_SYNC_NATIVE_FENCE_ANDROID\n");
- return false;
- }
- surface->flush();
- GR_GL_CALL(fGLCtx->gl(), Flush());
- fFdHandle = fEGLDupNativeFenceFDANDROID(eglDisplay, eglsync);
- EGLint result = fEGLDestroySyncKHR(eglDisplay, eglsync);
- if (EGL_TRUE != result) {
- ERRORF(reporter, "Failed to delete EGLSync, error: %d\n", result);
- return false;
- }
- return true;
- }
- bool EGLTestHelper::importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
- sk_sp<SkSurface> surface) {
- EGLDisplay eglDisplay = eglGetCurrentDisplay();
- EGLint attr[] = {
- EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fdHandle,
- EGL_NONE
- };
- EGLSyncKHR eglsync = fEGLCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attr);
- if (EGL_NO_SYNC_KHR == eglsync) {
- ERRORF(reporter,
- "Failed to create EGLSync when importing EGL_SYNC_NATIVE_FENCE_FD_ANDROID\n");
- return false;
- }
- EGLint result = fEGLWaitSyncKHR(eglDisplay, eglsync, 0);
- if (EGL_TRUE != result) {
- ERRORF(reporter, "Failed called to eglWaitSyncKHR, error: %d\n", result);
- // Don't return false yet, try to delete the sync first
- }
- result = fEGLDestroySyncKHR(eglDisplay, eglsync);
- if (EGL_TRUE != result) {
- ERRORF(reporter, "Failed to delete EGLSync, error: %d\n", result);
- return false;
- }
- return true;
- }
- void EGLTestHelper::doClientSync() {
- sk_gpu_test::FenceSync* fenceSync = fGLCtx->fenceSync();
- sk_gpu_test::PlatformFence fence = fenceSync->insertFence();
- fenceSync->waitFence(fence);
- fenceSync->deleteFence(fence);
- }
- #define DECLARE_VK_PROC(name) PFN_vk##name fVk##name
- #define ACQUIRE_INST_VK_PROC(name) \
- fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fBackendContext.fInstance,\
- VK_NULL_HANDLE)); \
- if (fVk##name == nullptr) { \
- ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
- return false; \
- }
- #define ACQUIRE_DEVICE_VK_PROC(name) \
- fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \
- if (fVk##name == nullptr) { \
- ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
- return false; \
- }
- class VulkanTestHelper : public BaseTestHelper {
- public:
- VulkanTestHelper() {}
- ~VulkanTestHelper() override {}
- void releaseImage() override {
- if (VK_NULL_HANDLE == fDevice) {
- return;
- }
- if (fImage != VK_NULL_HANDLE) {
- fVkDestroyImage(fDevice, fImage, nullptr);
- fImage = VK_NULL_HANDLE;
- }
- if (fMemory != VK_NULL_HANDLE) {
- fVkFreeMemory(fDevice, fMemory, nullptr);
- fMemory = VK_NULL_HANDLE;
- }
- }
- void cleanup() override {
- fGrContext.reset();
- this->releaseImage();
- if (fSignalSemaphore != VK_NULL_HANDLE) {
- fVkDestroySemaphore(fDevice, fSignalSemaphore, nullptr);
- fSignalSemaphore = VK_NULL_HANDLE;
- }
- fBackendContext.fMemoryAllocator.reset();
- if (fDevice != VK_NULL_HANDLE) {
- fVkDeviceWaitIdle(fDevice);
- fVkDestroyDevice(fDevice, nullptr);
- fDevice = VK_NULL_HANDLE;
- }
- #ifdef SK_ENABLE_VK_LAYERS
- if (fDebugCallback != VK_NULL_HANDLE) {
- fDestroyDebugCallback(fBackendContext.fInstance, fDebugCallback, nullptr);
- }
- #endif
- if (fBackendContext.fInstance != VK_NULL_HANDLE) {
- fVkDestroyInstance(fBackendContext.fInstance, nullptr);
- fBackendContext.fInstance = VK_NULL_HANDLE;
- }
- delete fExtensions;
- sk_gpu_test::FreeVulkanFeaturesStructs(fFeatures);
- delete fFeatures;
- }
- bool init(skiatest::Reporter* reporter) override;
- void doClientSync() override {
- if (!fGrContext) {
- return;
- }
- fGrContext->priv().getGpu()->testingOnly_flushGpuAndSync();
- }
- bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) override;
- bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
- sk_sp<SkSurface>) override;
- sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) override;
- sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) override;
- void makeCurrent() override {}
- GrContext* grContext() override { return fGrContext.get(); }
- private:
- bool checkOptimalHardwareBuffer(skiatest::Reporter* reporter);
- bool importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer, bool forWrite,
- GrVkImageInfo* outImageInfo);
- bool setupSemaphoreForSignaling(skiatest::Reporter* reporter, GrBackendSemaphore*);
- bool exportSemaphore(skiatest::Reporter* reporter, const GrBackendSemaphore&);
- DECLARE_VK_PROC(DestroyInstance);
- DECLARE_VK_PROC(DeviceWaitIdle);
- DECLARE_VK_PROC(DestroyDevice);
- DECLARE_VK_PROC(GetPhysicalDeviceExternalSemaphoreProperties);
- DECLARE_VK_PROC(GetPhysicalDeviceImageFormatProperties2);
- DECLARE_VK_PROC(GetPhysicalDeviceMemoryProperties2);
- DECLARE_VK_PROC(GetAndroidHardwareBufferPropertiesANDROID);
- DECLARE_VK_PROC(CreateImage);
- DECLARE_VK_PROC(GetImageMemoryRequirements2);
- DECLARE_VK_PROC(DestroyImage);
- DECLARE_VK_PROC(AllocateMemory);
- DECLARE_VK_PROC(BindImageMemory2);
- DECLARE_VK_PROC(FreeMemory);
- DECLARE_VK_PROC(CreateSemaphore);
- DECLARE_VK_PROC(GetSemaphoreFdKHR);
- DECLARE_VK_PROC(ImportSemaphoreFdKHR);
- DECLARE_VK_PROC(DestroySemaphore);
- VkImage fImage = VK_NULL_HANDLE;
- VkDeviceMemory fMemory = VK_NULL_HANDLE;
- GrVkExtensions* fExtensions = nullptr;
- VkPhysicalDeviceFeatures2* fFeatures = nullptr;
- VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
- PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugCallback = nullptr;
- // We hold on to the semaphore so we can delete once the GPU is done.
- VkSemaphore fSignalSemaphore = VK_NULL_HANDLE;
- VkDevice fDevice = VK_NULL_HANDLE;
- GrVkBackendContext fBackendContext;
- sk_sp<GrContext> fGrContext;
- };
- bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
- PFN_vkGetInstanceProcAddr instProc;
- PFN_vkGetDeviceProcAddr devProc;
- if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
- return false;
- }
- auto getProc = [&instProc, &devProc](const char* proc_name,
- VkInstance instance, VkDevice device) {
- if (device != VK_NULL_HANDLE) {
- return devProc(device, proc_name);
- }
- return instProc(instance, proc_name);
- };
- fExtensions = new GrVkExtensions();
- fFeatures = new VkPhysicalDeviceFeatures2;
- memset(fFeatures, 0, sizeof(VkPhysicalDeviceFeatures2));
- fFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- fFeatures->pNext = nullptr;
- fBackendContext.fInstance = VK_NULL_HANDLE;
- fBackendContext.fDevice = VK_NULL_HANDLE;
- if (!sk_gpu_test::CreateVkBackendContext(getProc, &fBackendContext, fExtensions,
- fFeatures, &fDebugCallback)) {
- return false;
- }
- fDevice = fBackendContext.fDevice;
- if (fDebugCallback != VK_NULL_HANDLE) {
- fDestroyDebugCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(
- fBackendContext.fInstance, "vkDestroyDebugReportCallbackEXT");
- }
- ACQUIRE_INST_VK_PROC(DestroyInstance);
- ACQUIRE_INST_VK_PROC(DeviceWaitIdle);
- ACQUIRE_INST_VK_PROC(DestroyDevice);
- if (!fExtensions->hasExtension(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
- 2)) {
- return false;
- }
- if (!fExtensions->hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1)) {
- return false;
- }
- if (!fExtensions->hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
- return false;
- }
- if (!fExtensions->hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1)) {
- // return false;
- }
- ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties2);
- ACQUIRE_INST_VK_PROC(GetPhysicalDeviceImageFormatProperties2);
- ACQUIRE_INST_VK_PROC(GetPhysicalDeviceExternalSemaphoreProperties);
- ACQUIRE_DEVICE_VK_PROC(GetAndroidHardwareBufferPropertiesANDROID);
- ACQUIRE_DEVICE_VK_PROC(CreateImage);
- ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements2);
- ACQUIRE_DEVICE_VK_PROC(DestroyImage);
- ACQUIRE_DEVICE_VK_PROC(AllocateMemory);
- ACQUIRE_DEVICE_VK_PROC(BindImageMemory2);
- ACQUIRE_DEVICE_VK_PROC(FreeMemory);
- ACQUIRE_DEVICE_VK_PROC(CreateSemaphore);
- ACQUIRE_DEVICE_VK_PROC(GetSemaphoreFdKHR);
- ACQUIRE_DEVICE_VK_PROC(ImportSemaphoreFdKHR);
- ACQUIRE_DEVICE_VK_PROC(DestroySemaphore);
- fGrContext = GrContext::MakeVulkan(fBackendContext);
- REPORTER_ASSERT(reporter, fGrContext.get());
- if (!fGrContext) {
- return false;
- }
- return this->checkOptimalHardwareBuffer(reporter);
- }
- bool VulkanTestHelper::checkOptimalHardwareBuffer(skiatest::Reporter* reporter) {
- VkResult err;
- VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
- externalImageFormatInfo.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
- externalImageFormatInfo.pNext = nullptr;
- externalImageFormatInfo.handleType =
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
- //externalImageFormatInfo.handType = 0x80;
- // We will create the hardware buffer with gpu sampled so these usages should all be valid
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
- imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
- imageFormatInfo.pNext = &externalImageFormatInfo;
- imageFormatInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
- imageFormatInfo.type = VK_IMAGE_TYPE_2D;
- imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
- imageFormatInfo.usage = usageFlags;
- imageFormatInfo.flags = 0;
- VkAndroidHardwareBufferUsageANDROID hwbUsage;
- hwbUsage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
- hwbUsage.pNext = nullptr;
- VkExternalImageFormatProperties externalImgFormatProps;
- externalImgFormatProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
- externalImgFormatProps.pNext = &hwbUsage;
- VkImageFormatProperties2 imgFormProps;
- imgFormProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
- imgFormProps.pNext = &externalImgFormatProps;
- err = fVkGetPhysicalDeviceImageFormatProperties2(fBackendContext.fPhysicalDevice,
- &imageFormatInfo, &imgFormProps);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "vkGetPhysicalDeviceImageFormatProperites failed, err: %d", err);
- return false;
- }
- const VkImageFormatProperties& imageFormatProperties = imgFormProps.imageFormatProperties;
- REPORTER_ASSERT(reporter, DEV_W <= imageFormatProperties.maxExtent.width);
- REPORTER_ASSERT(reporter, DEV_H <= imageFormatProperties.maxExtent.height);
- const VkExternalMemoryProperties& externalImageFormatProps =
- externalImgFormatProps.externalMemoryProperties;
- REPORTER_ASSERT(reporter, SkToBool(VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT &
- externalImageFormatProps.externalMemoryFeatures));
- REPORTER_ASSERT(reporter, SkToBool(VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT &
- externalImageFormatProps.externalMemoryFeatures));
- REPORTER_ASSERT(reporter, SkToBool(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE &
- hwbUsage.androidHardwareBufferUsage));
- return true;
- }
- bool VulkanTestHelper::importHardwareBuffer(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer,
- bool forWrite,
- GrVkImageInfo* outImageInfo) {
- VkResult err;
- VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
- hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
- hwbFormatProps.pNext = nullptr;
- VkAndroidHardwareBufferPropertiesANDROID hwbProps;
- hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
- hwbProps.pNext = &hwbFormatProps;
- err = fVkGetAndroidHardwareBufferPropertiesANDROID(fDevice, buffer, &hwbProps);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "GetAndroidHardwareBufferPropertiesAndroid failed, err: %d", err);
- return false;
- }
- REPORTER_ASSERT(reporter, VK_FORMAT_R8G8B8A8_UNORM == hwbFormatProps.format);
- REPORTER_ASSERT(reporter,
- SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
- SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
- SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
- if (forWrite) {
- REPORTER_ASSERT(reporter,
- SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT & hwbFormatProps.formatFeatures));
- }
- bool useExternalFormat = VK_FORMAT_UNDEFINED == hwbFormatProps.format;
- const VkExternalFormatANDROID externalFormatInfo {
- VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, // sType
- nullptr, // pNext
- useExternalFormat ? hwbFormatProps.externalFormat : 0, // externalFormat
- };
- const VkExternalMemoryImageCreateInfo externalMemoryImageInfo {
- VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
- &externalFormatInfo, // pNext
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
- };
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (forWrite) {
- usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- }
- const VkImageCreateInfo imageCreateInfo = {
- VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
- &externalMemoryImageInfo, // pNext
- 0, // VkImageCreateFlags
- VK_IMAGE_TYPE_2D, // VkImageType
- hwbFormatProps.format, // VkFormat
- { DEV_W, DEV_H, 1 }, // VkExtent3D
- 1, // mipLevels
- 1, // arrayLayers
- VK_SAMPLE_COUNT_1_BIT, // samples
- VK_IMAGE_TILING_OPTIMAL, // VkImageTiling
- usageFlags, // VkImageUsageFlags
- VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode
- 0, // queueFamilyCount
- 0, // pQueueFamilyIndices
- VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
- };
- err = fVkCreateImage(fDevice, &imageCreateInfo, nullptr, &fImage);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "Create Image failed, err: %d", err);
- return false;
- }
- VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
- phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
- phyDevMemProps.pNext = nullptr;
- uint32_t typeIndex = 0;
- uint32_t heapIndex = 0;
- bool foundHeap = false;
- fVkGetPhysicalDeviceMemoryProperties2(fBackendContext.fPhysicalDevice, &phyDevMemProps);
- uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
- for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
- if (hwbProps.memoryTypeBits & (1 << i)) {
- const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
- uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
- typeIndex = i;
- heapIndex = pdmp.memoryTypes[i].heapIndex;
- foundHeap = true;
- }
- }
- }
- if (!foundHeap) {
- ERRORF(reporter, "Failed to find valid heap for imported memory");
- return false;
- }
- VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
- hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
- hwbImportInfo.pNext = nullptr;
- hwbImportInfo.buffer = buffer;
- VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
- dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
- dedicatedAllocInfo.pNext = &hwbImportInfo;
- dedicatedAllocInfo.image = fImage;
- dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
- VkMemoryAllocateInfo allocInfo = {
- VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
- &dedicatedAllocInfo, // pNext
- hwbProps.allocationSize, // allocationSize
- typeIndex, // memoryTypeIndex
- };
- err = fVkAllocateMemory(fDevice, &allocInfo, nullptr, &fMemory);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "AllocateMemory failed for imported buffer, err: %d", err);
- return false;
- }
- VkBindImageMemoryInfo bindImageInfo;
- bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
- bindImageInfo.pNext = nullptr;
- bindImageInfo.image = fImage;
- bindImageInfo.memory = fMemory;
- bindImageInfo.memoryOffset = 0;
- err = fVkBindImageMemory2(fDevice, 1, &bindImageInfo);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "BindImageMemory failed for imported buffer, err: %d", err);
- return false;
- }
- outImageInfo->fImage = fImage;
- outImageInfo->fAlloc = GrVkAlloc(fMemory, 0, hwbProps.allocationSize, 0);
- outImageInfo->fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- outImageInfo->fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- outImageInfo->fFormat = VK_FORMAT_R8G8B8A8_UNORM;
- outImageInfo->fLevelCount = 1;
- outImageInfo->fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
- return true;
- }
- sk_sp<SkImage> VulkanTestHelper::importHardwareBufferForRead(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) {
- GrVkImageInfo imageInfo;
- if (!this->importHardwareBuffer(reporter, buffer, false, &imageInfo)) {
- return nullptr;
- }
- GrBackendTexture backendTex(DEV_W, DEV_H, imageInfo);
- sk_sp<SkImage> wrappedImage = SkImage::MakeFromTexture(fGrContext.get(),
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- kRGBA_8888_SkColorType,
- kPremul_SkAlphaType,
- nullptr);
- if (!wrappedImage.get()) {
- ERRORF(reporter, "Failed to create wrapped Vulkan SkImage");
- return nullptr;
- }
- return wrappedImage;
- }
- bool VulkanTestHelper::flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter,
- sk_sp<SkSurface> surface) {
- surface->flush();
- surface.reset();
- GrBackendSemaphore semaphore;
- if (!this->setupSemaphoreForSignaling(reporter, &semaphore)) {
- return false;
- }
- GrFlushInfo info;
- info.fNumSemaphores = 1;
- info.fSignalSemaphores = &semaphore;
- GrSemaphoresSubmitted submitted = fGrContext->flush(info);
- if (GrSemaphoresSubmitted::kNo == submitted) {
- ERRORF(reporter, "Failing call to flush on GrContext");
- return false;
- }
- SkASSERT(semaphore.isInitialized());
- if (!this->exportSemaphore(reporter, semaphore)) {
- return false;
- }
- return true;
- }
- bool VulkanTestHelper::setupSemaphoreForSignaling(skiatest::Reporter* reporter,
- GrBackendSemaphore* beSemaphore) {
- // Query supported info
- VkPhysicalDeviceExternalSemaphoreInfo exSemInfo;
- exSemInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO;
- exSemInfo.pNext = nullptr;
- exSemInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- VkExternalSemaphoreProperties exSemProps;
- exSemProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
- exSemProps.pNext = nullptr;
- fVkGetPhysicalDeviceExternalSemaphoreProperties(fBackendContext.fPhysicalDevice, &exSemInfo,
- &exSemProps);
- if (!SkToBool(exSemProps.exportFromImportedHandleTypes &
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
- ERRORF(reporter, "HANDLE_TYPE_SYNC_FD not listed as exportFromImportedHandleTypes");
- return false;
- }
- if (!SkToBool(exSemProps.compatibleHandleTypes &
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
- ERRORF(reporter, "HANDLE_TYPE_SYNC_FD not listed as compatibleHandleTypes");
- return false;
- }
- if (!SkToBool(exSemProps.externalSemaphoreFeatures &
- VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) ||
- !SkToBool(exSemProps.externalSemaphoreFeatures &
- VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) {
- ERRORF(reporter, "HANDLE_TYPE_SYNC_FD doesn't support export and import feature");
- return false;
- }
- VkExportSemaphoreCreateInfo exportInfo;
- exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
- exportInfo.pNext = nullptr;
- exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- VkSemaphoreCreateInfo semaphoreInfo;
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.pNext = &exportInfo;
- semaphoreInfo.flags = 0;
- VkSemaphore semaphore;
- VkResult err = fVkCreateSemaphore(fDevice, &semaphoreInfo, nullptr, &semaphore);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "Failed to create signal semaphore, err: %d", err);
- return false;
- }
- beSemaphore->initVulkan(semaphore);
- return true;
- }
- bool VulkanTestHelper::exportSemaphore(skiatest::Reporter* reporter,
- const GrBackendSemaphore& beSemaphore) {
- VkSemaphore semaphore = beSemaphore.vkSemaphore();
- if (VK_NULL_HANDLE == semaphore) {
- ERRORF(reporter, "Invalid vulkan handle in export call");
- return false;
- }
- VkSemaphoreGetFdInfoKHR getFdInfo;
- getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
- getFdInfo.pNext = nullptr;
- getFdInfo.semaphore = semaphore;
- getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- VkResult err = fVkGetSemaphoreFdKHR(fDevice, &getFdInfo, &fFdHandle);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "Failed to export signal semaphore, err: %d", err);
- return false;
- }
- fSignalSemaphore = semaphore;
- return true;
- }
- bool VulkanTestHelper::importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
- sk_sp<SkSurface> surface) {
- VkSemaphoreCreateInfo semaphoreInfo;
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.pNext = nullptr;
- semaphoreInfo.flags = 0;
- VkSemaphore semaphore;
- VkResult err = fVkCreateSemaphore(fDevice, &semaphoreInfo, nullptr, &semaphore);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "Failed to create import semaphore, err: %d", err);
- return false;
- }
- VkImportSemaphoreFdInfoKHR importInfo;
- importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
- importInfo.pNext = nullptr;
- importInfo.semaphore = semaphore;
- importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
- importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- importInfo.fd = fdHandle;
- err = fVkImportSemaphoreFdKHR(fDevice, &importInfo);
- if (VK_SUCCESS != err) {
- ERRORF(reporter, "Failed to import semaphore, err: %d", err);
- return false;
- }
- GrBackendSemaphore beSemaphore;
- beSemaphore.initVulkan(semaphore);
- if (!surface->wait(1, &beSemaphore)) {
- ERRORF(reporter, "Failed to add wait semaphore to surface");
- fVkDestroySemaphore(fDevice, semaphore, nullptr);
- return false;
- }
- return true;
- }
- sk_sp<SkSurface> VulkanTestHelper::importHardwareBufferForWrite(skiatest::Reporter* reporter,
- AHardwareBuffer* buffer) {
- GrVkImageInfo imageInfo;
- if (!this->importHardwareBuffer(reporter, buffer, true, &imageInfo)) {
- return nullptr;
- }
- GrBackendTexture backendTex(DEV_W, DEV_H, imageInfo);
- sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(fGrContext.get(),
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- 0,
- kRGBA_8888_SkColorType,
- nullptr, nullptr);
- if (!surface.get()) {
- ERRORF(reporter, "Failed to create wrapped Vulkan SkSurface");
- return nullptr;
- }
- return surface;
- }
- static SkPMColor get_src_color(int x, int y) {
- SkASSERT(x >= 0 && x < DEV_W);
- SkASSERT(y >= 0 && y < DEV_H);
- U8CPU r = x;
- U8CPU g = y;
- U8CPU b = 0xc;
- U8CPU a = 0xff;
- switch ((x+y) % 5) {
- case 0:
- a = 0xff;
- break;
- case 1:
- a = 0x80;
- break;
- case 2:
- a = 0xCC;
- break;
- case 4:
- a = 0x01;
- break;
- case 3:
- a = 0x00;
- break;
- }
- a = 0xff;
- return SkPremultiplyARGBInline(a, r, g, b);
- }
- static SkBitmap make_src_bitmap() {
- static SkBitmap bmp;
- if (bmp.isNull()) {
- bmp.allocN32Pixels(DEV_W, DEV_H);
- intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
- for (int y = 0; y < DEV_H; ++y) {
- for (int x = 0; x < DEV_W; ++x) {
- SkPMColor* pixel = reinterpret_cast<SkPMColor*>(
- pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
- *pixel = get_src_color(x, y);
- }
- }
- }
- return bmp;
- }
- static bool check_read(skiatest::Reporter* reporter, const SkBitmap& srcBitmap,
- const SkBitmap& dstBitmap) {
- bool result = true;
- for (int y = 0; y < DEV_H && result; ++y) {
- for (int x = 0; x < DEV_W && result; ++x) {
- const uint32_t srcPixel = *srcBitmap.getAddr32(x, y);
- const uint32_t dstPixel = *dstBitmap.getAddr32(x, y);
- if (srcPixel != dstPixel) {
- ERRORF(reporter, "Expected readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
- x, y, srcPixel, dstPixel);
- result = false;
- } /*else {
- ERRORF(reporter, "Got good readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
- x, y, srcPixel, dstPixel);
- }*/
- }
- }
- return result;
- }
- static void cleanup_resources(BaseTestHelper* srcHelper, BaseTestHelper* dstHelper,
- AHardwareBuffer* buffer) {
- if (srcHelper) {
- srcHelper->cleanup();
- }
- if (dstHelper) {
- dstHelper->cleanup();
- }
- if (buffer) {
- AHardwareBuffer_release(buffer);
- }
- }
- enum class SrcType {
- kCPU,
- kEGL,
- kVulkan,
- };
- enum class DstType {
- kEGL,
- kVulkan,
- };
- void run_test(skiatest::Reporter* reporter, const GrContextOptions& options,
- SrcType srcType, DstType dstType, bool shareSyncs) {
- if (SrcType::kCPU == srcType && shareSyncs) {
- // We don't currently test this since we don't do any syncs in this case.
- return;
- }
- std::unique_ptr<BaseTestHelper> srcHelper;
- std::unique_ptr<BaseTestHelper> dstHelper;
- AHardwareBuffer* buffer = nullptr;
- if (SrcType::kVulkan == srcType) {
- srcHelper.reset(new VulkanTestHelper());
- } else if (SrcType::kEGL == srcType) {
- srcHelper.reset(new EGLTestHelper(options));
- }
- if (srcHelper) {
- if (!srcHelper->init(reporter)) {
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- }
- if (DstType::kVulkan == dstType) {
- dstHelper.reset(new VulkanTestHelper());
- } else {
- SkASSERT(DstType::kEGL == dstType);
- dstHelper.reset(new EGLTestHelper(options));
- }
- if (dstHelper) {
- if (!dstHelper->init(reporter)) {
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- // Setup SkBitmaps
- ///////////////////////////////////////////////////////////////////////////
- SkBitmap srcBitmap = make_src_bitmap();
- SkBitmap dstBitmapSurface;
- dstBitmapSurface.allocN32Pixels(DEV_W, DEV_H);
- SkBitmap dstBitmapFinal;
- dstBitmapFinal.allocN32Pixels(DEV_W, DEV_H);
- ///////////////////////////////////////////////////////////////////////////
- // Setup AHardwareBuffer
- ///////////////////////////////////////////////////////////////////////////
- AHardwareBuffer_Desc hwbDesc;
- hwbDesc.width = DEV_W;
- hwbDesc.height = DEV_H;
- hwbDesc.layers = 1;
- if (SrcType::kCPU == srcType) {
- hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
- AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
- } else {
- hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
- AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
- }
- hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
- // The following three are not used in the allocate
- hwbDesc.stride = 0;
- hwbDesc.rfu0= 0;
- hwbDesc.rfu1= 0;
- if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
- ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- if (SrcType::kCPU == srcType) {
- // Get actual desc for allocated buffer so we know the stride for uploading cpu data.
- AHardwareBuffer_describe(buffer, &hwbDesc);
- uint32_t* bufferAddr;
- if (AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
- reinterpret_cast<void**>(&bufferAddr))) {
- ERRORF(reporter, "Failed to lock hardware buffer");
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- int bbp = srcBitmap.bytesPerPixel();
- uint32_t* src = (uint32_t*)srcBitmap.getPixels();
- uint32_t* dst = bufferAddr;
- for (int y = 0; y < DEV_H; ++y) {
- memcpy(dst, src, DEV_W * bbp);
- src += DEV_W;
- dst += hwbDesc.stride;
- }
- for (int y = 0; y < DEV_H; ++y) {
- for (int x = 0; x < DEV_W; ++x) {
- const uint32_t srcPixel = *srcBitmap.getAddr32(x, y);
- uint32_t dstPixel = bufferAddr[y * hwbDesc.stride + x];
- if (srcPixel != dstPixel) {
- ERRORF(reporter, "CPU HWB Expected readpix (%d, %d) value 0x%08x, got 0x%08x.",
- x, y, srcPixel, dstPixel);
- }
- }
- }
- AHardwareBuffer_unlock(buffer, nullptr);
- } else {
- srcHelper->makeCurrent();
- sk_sp<SkSurface> surface = srcHelper->importHardwareBufferForWrite(reporter, buffer);
- if (!surface) {
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- sk_sp<SkImage> srcBmpImage = SkImage::MakeFromBitmap(srcBitmap);
- surface->getCanvas()->drawImage(srcBmpImage, 0, 0);
- // If we are testing sharing of syncs, don't do a read here since it forces sychronization
- // to occur.
- if (!shareSyncs) {
- bool readResult = surface->readPixels(dstBitmapSurface, 0, 0);
- if (!readResult) {
- ERRORF(reporter, "Read Pixels on surface failed");
- surface.reset();
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, dstBitmapSurface));
- }
- ///////////////////////////////////////////////////////////////////////////
- // Cleanup GL/EGL and add syncs
- ///////////////////////////////////////////////////////////////////////////
- if (shareSyncs) {
- if (!srcHelper->flushSurfaceAndSignalSemaphore(reporter, std::move(surface))) {
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- } else {
- surface.reset();
- srcHelper->doClientSync();
- srcHelper->releaseImage();
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- // Import the HWB into backend and draw it to a surface
- ///////////////////////////////////////////////////////////////////////////
- dstHelper->makeCurrent();
- sk_sp<SkImage> wrappedImage = dstHelper->importHardwareBufferForRead(reporter, buffer);
- if (!wrappedImage) {
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- GrContext* grContext = dstHelper->grContext();
- // Make SkSurface to render wrapped HWB into.
- SkImageInfo imageInfo = SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType,
- kPremul_SkAlphaType, nullptr);
- sk_sp<SkSurface> dstSurf = SkSurface::MakeRenderTarget(grContext,
- SkBudgeted::kNo, imageInfo, 0,
- kTopLeft_GrSurfaceOrigin,
- nullptr, false);
- if (!dstSurf.get()) {
- ERRORF(reporter, "Failed to create destination SkSurface");
- wrappedImage.reset();
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- if (shareSyncs) {
- if (!dstHelper->importAndWaitOnSemaphore(reporter, srcHelper->getFdHandle(), dstSurf)) {
- wrappedImage.reset();
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- }
- dstSurf->getCanvas()->drawImage(wrappedImage, 0, 0);
- bool readResult = dstSurf->readPixels(dstBitmapFinal, 0, 0);
- if (!readResult) {
- ERRORF(reporter, "Read Pixels failed");
- wrappedImage.reset();
- dstSurf.reset();
- dstHelper->doClientSync();
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- return;
- }
- REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, dstBitmapFinal));
- dstSurf.reset();
- wrappedImage.reset();
- dstHelper->doClientSync();
- cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_CPU_Vulkan, reporter, options) {
- run_test(reporter, options, SrcType::kCPU, DstType::kVulkan, false);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_EGL_Vulkan, reporter, options) {
- run_test(reporter, options, SrcType::kEGL, DstType::kVulkan, false);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_Vulkan, reporter, options) {
- run_test(reporter, options, SrcType::kVulkan, DstType::kVulkan, false);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_CPU_EGL, reporter, options) {
- run_test(reporter, options, SrcType::kCPU, DstType::kEGL, false);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_EGL_EGL, reporter, options) {
- run_test(reporter, options, SrcType::kEGL, DstType::kEGL, false);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_EGL, reporter, options) {
- run_test(reporter, options, SrcType::kVulkan, DstType::kEGL, false);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_EGL_EGL_Syncs, reporter, options) {
- run_test(reporter, options, SrcType::kEGL, DstType::kEGL, true);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_EGL_Syncs, reporter, options) {
- run_test(reporter, options, SrcType::kVulkan, DstType::kEGL, true);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_EGL_Vulkan_Syncs, reporter, options) {
- run_test(reporter, options, SrcType::kEGL, DstType::kVulkan, true);
- }
- DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_Vulkan_Syncs, reporter, options) {
- run_test(reporter, options, SrcType::kVulkan, DstType::kVulkan, true);
- }
- #endif
|