Loading graphics/allocator/aidl/vts/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_test { defaults: [ "VtsHalTargetTestDefaults", "use_libaidlvintf_gtest_helper_static", "hwui_defaults", ], srcs: [ "VtsHalGraphicsAllocatorAidl_TargetTest.cpp", Loading @@ -46,10 +47,15 @@ cc_test { "libgui", "libhidlbase", "libvndksupport", "libnativewindow", ], static_libs: [ "libaidlcommonsupport", "libgtest", "libhwui", ], header_libs: [ "libhwui_internal_headers", ], cflags: [ "-Wall", Loading graphics/allocator/aidl/vts/VtsHalGraphicsAllocatorAidl_TargetTest.cpp +224 −35 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #undef LOG_TAG #define LOG_TAG "VtsHalGraphicsAllocatorAidl_TargetTest" #include <aidl/Vintf.h> Loading @@ -28,6 +29,10 @@ #include <gtest/gtest.h> #include <hidl/GtestPrinter.h> #include <hidl/ServiceManagement.h> #include <hwui/Bitmap.h> #include <renderthread/EglManager.h> #include <utils/GLUtils.h> #include <vndk/hardware_buffer.h> #include <initializer_list> #include <optional> #include <string> Loading @@ -38,6 +43,10 @@ using namespace aidl::android::hardware::graphics::common; using namespace android; using namespace android::hardware; using namespace android::hardware::graphics::mapper::V4_0; using android::uirenderer::AutoEglImage; using android::uirenderer::AutoGLFramebuffer; using android::uirenderer::AutoSkiaGlTexture; using android::uirenderer::renderthread::EglManager; static constexpr uint64_t pack(const std::initializer_list<BufferUsage>& usages) { uint64_t ret = 0; Loading @@ -56,13 +65,15 @@ class BufferHandle { native_handle_t* mRawHandle; bool mImported = false; uint32_t mStride; const IMapper::BufferDescriptorInfo mInfo; BufferHandle(const BufferHandle&) = delete; void operator=(const BufferHandle&) = delete; public: BufferHandle(const sp<IMapper> mapper, native_handle_t* handle, bool imported, uint32_t stride) : mMapper(mapper), mRawHandle(handle), mImported(imported), mStride(stride) {} BufferHandle(const sp<IMapper> mapper, native_handle_t* handle, bool imported, uint32_t stride, const IMapper::BufferDescriptorInfo& info) : mMapper(mapper), mRawHandle(handle), mImported(imported), mStride(stride), mInfo(info) {} ~BufferHandle() { if (mRawHandle == nullptr) return; Loading @@ -77,27 +88,47 @@ class BufferHandle { } uint32_t stride() const { return mStride; } AHardwareBuffer_Desc describe() const { return { .width = mInfo.width, .height = mInfo.height, .layers = mInfo.layerCount, .format = static_cast<uint32_t>(mInfo.format), .usage = mInfo.usage, .stride = stride(), .rfu0 = 0, .rfu1 = 0, }; } class GraphicsAllocatorAidlTests : public ::testing::TestWithParam<std::tuple<std::string, std::string>> { AHardwareBuffer* createAHardwareBuffer() const { auto desc = describe(); AHardwareBuffer* buffer = nullptr; int err = AHardwareBuffer_createFromHandle( &desc, mRawHandle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &buffer); EXPECT_EQ(0, err) << "Failed to AHardwareBuffer_createFromHandle"; return err ? nullptr : buffer; } }; class GraphicsTestsBase { private: std::shared_ptr<IAllocator> mAllocator; sp<IMapper> mMapper; public: void SetUp() override { protected: void Initialize(std::string allocatorService, std::string mapperService) { mAllocator = IAllocator::fromBinder( ndk::SpAIBinder(AServiceManager_checkService(std::get<0>(GetParam()).c_str()))); mMapper = IMapper::getService(std::get<1>(GetParam())); ndk::SpAIBinder(AServiceManager_checkService(allocatorService.c_str()))); mMapper = IMapper::getService(mapperService); ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service"; ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service"; ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode"; } void TearDown() override {} public: BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) { BufferDescriptor descriptor; mMapper->createDescriptor( Loading @@ -109,18 +140,7 @@ class GraphicsAllocatorAidlTests return descriptor; } native_handle_t* importBuffer(const hidl_handle& rawHandle) { native_handle_t* bufferHandle = nullptr; mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) { ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p" << rawHandle.getNativeHandle(); bufferHandle = static_cast<native_handle_t*>(tmpBuffer); }); return bufferHandle; } std::unique_ptr<BufferHandle> allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = false) { std::unique_ptr<BufferHandle> allocate(const IMapper::BufferDescriptorInfo& descriptorInfo) { auto descriptor = createDescriptor(descriptorInfo); if (::testing::Test::HasFatalFailure()) { return nullptr; Loading @@ -139,19 +159,80 @@ class GraphicsAllocatorAidlTests } return nullptr; } else { if (import) { native_handle_t* importedHandle = importBuffer(makeFromAidl(result.buffers[0])); if (importedHandle) { return std::make_unique<BufferHandle>(mMapper, importedHandle, true, result.stride); } else { return nullptr; return std::make_unique<BufferHandle>(mMapper, dupFromAidl(result.buffers[0]), false, result.stride, descriptorInfo); } } else { return std::make_unique<BufferHandle>(mMapper, dupFromAidl(result.buffers[0]), false, result.stride); } bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) { bool ret = false; EXPECT_TRUE(mMapper->isSupported(descriptorInfo, [&](auto error, bool supported) { ASSERT_EQ(Error::NONE, error); ret = supported; }) .isOk()); return ret; } }; class GraphicsAllocatorAidlTests : public GraphicsTestsBase, public ::testing::TestWithParam<std::tuple<std::string, std::string>> { public: void SetUp() override { Initialize(std::get<0>(GetParam()), std::get<1>(GetParam())); } void TearDown() override {} }; struct FlushMethod { std::string name; std::function<void(EglManager&)> func; }; class GraphicsFrontBufferTests : public GraphicsTestsBase, public ::testing::TestWithParam<std::tuple<std::string, std::string, FlushMethod>> { private: EglManager eglManager; std::function<void(EglManager&)> flush; public: void SetUp() override { Initialize(std::get<0>(GetParam()), std::get<1>(GetParam())); flush = std::get<2>(GetParam()).func; eglManager.initialize(); } void TearDown() override { eglManager.destroy(); } void fillWithGpu(AHardwareBuffer* buffer, float red, float green, float blue, float alpha) { const EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer); AutoEglImage eglImage(eglManager.eglDisplay(), clientBuffer); AutoSkiaGlTexture glTexture; AutoGLFramebuffer glFbo; glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage.image); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture.mTexture, 0); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); glViewport(0, 0, desc.width, desc.height); glDisable(GL_STENCIL_TEST); glDisable(GL_SCISSOR_TEST); glClearColor(red, green, blue, alpha); glClear(GL_COLOR_BUFFER_BIT); flush(eglManager); } void fillWithGpu(AHardwareBuffer* buffer, /*RGBA*/ uint32_t color) { // Keep it simple for now static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); float a = float((color >> 24) & 0xff) / 255.0f; float b = float((color >> 16) & 0xff) / 255.0f; float g = float((color >> 8) & 0xff) / 255.0f; float r = float((color)&0xff) / 255.0f; fillWithGpu(buffer, r, g, b, a); } }; Loading Loading @@ -181,9 +262,117 @@ TEST_P(GraphicsAllocatorAidlTests, CanAllocate) { EXPECT_GE(buffer->stride(), 64); } TEST_P(GraphicsFrontBufferTests, FrontBufferGpuToCpu) { IMapper::BufferDescriptorInfo info{ .name = "CPU_8888", .width = 64, .height = 64, .layerCount = 1, .format = cast(PixelFormat::RGBA_8888), .usage = pack({BufferUsage::GPU_RENDER_TARGET, BufferUsage::CPU_READ_OFTEN, BufferUsage::FRONT_BUFFER}), .reservedSize = 0, }; const bool supported = isSupported(info); auto buffer = allocate(info); if (!supported) { ASSERT_EQ(nullptr, buffer.get()) << "Allocation succeeded, but IMapper::isSupported was false"; } else { ASSERT_NE(nullptr, buffer.get()) << "Allocation failed, but IMapper::isSupported was true"; } AHardwareBuffer* ahb = buffer->createAHardwareBuffer(); ASSERT_NE(nullptr, ahb); // We draw 3 times with 3 different colors to ensure the flush is consistently flushing. // Particularly for glFlush() there's occasions where it seems something triggers a flush // to happen even though glFlush itself isn't consistently doing so, but for FRONT_BUFFER // bound buffers it is supposed to consistently flush. for (uint32_t color : {0xFF0000FFu, 0x00FF00FFu, 0x0000FFFFu}) { fillWithGpu(ahb, color); uint32_t* addr; ASSERT_EQ(0, AHardwareBuffer_lock(ahb, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, nullptr, (void**)&addr)); // Spot check a few pixels EXPECT_EQ(color, addr[0]); EXPECT_EQ(color, addr[32 + (32 * buffer->stride())]); AHardwareBuffer_unlock(ahb, nullptr); } AHardwareBuffer_release(ahb); } TEST_P(GraphicsFrontBufferTests, FrontBufferGpuToGpu) { IMapper::BufferDescriptorInfo info{ .name = "CPU_8888", .width = 64, .height = 64, .layerCount = 1, .format = cast(PixelFormat::RGBA_8888), .usage = pack({BufferUsage::GPU_RENDER_TARGET, BufferUsage::GPU_TEXTURE, BufferUsage::FRONT_BUFFER}), .reservedSize = 0, }; const bool supported = isSupported(info); auto buffer = allocate(info); if (!supported) { ASSERT_EQ(nullptr, buffer.get()) << "Allocation succeeded, but IMapper::isSupported was false"; } else { ASSERT_NE(nullptr, buffer.get()) << "Allocation failed, but IMapper::isSupported was true"; } AHardwareBuffer* ahb = buffer->createAHardwareBuffer(); ASSERT_NE(nullptr, ahb); // We draw 3 times with 3 different colors to ensure the flush is consistently flushing. // Particularly for glFlush() there's occasions where it seems something triggers a flush // to happen even though glFlush itself isn't consistently doing so, but for FRONT_BUFFER // bound buffers it is supposed to consistently flush. for (uint32_t color : {0xFF0000FFu, 0x00FF00FFu, 0x0000FFFFu}) { fillWithGpu(ahb, color); sk_sp<Bitmap> hwBitmap = Bitmap::createFrom(ahb, SkColorSpace::MakeSRGB()); SkBitmap cpuBitmap = hwBitmap->getSkBitmap(); // Spot check a few pixels EXPECT_EQ(color, *cpuBitmap.getAddr32(0, 0)); EXPECT_EQ(color, *cpuBitmap.getAddr32(16, 30)); } AHardwareBuffer_release(ahb); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsAllocatorAidlTests); INSTANTIATE_TEST_CASE_P( PerInstance, GraphicsAllocatorAidlTests, testing::Combine(testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)), testing::ValuesIn(getAllHalInstanceNames(IMapper::descriptor))), PrintInstanceTupleNameToString<>); const auto FlushMethodsValues = testing::Values( FlushMethod{"glFinish", [](EglManager&) { glFinish(); }}, FlushMethod{"glFlush", [](EglManager&) { glFlush(); // Since the goal is to verify that glFlush() actually flushes, we can't // wait on any sort of fence since that will change behavior So instead we // just sleep & hope sleep(1); }}, FlushMethod{"eglClientWaitSync", [](EglManager& eglManager) { EGLDisplay display = eglManager.eglDisplay(); EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); eglDestroySyncKHR(display, fence); }}); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsFrontBufferTests); INSTANTIATE_TEST_CASE_P( PerInstance, GraphicsFrontBufferTests, testing::Combine(testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)), testing::ValuesIn(getAllHalInstanceNames(IMapper::descriptor)), FlushMethodsValues), [](auto info) -> std::string { std::string name = std::to_string(info.index) + "/" + std::get<2>(info.param).name; return Sanitize(name); }); No newline at end of file Loading
graphics/allocator/aidl/vts/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_test { defaults: [ "VtsHalTargetTestDefaults", "use_libaidlvintf_gtest_helper_static", "hwui_defaults", ], srcs: [ "VtsHalGraphicsAllocatorAidl_TargetTest.cpp", Loading @@ -46,10 +47,15 @@ cc_test { "libgui", "libhidlbase", "libvndksupport", "libnativewindow", ], static_libs: [ "libaidlcommonsupport", "libgtest", "libhwui", ], header_libs: [ "libhwui_internal_headers", ], cflags: [ "-Wall", Loading
graphics/allocator/aidl/vts/VtsHalGraphicsAllocatorAidl_TargetTest.cpp +224 −35 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #undef LOG_TAG #define LOG_TAG "VtsHalGraphicsAllocatorAidl_TargetTest" #include <aidl/Vintf.h> Loading @@ -28,6 +29,10 @@ #include <gtest/gtest.h> #include <hidl/GtestPrinter.h> #include <hidl/ServiceManagement.h> #include <hwui/Bitmap.h> #include <renderthread/EglManager.h> #include <utils/GLUtils.h> #include <vndk/hardware_buffer.h> #include <initializer_list> #include <optional> #include <string> Loading @@ -38,6 +43,10 @@ using namespace aidl::android::hardware::graphics::common; using namespace android; using namespace android::hardware; using namespace android::hardware::graphics::mapper::V4_0; using android::uirenderer::AutoEglImage; using android::uirenderer::AutoGLFramebuffer; using android::uirenderer::AutoSkiaGlTexture; using android::uirenderer::renderthread::EglManager; static constexpr uint64_t pack(const std::initializer_list<BufferUsage>& usages) { uint64_t ret = 0; Loading @@ -56,13 +65,15 @@ class BufferHandle { native_handle_t* mRawHandle; bool mImported = false; uint32_t mStride; const IMapper::BufferDescriptorInfo mInfo; BufferHandle(const BufferHandle&) = delete; void operator=(const BufferHandle&) = delete; public: BufferHandle(const sp<IMapper> mapper, native_handle_t* handle, bool imported, uint32_t stride) : mMapper(mapper), mRawHandle(handle), mImported(imported), mStride(stride) {} BufferHandle(const sp<IMapper> mapper, native_handle_t* handle, bool imported, uint32_t stride, const IMapper::BufferDescriptorInfo& info) : mMapper(mapper), mRawHandle(handle), mImported(imported), mStride(stride), mInfo(info) {} ~BufferHandle() { if (mRawHandle == nullptr) return; Loading @@ -77,27 +88,47 @@ class BufferHandle { } uint32_t stride() const { return mStride; } AHardwareBuffer_Desc describe() const { return { .width = mInfo.width, .height = mInfo.height, .layers = mInfo.layerCount, .format = static_cast<uint32_t>(mInfo.format), .usage = mInfo.usage, .stride = stride(), .rfu0 = 0, .rfu1 = 0, }; } class GraphicsAllocatorAidlTests : public ::testing::TestWithParam<std::tuple<std::string, std::string>> { AHardwareBuffer* createAHardwareBuffer() const { auto desc = describe(); AHardwareBuffer* buffer = nullptr; int err = AHardwareBuffer_createFromHandle( &desc, mRawHandle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &buffer); EXPECT_EQ(0, err) << "Failed to AHardwareBuffer_createFromHandle"; return err ? nullptr : buffer; } }; class GraphicsTestsBase { private: std::shared_ptr<IAllocator> mAllocator; sp<IMapper> mMapper; public: void SetUp() override { protected: void Initialize(std::string allocatorService, std::string mapperService) { mAllocator = IAllocator::fromBinder( ndk::SpAIBinder(AServiceManager_checkService(std::get<0>(GetParam()).c_str()))); mMapper = IMapper::getService(std::get<1>(GetParam())); ndk::SpAIBinder(AServiceManager_checkService(allocatorService.c_str()))); mMapper = IMapper::getService(mapperService); ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service"; ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service"; ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode"; } void TearDown() override {} public: BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) { BufferDescriptor descriptor; mMapper->createDescriptor( Loading @@ -109,18 +140,7 @@ class GraphicsAllocatorAidlTests return descriptor; } native_handle_t* importBuffer(const hidl_handle& rawHandle) { native_handle_t* bufferHandle = nullptr; mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) { ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p" << rawHandle.getNativeHandle(); bufferHandle = static_cast<native_handle_t*>(tmpBuffer); }); return bufferHandle; } std::unique_ptr<BufferHandle> allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = false) { std::unique_ptr<BufferHandle> allocate(const IMapper::BufferDescriptorInfo& descriptorInfo) { auto descriptor = createDescriptor(descriptorInfo); if (::testing::Test::HasFatalFailure()) { return nullptr; Loading @@ -139,19 +159,80 @@ class GraphicsAllocatorAidlTests } return nullptr; } else { if (import) { native_handle_t* importedHandle = importBuffer(makeFromAidl(result.buffers[0])); if (importedHandle) { return std::make_unique<BufferHandle>(mMapper, importedHandle, true, result.stride); } else { return nullptr; return std::make_unique<BufferHandle>(mMapper, dupFromAidl(result.buffers[0]), false, result.stride, descriptorInfo); } } else { return std::make_unique<BufferHandle>(mMapper, dupFromAidl(result.buffers[0]), false, result.stride); } bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) { bool ret = false; EXPECT_TRUE(mMapper->isSupported(descriptorInfo, [&](auto error, bool supported) { ASSERT_EQ(Error::NONE, error); ret = supported; }) .isOk()); return ret; } }; class GraphicsAllocatorAidlTests : public GraphicsTestsBase, public ::testing::TestWithParam<std::tuple<std::string, std::string>> { public: void SetUp() override { Initialize(std::get<0>(GetParam()), std::get<1>(GetParam())); } void TearDown() override {} }; struct FlushMethod { std::string name; std::function<void(EglManager&)> func; }; class GraphicsFrontBufferTests : public GraphicsTestsBase, public ::testing::TestWithParam<std::tuple<std::string, std::string, FlushMethod>> { private: EglManager eglManager; std::function<void(EglManager&)> flush; public: void SetUp() override { Initialize(std::get<0>(GetParam()), std::get<1>(GetParam())); flush = std::get<2>(GetParam()).func; eglManager.initialize(); } void TearDown() override { eglManager.destroy(); } void fillWithGpu(AHardwareBuffer* buffer, float red, float green, float blue, float alpha) { const EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer); AutoEglImage eglImage(eglManager.eglDisplay(), clientBuffer); AutoSkiaGlTexture glTexture; AutoGLFramebuffer glFbo; glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage.image); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture.mTexture, 0); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); glViewport(0, 0, desc.width, desc.height); glDisable(GL_STENCIL_TEST); glDisable(GL_SCISSOR_TEST); glClearColor(red, green, blue, alpha); glClear(GL_COLOR_BUFFER_BIT); flush(eglManager); } void fillWithGpu(AHardwareBuffer* buffer, /*RGBA*/ uint32_t color) { // Keep it simple for now static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); float a = float((color >> 24) & 0xff) / 255.0f; float b = float((color >> 16) & 0xff) / 255.0f; float g = float((color >> 8) & 0xff) / 255.0f; float r = float((color)&0xff) / 255.0f; fillWithGpu(buffer, r, g, b, a); } }; Loading Loading @@ -181,9 +262,117 @@ TEST_P(GraphicsAllocatorAidlTests, CanAllocate) { EXPECT_GE(buffer->stride(), 64); } TEST_P(GraphicsFrontBufferTests, FrontBufferGpuToCpu) { IMapper::BufferDescriptorInfo info{ .name = "CPU_8888", .width = 64, .height = 64, .layerCount = 1, .format = cast(PixelFormat::RGBA_8888), .usage = pack({BufferUsage::GPU_RENDER_TARGET, BufferUsage::CPU_READ_OFTEN, BufferUsage::FRONT_BUFFER}), .reservedSize = 0, }; const bool supported = isSupported(info); auto buffer = allocate(info); if (!supported) { ASSERT_EQ(nullptr, buffer.get()) << "Allocation succeeded, but IMapper::isSupported was false"; } else { ASSERT_NE(nullptr, buffer.get()) << "Allocation failed, but IMapper::isSupported was true"; } AHardwareBuffer* ahb = buffer->createAHardwareBuffer(); ASSERT_NE(nullptr, ahb); // We draw 3 times with 3 different colors to ensure the flush is consistently flushing. // Particularly for glFlush() there's occasions where it seems something triggers a flush // to happen even though glFlush itself isn't consistently doing so, but for FRONT_BUFFER // bound buffers it is supposed to consistently flush. for (uint32_t color : {0xFF0000FFu, 0x00FF00FFu, 0x0000FFFFu}) { fillWithGpu(ahb, color); uint32_t* addr; ASSERT_EQ(0, AHardwareBuffer_lock(ahb, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, nullptr, (void**)&addr)); // Spot check a few pixels EXPECT_EQ(color, addr[0]); EXPECT_EQ(color, addr[32 + (32 * buffer->stride())]); AHardwareBuffer_unlock(ahb, nullptr); } AHardwareBuffer_release(ahb); } TEST_P(GraphicsFrontBufferTests, FrontBufferGpuToGpu) { IMapper::BufferDescriptorInfo info{ .name = "CPU_8888", .width = 64, .height = 64, .layerCount = 1, .format = cast(PixelFormat::RGBA_8888), .usage = pack({BufferUsage::GPU_RENDER_TARGET, BufferUsage::GPU_TEXTURE, BufferUsage::FRONT_BUFFER}), .reservedSize = 0, }; const bool supported = isSupported(info); auto buffer = allocate(info); if (!supported) { ASSERT_EQ(nullptr, buffer.get()) << "Allocation succeeded, but IMapper::isSupported was false"; } else { ASSERT_NE(nullptr, buffer.get()) << "Allocation failed, but IMapper::isSupported was true"; } AHardwareBuffer* ahb = buffer->createAHardwareBuffer(); ASSERT_NE(nullptr, ahb); // We draw 3 times with 3 different colors to ensure the flush is consistently flushing. // Particularly for glFlush() there's occasions where it seems something triggers a flush // to happen even though glFlush itself isn't consistently doing so, but for FRONT_BUFFER // bound buffers it is supposed to consistently flush. for (uint32_t color : {0xFF0000FFu, 0x00FF00FFu, 0x0000FFFFu}) { fillWithGpu(ahb, color); sk_sp<Bitmap> hwBitmap = Bitmap::createFrom(ahb, SkColorSpace::MakeSRGB()); SkBitmap cpuBitmap = hwBitmap->getSkBitmap(); // Spot check a few pixels EXPECT_EQ(color, *cpuBitmap.getAddr32(0, 0)); EXPECT_EQ(color, *cpuBitmap.getAddr32(16, 30)); } AHardwareBuffer_release(ahb); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsAllocatorAidlTests); INSTANTIATE_TEST_CASE_P( PerInstance, GraphicsAllocatorAidlTests, testing::Combine(testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)), testing::ValuesIn(getAllHalInstanceNames(IMapper::descriptor))), PrintInstanceTupleNameToString<>); const auto FlushMethodsValues = testing::Values( FlushMethod{"glFinish", [](EglManager&) { glFinish(); }}, FlushMethod{"glFlush", [](EglManager&) { glFlush(); // Since the goal is to verify that glFlush() actually flushes, we can't // wait on any sort of fence since that will change behavior So instead we // just sleep & hope sleep(1); }}, FlushMethod{"eglClientWaitSync", [](EglManager& eglManager) { EGLDisplay display = eglManager.eglDisplay(); EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); eglDestroySyncKHR(display, fence); }}); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsFrontBufferTests); INSTANTIATE_TEST_CASE_P( PerInstance, GraphicsFrontBufferTests, testing::Combine(testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)), testing::ValuesIn(getAllHalInstanceNames(IMapper::descriptor)), FlushMethodsValues), [](auto info) -> std::string { std::string name = std::to_string(info.index) + "/" + std::get<2>(info.param).name; return Sanitize(name); }); No newline at end of file