1#include <android/hardware_buffer.h> 2#include <android/log.h> 3#include <dvr/dvr_api.h> 4#include <dvr/dvr_display_types.h> 5#include <dvr/dvr_surface.h> 6 7#include <gtest/gtest.h> 8 9#include "dvr_api_test.h" 10 11#define LOG_TAG "dvr_display-test" 12 13#ifndef ALOGD 14#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 15#endif 16 17class DvrDisplayTest : public DvrApiTest { 18 protected: 19 void SetUp() override { 20 DvrApiTest::SetUp(); 21 int ret = api_.GetNativeDisplayMetrics(sizeof(display_metrics_), 22 &display_metrics_); 23 ASSERT_EQ(ret, 0) << "Failed to get display metrics."; 24 ALOGD( 25 "display_width: %d, display_height: %d, display_x_dpi: %d, " 26 "display_y_dpi: %d, vsync_period_ns: %d.", 27 display_metrics_.display_width, display_metrics_.display_height, 28 display_metrics_.display_x_dpi, display_metrics_.display_y_dpi, 29 display_metrics_.vsync_period_ns); 30 } 31 32 void TearDown() override { 33 if (write_queue_ != nullptr) { 34 api_.WriteBufferQueueDestroy(write_queue_); 35 write_queue_ = nullptr; 36 } 37 if (direct_surface_ != nullptr) { 38 api_.SurfaceDestroy(direct_surface_); 39 direct_surface_ = nullptr; 40 } 41 DvrApiTest::TearDown(); 42 } 43 44 /* Convert a write buffer to an android hardware buffer and fill in 45 * color_textures evenly to the buffer. 46 * AssertionError if the width of the buffer is not equal to the input width, 47 * AssertionError if the height of the buffer is not equal to the input 48 * height. 49 */ 50 void FillWriteBuffer(DvrWriteBuffer* write_buffer, 51 const std::vector<uint32_t>& color_textures, 52 uint32_t width, uint32_t height); 53 54 // Write buffer queue properties. 55 static constexpr uint64_t kUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | 56 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | 57 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; 58 uint32_t kFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; 59 static constexpr size_t kMetadataSize = 0; 60 static constexpr int kTimeoutMs = 1000; // Time for getting buffer. 61 uint32_t kLayerCount = 1; 62 DvrWriteBufferQueue* write_queue_ = nullptr; 63 DvrSurface* direct_surface_ = nullptr; 64 65 // Device display properties. 66 DvrNativeDisplayMetrics display_metrics_; 67}; 68 69TEST_F(DvrDisplayTest, DisplayWithOneBuffer) { 70 // Create a direct surface. 71 std::vector<DvrSurfaceAttribute> direct_surface_attributes = { 72 {.key = DVR_SURFACE_ATTRIBUTE_DIRECT, 73 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 74 .value.bool_value = true}, 75 {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER, 76 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32, 77 .value.int32_value = 10}, 78 {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE, 79 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 80 .value.bool_value = true}, 81 }; 82 int ret = 83 api_.SurfaceCreate(direct_surface_attributes.data(), 84 direct_surface_attributes.size(), &direct_surface_); 85 ASSERT_EQ(ret, 0) << "Failed to create direct surface."; 86 87 // Create a buffer queue with the direct surface. 88 constexpr size_t kCapacity = 1; 89 uint32_t width = display_metrics_.display_width; 90 uint32_t height = display_metrics_.display_height; 91 ret = api_.SurfaceCreateWriteBufferQueue( 92 direct_surface_, width, height, kFormat, kLayerCount, kUsage, kCapacity, 93 kMetadataSize, &write_queue_); 94 EXPECT_EQ(0, ret) << "Failed to create buffer queue."; 95 ASSERT_NE(nullptr, write_queue_) << "Write buffer queue should not be null."; 96 97 // Get buffer from WriteBufferQueue. 98 DvrWriteBuffer* write_buffer = nullptr; 99 DvrNativeBufferMetadata out_meta; 100 int out_fence_fd = -1; 101 ret = api_.WriteBufferQueueGainBuffer(write_queue_, kTimeoutMs, &write_buffer, 102 &out_meta, &out_fence_fd); 103 EXPECT_EQ(0, ret) << "Failed to get the buffer."; 104 ASSERT_NE(nullptr, write_buffer) << "Gained buffer should not be null."; 105 106 // Color the write buffer. 107 FillWriteBuffer(write_buffer, 108 {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, 109 width, height); 110 111 // Post buffer. 112 int ready_fence_fd = -1; 113 ret = api_.WriteBufferQueuePostBuffer(write_queue_, write_buffer, &out_meta, 114 ready_fence_fd); 115 EXPECT_EQ(0, ret) << "Failed to post the buffer."; 116 117 sleep(5); // For visual check on the device under test. 118 // Should observe three primary colors on the screen center. 119} 120 121TEST_F(DvrDisplayTest, DisplayWithDoubleBuffering) { 122 // Create a direct surface. 123 std::vector<DvrSurfaceAttribute> direct_surface_attributes = { 124 {.key = DVR_SURFACE_ATTRIBUTE_DIRECT, 125 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 126 .value.bool_value = true}, 127 {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER, 128 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32, 129 .value.int32_value = 10}, 130 {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE, 131 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 132 .value.bool_value = true}, 133 }; 134 int ret = 135 api_.SurfaceCreate(direct_surface_attributes.data(), 136 direct_surface_attributes.size(), &direct_surface_); 137 ASSERT_EQ(ret, 0) << "Failed to create direct surface."; 138 139 // Create a buffer queue with the direct surface. 140 constexpr size_t kCapacity = 2; 141 uint32_t width = display_metrics_.display_width; 142 uint32_t height = display_metrics_.display_height; 143 ret = api_.SurfaceCreateWriteBufferQueue( 144 direct_surface_, width, height, kFormat, kLayerCount, kUsage, kCapacity, 145 kMetadataSize, &write_queue_); 146 EXPECT_EQ(0, ret) << "Failed to create buffer queue."; 147 ASSERT_NE(nullptr, write_queue_) << "Write buffer queue should not be null."; 148 149 int num_display_cycles_in_5s = 5 / (display_metrics_.vsync_period_ns / 1e9); 150 ALOGD("The number of display cycles: %d", num_display_cycles_in_5s); 151 int bufferhub_id_prev_write_buffer = -1; 152 for (int i = 0; i < num_display_cycles_in_5s; ++i) { 153 // Get a buffer from the WriteBufferQueue. 154 DvrWriteBuffer* write_buffer = nullptr; 155 DvrNativeBufferMetadata out_meta; 156 int out_fence_fd = -1; 157 ret = api_.WriteBufferQueueGainBuffer( 158 write_queue_, kTimeoutMs, &write_buffer, &out_meta, &out_fence_fd); 159 EXPECT_EQ(0, ret) << "Failed to get the a write buffer."; 160 ASSERT_NE(nullptr, write_buffer) << "The gained buffer should not be null."; 161 162 int bufferhub_id = api_.WriteBufferGetId(write_buffer); 163 ALOGD("Display cycle: %d, bufferhub id of the write buffer: %d", i, 164 bufferhub_id); 165 EXPECT_NE(bufferhub_id_prev_write_buffer, bufferhub_id) 166 << "Double buffering should be using the two buffers in turns, not " 167 "reusing the same write buffer."; 168 bufferhub_id_prev_write_buffer = bufferhub_id; 169 170 // Color the write buffer. 171 if (i % 2) { 172 FillWriteBuffer(write_buffer, {0xffff0000, 0xff00ff00, 0xff0000ff}, width, 173 height); 174 } else { 175 FillWriteBuffer(write_buffer, {0xff00ff00, 0xff0000ff, 0xffff0000}, width, 176 height); 177 } 178 179 // Post the write buffer. 180 int ready_fence_fd = -1; 181 ret = api_.WriteBufferQueuePostBuffer(write_queue_, write_buffer, &out_meta, 182 ready_fence_fd); 183 EXPECT_EQ(0, ret) << "Failed to post the buffer."; 184 } 185 // Should observe blinking screen in secondary colors 186 // although it is actually displaying primary colors. 187} 188 189TEST_F(DvrDisplayTest, DisplayWithTwoHardwareLayers) { 190 // Create the direct_surface_0 of z order 10 and direct_surface_1 of z 191 // order 11. 192 DvrSurface* direct_surface_0 = nullptr; 193 std::vector<DvrSurfaceAttribute> direct_surface_0_attributes = { 194 {.key = DVR_SURFACE_ATTRIBUTE_DIRECT, 195 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 196 .value.bool_value = true}, 197 {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER, 198 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32, 199 .value.int32_value = 10}, 200 {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE, 201 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 202 .value.bool_value = true}, 203 }; 204 int ret = 205 api_.SurfaceCreate(direct_surface_0_attributes.data(), 206 direct_surface_0_attributes.size(), &direct_surface_0); 207 EXPECT_EQ(ret, 0) << "Failed to create direct surface."; 208 209 DvrSurface* direct_surface_1 = nullptr; 210 std::vector<DvrSurfaceAttribute> direct_surface_1_attributes = { 211 {.key = DVR_SURFACE_ATTRIBUTE_DIRECT, 212 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 213 .value.bool_value = true}, 214 {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER, 215 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32, 216 .value.int32_value = 11}, 217 {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE, 218 .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL, 219 .value.bool_value = true}, 220 }; 221 ret = 222 api_.SurfaceCreate(direct_surface_1_attributes.data(), 223 direct_surface_1_attributes.size(), &direct_surface_1); 224 EXPECT_EQ(ret, 0) << "Failed to create direct surface."; 225 226 // Create a buffer queue for each of the direct surfaces. 227 constexpr size_t kCapacity = 1; 228 uint32_t width = display_metrics_.display_width; 229 uint32_t height = display_metrics_.display_height; 230 231 DvrWriteBufferQueue* write_queue_0 = nullptr; 232 ret = api_.SurfaceCreateWriteBufferQueue( 233 direct_surface_0, width, height, kFormat, kLayerCount, kUsage, kCapacity, 234 kMetadataSize, &write_queue_0); 235 EXPECT_EQ(0, ret) << "Failed to create buffer queue."; 236 EXPECT_NE(nullptr, write_queue_0) << "Write buffer queue should not be null."; 237 238 DvrWriteBufferQueue* write_queue_1 = nullptr; 239 ret = api_.SurfaceCreateWriteBufferQueue( 240 direct_surface_1, width, height, kFormat, kLayerCount, kUsage, kCapacity, 241 kMetadataSize, &write_queue_1); 242 EXPECT_EQ(0, ret) << "Failed to create buffer queue."; 243 EXPECT_NE(nullptr, write_queue_1) << "Write buffer queue should not be null."; 244 245 // Get a buffer from each of the write buffer queues. 246 DvrWriteBuffer* write_buffer_0 = nullptr; 247 DvrNativeBufferMetadata out_meta_0; 248 int out_fence_fd = -1; 249 ret = api_.WriteBufferQueueGainBuffer( 250 write_queue_0, kTimeoutMs, &write_buffer_0, &out_meta_0, &out_fence_fd); 251 EXPECT_EQ(0, ret) << "Failed to get the buffer."; 252 EXPECT_NE(nullptr, write_buffer_0) << "Gained buffer should not be null."; 253 254 DvrWriteBuffer* write_buffer_1 = nullptr; 255 DvrNativeBufferMetadata out_meta_1; 256 out_fence_fd = -1; 257 ret = api_.WriteBufferQueueGainBuffer( 258 write_queue_1, kTimeoutMs, &write_buffer_1, &out_meta_1, &out_fence_fd); 259 EXPECT_EQ(0, ret) << "Failed to get the buffer."; 260 EXPECT_NE(nullptr, write_buffer_1) << "Gained buffer should not be null."; 261 262 // Color the write buffers. 263 FillWriteBuffer(write_buffer_0, {0xffff0000, 0xff00ff00, 0xff0000ff}, width, 264 height); 265 FillWriteBuffer(write_buffer_1, {0x7f00ff00, 0x7f0000ff, 0x7fff0000}, width, 266 height); 267 268 // Post buffers. 269 int ready_fence_fd = -1; 270 ret = api_.WriteBufferQueuePostBuffer(write_queue_0, write_buffer_0, 271 &out_meta_0, ready_fence_fd); 272 EXPECT_EQ(0, ret) << "Failed to post the buffer."; 273 274 ready_fence_fd = -1; 275 ret = api_.WriteBufferQueuePostBuffer(write_queue_1, write_buffer_1, 276 &out_meta_1, ready_fence_fd); 277 EXPECT_EQ(0, ret) << "Failed to post the buffer."; 278 279 sleep(5); // For visual check on the device under test. 280 // Should observe three secondary colors. 281 282 // Test finished. Clean up buffers and surfaces. 283 if (write_queue_0 != nullptr) { 284 api_.WriteBufferQueueDestroy(write_queue_0); 285 write_queue_0 = nullptr; 286 } 287 if (write_queue_1 != nullptr) { 288 api_.WriteBufferQueueDestroy(write_queue_1); 289 write_queue_1 = nullptr; 290 } 291 if (direct_surface_0 != nullptr) { 292 api_.SurfaceDestroy(direct_surface_0); 293 } 294 if (direct_surface_1 != nullptr) { 295 api_.SurfaceDestroy(direct_surface_1); 296 } 297} 298 299void DvrDisplayTest::FillWriteBuffer( 300 DvrWriteBuffer* write_buffer, const std::vector<uint32_t>& color_textures, 301 uint32_t width, uint32_t height) { 302 uint32_t num_colors = color_textures.size(); 303 // Convert the first write buffer to an android hardware buffer. 304 AHardwareBuffer* ah_buffer = nullptr; 305 int ret = api_.WriteBufferGetAHardwareBuffer(write_buffer, &ah_buffer); 306 ASSERT_EQ(0, ret) << "Failed to get a hardware buffer from the write buffer."; 307 ASSERT_NE(nullptr, ah_buffer) << "AHardware buffer should not be null."; 308 AHardwareBuffer_Desc ah_buffer_describe; 309 AHardwareBuffer_describe(ah_buffer, &ah_buffer_describe); 310 ASSERT_EQ(ah_buffer_describe.format, kFormat) 311 << "The format of the android hardware buffer is wrong."; 312 ASSERT_EQ(ah_buffer_describe.layers, kLayerCount) 313 << "The obtained android hardware buffer should have 2 layers."; 314 ASSERT_EQ(ah_buffer_describe.width, width) 315 << "The obtained android hardware buffer width is wrong."; 316 ASSERT_EQ(ah_buffer_describe.height, height) 317 << "The obtained android hardware buffer height is wrong."; 318 // Change the content of the android hardware buffer. 319 void* buffer_data = nullptr; 320 int32_t fence = -1; 321 ret = AHardwareBuffer_lock(ah_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, 322 fence, nullptr, &buffer_data); 323 ASSERT_EQ(0, ret) << "Failed to lock the hardware buffer."; 324 ASSERT_NE(nullptr, buffer_data) << "Buffer data should not be null."; 325 326 uint32_t num_pixels = width * height / num_colors; 327 for (uint32_t color_index = 0; color_index < num_colors - 1; ++color_index) { 328 uint32_t color_texture = color_textures[color_index]; 329 for (uint32_t i = 0; i < num_pixels; ++i) { 330 memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) + 331 (i + num_pixels * color_index) * 332 sizeof(color_texture)), 333 &color_texture, sizeof(color_texture)); 334 } 335 } 336 uint32_t color_texture = color_textures[num_colors - 1]; 337 uint32_t num_colored_pixels = num_pixels * (num_colors - 1); 338 num_pixels = width * height - num_colored_pixels; 339 for (uint32_t i = 0; i < num_pixels; ++i) { 340 memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) + 341 (i + num_colored_pixels) * 342 sizeof(color_texture)), 343 &color_texture, sizeof(color_texture)); 344 } 345 fence = -1; 346 ret = AHardwareBuffer_unlock(ah_buffer, &fence); 347 EXPECT_EQ(0, ret) << "Failed to unlock the hardware buffer."; 348 349 // Release the android hardware buffer. 350 AHardwareBuffer_release(ah_buffer); 351} 352