1 // Copyright (C) 2023 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <gmock/gmock.h> 18 #include <gtest/gtest.h> 19 20 #include <android-base/expected.h> 21 #include <inttypes.h> 22 23 #include <future> 24 #include <memory> 25 #include <optional> 26 #include <string> 27 #include <thread> 28 #include <unordered_set> 29 #include <variant> 30 31 // clang-format off 32 #include <EGL/egl.h> 33 #include <EGL/eglext.h> 34 #include "OpenGLESDispatch/gldefs.h" 35 #include "OpenGLESDispatch/gles_functions.h" 36 #include "OpenGLESDispatch/RenderEGL_functions.h" 37 #include "OpenGLESDispatch/RenderEGL_extensions_functions.h" 38 39 #define VULKAN_HPP_NAMESPACE vkhpp 40 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 41 #define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1 42 #define VULKAN_HPP_NO_CONSTRUCTORS 43 #define VULKAN_HPP_NO_EXCEPTIONS 44 #include <vulkan/vulkan.hpp> 45 #include <vulkan/vk_android_native_buffer.h> 46 // clang-format on 47 48 #include "Sync.h" 49 #include "drm_fourcc.h" 50 #include "gfxstream/guest/ANativeWindow.h" 51 #include "gfxstream/guest/Gralloc.h" 52 #include "gfxstream/guest/RenderControlApi.h" 53 54 namespace gfxstream { 55 namespace tests { 56 57 constexpr const bool kSaveImagesIfComparisonFailed = false; 58 59 MATCHER(IsOk, "an ok result") { 60 auto& result = arg; 61 if (!result.ok()) { 62 *result_listener << "which is an error with message: \"" 63 << result.error() 64 << "\""; 65 return false; 66 } 67 return true; 68 } 69 70 MATCHER(IsError, "an error result") { 71 auto& result = arg; 72 if (result.ok()) { 73 *result_listener << "which is an ok result"; 74 return false; 75 } 76 return true; 77 } 78 79 MATCHER(IsVkSuccess, "is VK_SUCCESS") { 80 auto& result = arg; 81 if (result != vkhpp::Result::eSuccess) { 82 *result_listener << "which is " << vkhpp::to_string(result); 83 return false; 84 } 85 return true; 86 } 87 88 MATCHER(IsValidHandle, "a non-null handle") { 89 auto& result = arg; 90 if (!result) { 91 *result_listener << "which is a VK_NULL_HANDLE"; 92 return false; 93 } 94 return true; 95 } 96 97 struct Ok {}; 98 99 template <typename GlType> 100 using GlExpected = android::base::expected<GlType, std::string>; 101 102 #define GL_ASSERT(x) \ 103 ({ \ 104 auto gl_result = (x); \ 105 if (!gl_result.ok()) { \ 106 ASSERT_THAT(gl_result, IsOk()); \ 107 } \ 108 std::move(gl_result.value()); \ 109 }) 110 111 #define GL_EXPECT(x) \ 112 ({ \ 113 auto gl_result = (x); \ 114 if (!gl_result.ok()) { \ 115 return android::base::unexpected(gl_result.error()); \ 116 } \ 117 std::move(gl_result.value()); \ 118 }) 119 120 template <typename VkType> 121 using VkExpected = android::base::expected<VkType, vkhpp::Result>; 122 123 #define VK_ASSERT(x) \ 124 ({ \ 125 auto vk_expect_android_base_expected = (x); \ 126 if (!vk_expect_android_base_expected.ok()) { \ 127 ASSERT_THAT(vk_expect_android_base_expected.ok(), ::testing::IsTrue()); \ 128 }; \ 129 std::move(vk_expect_android_base_expected.value()); \ 130 }) 131 132 #define VK_ASSERT_RV(x) \ 133 ({ \ 134 auto vkhpp_result_value = (x); \ 135 ASSERT_THAT(vkhpp_result_value.result, IsVkSuccess()); \ 136 std::move(vkhpp_result_value.value); \ 137 }) 138 139 #define VK_EXPECT_RESULT(x) \ 140 ({ \ 141 auto vkhpp_result = (x); \ 142 if (vkhpp_result != vkhpp::Result::eSuccess) { \ 143 return android::base::unexpected(vkhpp_result); \ 144 } \ 145 }) 146 147 #define VK_EXPECT_RV(x) \ 148 ({ \ 149 auto vkhpp_result_value = (x); \ 150 if (vkhpp_result_value.result != vkhpp::Result::eSuccess) { \ 151 return android::base::unexpected(vkhpp_result_value.result); \ 152 } \ 153 std::move(vkhpp_result_value.value); \ 154 }) 155 156 #define VK_TRY(x) \ 157 ({ \ 158 auto vk_try_android_base_expected = (x); \ 159 if (!vk_try_android_base_expected.ok()) { \ 160 return android::base::unexpected(vk_try_android_base_expected.error()); \ 161 } \ 162 std::move(vk_try_android_base_expected.value()); \ 163 }) 164 165 #define VK_TRY_RESULT(x) \ 166 ({ \ 167 auto vkhpp_result = (x); \ 168 if (vkhpp_result != vkhpp::Result::eSuccess) { \ 169 return vkhpp_result; \ 170 } \ 171 }) 172 173 #define VK_TRY_RV(x) \ 174 ({ \ 175 auto vkhpp_result_value = (x); \ 176 if (vkhpp_result_value.result != vkhpp::Result::eSuccess) { \ 177 return vkhpp_result_value.result; \ 178 } \ 179 std::move(vkhpp_result_value.value); \ 180 }) 181 182 struct GuestGlDispatchTable { 183 #define DECLARE_EGL_FUNCTION(return_type, function_name, signature) \ 184 return_type(*function_name) signature = nullptr; 185 186 #define DECLARE_GLES_FUNCTION(return_type, function_name, signature, args) \ 187 return_type(*function_name) signature = nullptr; 188 189 LIST_RENDER_EGL_FUNCTIONS(DECLARE_EGL_FUNCTION) 190 LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(DECLARE_EGL_FUNCTION) 191 LIST_GLES_FUNCTIONS(DECLARE_GLES_FUNCTION, DECLARE_GLES_FUNCTION) 192 }; 193 194 struct GuestRenderControlDispatchTable { 195 PFN_rcCreateDevice rcCreateDevice = nullptr; 196 PFN_rcDestroyDevice rcDestroyDevice = nullptr; 197 PFN_rcCompose rcCompose = nullptr; 198 }; 199 200 class ScopedRenderControlDevice { 201 public: ScopedRenderControlDevice()202 ScopedRenderControlDevice() {} 203 ScopedRenderControlDevice(GuestRenderControlDispatchTable & dispatch)204 ScopedRenderControlDevice(GuestRenderControlDispatchTable& dispatch) : mDispatch(&dispatch) { 205 mDevice = dispatch.rcCreateDevice(); 206 } 207 208 ScopedRenderControlDevice(const ScopedRenderControlDevice& rhs) = delete; 209 ScopedRenderControlDevice& operator=(const ScopedRenderControlDevice& rhs) = delete; 210 ScopedRenderControlDevice(ScopedRenderControlDevice && rhs)211 ScopedRenderControlDevice(ScopedRenderControlDevice&& rhs) 212 : mDispatch(rhs.mDispatch), mDevice(rhs.mDevice) { 213 rhs.mDevice = nullptr; 214 } 215 216 ScopedRenderControlDevice& operator=(ScopedRenderControlDevice&& rhs) { 217 mDispatch = rhs.mDispatch; 218 std::swap(mDevice, rhs.mDevice); 219 return *this; 220 } 221 ~ScopedRenderControlDevice()222 ~ScopedRenderControlDevice() { 223 if (mDevice != nullptr) { 224 mDispatch->rcDestroyDevice(mDevice); 225 mDevice = nullptr; 226 } 227 } 228 229 operator RenderControlDevice*() { return mDevice; } 230 operator RenderControlDevice*() const { return mDevice; } 231 232 private: 233 GuestRenderControlDispatchTable* mDispatch = nullptr; 234 RenderControlDevice* mDevice = nullptr; 235 }; 236 237 class ScopedGlType { 238 public: 239 using GlDispatch = GuestGlDispatchTable; 240 using GlDispatchGenFunc = void (*GuestGlDispatchTable::*)(GLsizei, GLuint*); 241 using GlDispatchDelFunc = void (*GuestGlDispatchTable::*)(GLsizei, const GLuint*); 242 ScopedGlType()243 ScopedGlType() {} 244 ScopedGlType(GlDispatch & glDispatch,GlDispatchGenFunc glGenFunc,GlDispatchDelFunc glDelFunc)245 ScopedGlType(GlDispatch& glDispatch, GlDispatchGenFunc glGenFunc, GlDispatchDelFunc glDelFunc) 246 : mGlDispatch(&glDispatch), mGlGenFunc(glGenFunc), mGlDelFunc(glDelFunc) { 247 (mGlDispatch->*mGlGenFunc)(1, &mHandle); 248 } 249 250 ScopedGlType(const ScopedGlType& rhs) = delete; 251 ScopedGlType& operator=(const ScopedGlType& rhs) = delete; 252 ScopedGlType(ScopedGlType && rhs)253 ScopedGlType(ScopedGlType&& rhs) 254 : mGlDispatch(rhs.mGlDispatch), 255 mGlGenFunc(rhs.mGlGenFunc), 256 mGlDelFunc(rhs.mGlDelFunc), 257 mHandle(rhs.mHandle) { 258 rhs.mHandle = 0; 259 } 260 261 ScopedGlType& operator=(ScopedGlType&& rhs) { 262 mGlDispatch = rhs.mGlDispatch; 263 mGlGenFunc = rhs.mGlGenFunc; 264 mGlDelFunc = rhs.mGlDelFunc; 265 std::swap(mHandle, rhs.mHandle); 266 return *this; 267 } 268 ~ScopedGlType()269 ~ScopedGlType() { 270 if (mHandle != 0) { 271 (mGlDispatch->*mGlDelFunc)(1, &mHandle); 272 mHandle = 0; 273 } 274 } 275 GLuint()276 operator GLuint() { return mHandle; } GLuint()277 operator GLuint() const { return mHandle; } 278 279 private: 280 GlDispatch* mGlDispatch = nullptr; 281 GlDispatchGenFunc mGlGenFunc = nullptr; 282 GlDispatchDelFunc mGlDelFunc = nullptr; 283 GLuint mHandle = 0; 284 }; 285 286 class ScopedGlBuffer : public ScopedGlType { 287 public: ScopedGlBuffer(GlDispatch & dispatch)288 ScopedGlBuffer(GlDispatch& dispatch) 289 : ScopedGlType(dispatch, &GlDispatch::glGenBuffers, &GlDispatch::glDeleteBuffers) {} 290 }; 291 292 class ScopedGlTexture : public ScopedGlType { 293 public: ScopedGlTexture(GlDispatch & dispatch)294 ScopedGlTexture(GlDispatch& dispatch) 295 : ScopedGlType(dispatch, &GlDispatch::glGenTextures, &GlDispatch::glDeleteTextures) {} 296 }; 297 298 class ScopedGlFramebuffer : public ScopedGlType { 299 public: ScopedGlFramebuffer(GlDispatch & dispatch)300 ScopedGlFramebuffer(GlDispatch& dispatch) 301 : ScopedGlType(dispatch, &GlDispatch::glGenFramebuffers, 302 &GlDispatch::glDeleteFramebuffers) {} 303 }; 304 305 class ScopedGlShader { 306 public: 307 using GlDispatch = GuestGlDispatchTable; 308 309 ScopedGlShader() = default; 310 311 ScopedGlShader(const ScopedGlShader& rhs) = delete; 312 ScopedGlShader& operator=(const ScopedGlShader& rhs) = delete; 313 314 static GlExpected<ScopedGlShader> MakeShader(GlDispatch& dispatch, GLenum type, 315 const std::string& source); 316 ScopedGlShader(ScopedGlShader && rhs)317 ScopedGlShader(ScopedGlShader&& rhs) : mGlDispatch(rhs.mGlDispatch), mHandle(rhs.mHandle) { 318 rhs.mHandle = 0; 319 } 320 321 ScopedGlShader& operator=(ScopedGlShader&& rhs) { 322 mGlDispatch = rhs.mGlDispatch; 323 std::swap(mHandle, rhs.mHandle); 324 return *this; 325 } 326 ~ScopedGlShader()327 ~ScopedGlShader() { 328 if (mHandle != 0) { 329 mGlDispatch->glDeleteShader(mHandle); 330 mHandle = 0; 331 } 332 } 333 GLuint()334 operator GLuint() { return mHandle; } GLuint()335 operator GLuint() const { return mHandle; } 336 337 private: ScopedGlShader(GlDispatch & dispatch,GLuint handle)338 ScopedGlShader(GlDispatch& dispatch, GLuint handle) : mGlDispatch(&dispatch), mHandle(handle) {} 339 340 GlDispatch* mGlDispatch = nullptr; 341 GLuint mHandle = 0; 342 }; 343 344 class ScopedGlProgram { 345 public: 346 using GlDispatch = GuestGlDispatchTable; 347 348 ScopedGlProgram() = default; 349 350 ScopedGlProgram(const ScopedGlProgram& rhs) = delete; 351 ScopedGlProgram& operator=(const ScopedGlProgram& rhs) = delete; 352 353 static GlExpected<ScopedGlProgram> MakeProgram(GlDispatch& dispatch, 354 const std::string& vertShader, 355 const std::string& fragShader); 356 357 static GlExpected<ScopedGlProgram> MakeProgram(GlDispatch& dispatch, GLenum programBinaryFormat, 358 const std::vector<uint8_t>& programBinaryData); 359 ScopedGlProgram(ScopedGlProgram && rhs)360 ScopedGlProgram(ScopedGlProgram&& rhs) : mGlDispatch(rhs.mGlDispatch), mHandle(rhs.mHandle) { 361 rhs.mHandle = 0; 362 } 363 364 ScopedGlProgram& operator=(ScopedGlProgram&& rhs) { 365 mGlDispatch = rhs.mGlDispatch; 366 std::swap(mHandle, rhs.mHandle); 367 return *this; 368 } 369 ~ScopedGlProgram()370 ~ScopedGlProgram() { 371 if (mHandle != 0) { 372 mGlDispatch->glDeleteProgram(mHandle); 373 mHandle = 0; 374 } 375 } 376 GLuint()377 operator GLuint() { return mHandle; } GLuint()378 operator GLuint() const { return mHandle; } 379 380 private: ScopedGlProgram(GlDispatch & dispatch,GLuint handle)381 ScopedGlProgram(GlDispatch& dispatch, GLuint handle) 382 : mGlDispatch(&dispatch), mHandle(handle) {} 383 384 GlDispatch* mGlDispatch = nullptr; 385 GLuint mHandle = 0; 386 }; 387 388 class ScopedAHardwareBuffer { 389 public: 390 ScopedAHardwareBuffer() = default; 391 392 static GlExpected<ScopedAHardwareBuffer> Allocate(Gralloc& gralloc, uint32_t width, 393 uint32_t height, uint32_t format); 394 395 ScopedAHardwareBuffer(const ScopedAHardwareBuffer& rhs) = delete; 396 ScopedAHardwareBuffer& operator=(const ScopedAHardwareBuffer& rhs) = delete; 397 ScopedAHardwareBuffer(ScopedAHardwareBuffer && rhs)398 ScopedAHardwareBuffer(ScopedAHardwareBuffer&& rhs) 399 : mGralloc(rhs.mGralloc), mHandle(rhs.mHandle) { 400 rhs.mHandle = nullptr; 401 } 402 403 ScopedAHardwareBuffer& operator=(ScopedAHardwareBuffer&& rhs) { 404 mGralloc = rhs.mGralloc; 405 std::swap(mHandle, rhs.mHandle); 406 return *this; 407 } 408 ~ScopedAHardwareBuffer()409 ~ScopedAHardwareBuffer() { 410 if (mHandle != nullptr) { 411 mGralloc->release(mHandle); 412 mHandle = 0; 413 } 414 } 415 GetWidth()416 uint32_t GetWidth() const { return mGralloc->getWidth(mHandle); } 417 GetHeight()418 uint32_t GetHeight() const { return mGralloc->getHeight(mHandle); } 419 GetAHBFormat()420 uint32_t GetAHBFormat() const { return mGralloc->getFormat(mHandle); } 421 Lock()422 GlExpected<uint8_t*> Lock() { 423 uint8_t* mapped = nullptr; 424 int status = mGralloc->lock(mHandle, &mapped); 425 if (status != 0) { 426 return android::base::unexpected("Failed to lock AHB"); 427 } 428 return mapped; 429 } 430 Unlock()431 void Unlock() { mGralloc->unlock(mHandle); } 432 433 operator AHardwareBuffer*() { return mHandle; } 434 operator AHardwareBuffer*() const { return mHandle; } 435 436 private: ScopedAHardwareBuffer(Gralloc & gralloc,AHardwareBuffer * handle)437 ScopedAHardwareBuffer(Gralloc& gralloc, AHardwareBuffer* handle) 438 : mGralloc(&gralloc), mHandle(handle) {} 439 440 Gralloc* mGralloc = nullptr; 441 AHardwareBuffer* mHandle = nullptr; 442 }; 443 444 struct Image { 445 uint32_t width; 446 uint32_t height; 447 std::vector<uint32_t> pixels; 448 }; 449 450 enum class GfxstreamTransport { 451 kVirtioGpuAsg, 452 kVirtioGpuPipe, 453 }; 454 455 struct TestParams { 456 bool with_gl; 457 bool with_vk; 458 int samples = 1; 459 std::unordered_set<std::string> with_features; 460 GfxstreamTransport with_transport = GfxstreamTransport::kVirtioGpuAsg; 461 462 std::string ToString() const; 463 friend std::ostream& operator<<(std::ostream& os, const TestParams& params); 464 }; 465 466 std::string GetTestName(const ::testing::TestParamInfo<TestParams>& info); 467 468 // Generates the cartesian product of params with and without the given features. 469 std::vector<TestParams> WithAndWithoutFeatures(const std::vector<TestParams>& params, 470 const std::vector<std::string>& features); 471 472 struct TypicalVkTestEnvironmentOptions { 473 uint32_t apiVersion{VK_API_VERSION_1_2}; 474 std::optional<const void*> instanceCreateInfoPNext; 475 std::optional<std::vector<std::string>> deviceExtensions; 476 std::optional<const void*> deviceCreateInfoPNext; 477 }; 478 479 class GfxstreamEnd2EndTest : public ::testing::TestWithParam<TestParams> { 480 public: 481 std::unique_ptr<GuestGlDispatchTable> SetupGuestGl(); 482 std::unique_ptr<GuestRenderControlDispatchTable> SetupGuestRc(); 483 std::unique_ptr<vkhpp::DynamicLoader> SetupGuestVk(); 484 485 void SetUp() override; 486 487 void TearDownGuest(); 488 void TearDownHost(); 489 void TearDown() override; 490 491 void SetUpEglContextAndSurface(uint32_t contextVersion, 492 uint32_t width, 493 uint32_t height, 494 EGLDisplay* outDisplay, 495 EGLContext* outContext, 496 EGLSurface* outSurface); 497 498 void TearDownEglContextAndSurface(EGLDisplay display, 499 EGLContext context, 500 EGLSurface surface); 501 502 GlExpected<ScopedGlShader> SetUpShader(GLenum type, const std::string& source); 503 504 GlExpected<ScopedGlProgram> SetUpProgram(const std::string& vertSource, 505 const std::string& fragSource); 506 507 GlExpected<ScopedGlProgram> SetUpProgram(GLenum programBinaryFormat, 508 const std::vector<uint8_t>& programBinaryData); 509 510 struct TypicalVkTestEnvironment { 511 vkhpp::UniqueInstance instance; 512 vkhpp::PhysicalDevice physicalDevice; 513 vkhpp::UniqueDevice device; 514 vkhpp::Queue queue; 515 uint32_t queueFamilyIndex; 516 }; 517 VkExpected<TypicalVkTestEnvironment> SetUpTypicalVkTestEnvironment( 518 const TypicalVkTestEnvironmentOptions& opts = {}); 519 520 void SnapshotSaveAndLoad(); 521 522 GlExpected<Image> LoadImage(const std::string& basename); 523 524 GlExpected<Image> AsImage(ScopedAHardwareBuffer& ahb); 525 526 GlExpected<ScopedAHardwareBuffer> CreateAHBFromImage(const std::string& basename); 527 528 bool ArePixelsSimilar(uint32_t expectedPixel, uint32_t actualPixel); 529 530 bool AreImagesSimilar(const Image& expected, const Image& actual); 531 532 GlExpected<Ok> CompareAHBWithGolden(ScopedAHardwareBuffer& ahb, 533 const std::string& goldenBasename); 534 535 std::unique_ptr<ANativeWindowHelper> mAnwHelper; 536 std::unique_ptr<Gralloc> mGralloc; 537 std::unique_ptr<SyncHelper> mSync; 538 std::unique_ptr<GuestGlDispatchTable> mGl; 539 std::unique_ptr<GuestRenderControlDispatchTable> mRc; 540 std::unique_ptr<vkhpp::DynamicLoader> mVk; 541 }; 542 543 } // namespace tests 544 } // namespace gfxstream 545