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
17 class DvrDisplayTest : public DvrApiTest {
18 protected:
SetUp()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
TearDown()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
TEST_F(DvrDisplayTest,DisplayWithOneBuffer)69 TEST_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
TEST_F(DvrDisplayTest,DisplayWithDoubleBuffering)121 TEST_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
TEST_F(DvrDisplayTest,DisplayWithTwoHardwareLayers)189 TEST_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
FillWriteBuffer(DvrWriteBuffer * write_buffer,const std::vector<uint32_t> & color_textures,uint32_t width,uint32_t height)299 void 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