1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <errno.h> 18#include <fcntl.h> 19 20#include <adf/adf.h> 21#include <gtest/gtest.h> 22#include <sys/mman.h> 23 24class AdfTest : public testing::Test { 25public: 26 AdfTest() : intf_id(0), intf(-1), eng_id(0), eng(-1) { } 27 28 virtual void SetUp() { 29 int err = adf_device_open(dev_id, O_RDWR, &dev); 30 ASSERT_GE(err, 0) << "opening ADF device " << dev_id << 31 " failed: " << strerror(-err); 32 33 err = adf_find_simple_post_configuration(&dev, fmt8888, n_fmt8888, 34 &intf_id, &eng_id); 35 ASSERT_GE(err, 0) << "finding ADF configuration failed: " << 36 strerror(-err); 37 38 intf = adf_interface_open(&dev, intf_id, O_RDWR); 39 ASSERT_GE(intf, 0) << "opening ADF interface " << dev_id << "." << 40 intf_id << " failed: " << strerror(-intf); 41 42 eng = adf_overlay_engine_open(&dev, eng_id, O_RDWR); 43 ASSERT_GE(eng, 0) << "opening ADF overlay engine " << dev_id << "." << 44 eng_id << " failed: " << strerror(-eng); 45 } 46 47 virtual void TearDown() { 48 if (eng >= 0) 49 close(eng); 50 if (intf >= 0) 51 close(intf); 52 adf_device_close(&dev); 53 } 54 55 void get8888Format(uint32_t &fmt, char fmt_str[ADF_FORMAT_STR_SIZE]) { 56 adf_overlay_engine_data data; 57 int err = adf_get_overlay_engine_data(eng, &data); 58 ASSERT_GE(err, 0) << "getting ADF overlay engine data failed: " << 59 strerror(-err); 60 61 for (size_t i = 0; i < data.n_supported_formats; i++) { 62 for (size_t j = 0; j < n_fmt8888; j++) { 63 if (data.supported_formats[i] == fmt8888[j]) { 64 fmt = data.supported_formats[i]; 65 adf_format_str(fmt, fmt_str); 66 adf_free_overlay_engine_data(&data); 67 return; 68 } 69 } 70 } 71 72 adf_free_overlay_engine_data(&data); 73 FAIL(); /* this should never happen */ 74 } 75 76 void drawCheckerboard(void *buf, uint32_t w, uint32_t h, uint32_t pitch) { 77 uint8_t *buf8 = reinterpret_cast<uint8_t *>(buf); 78 for (uint32_t y = 0; y < h / 2; y++) { 79 uint32_t *scanline = reinterpret_cast<uint32_t *>(buf8 + y * pitch); 80 for (uint32_t x = 0; x < w / 2; x++) 81 scanline[x] = 0xFF0000FF; 82 for (uint32_t x = w / 2; x < w; x++) 83 scanline[x] = 0xFF00FFFF; 84 } 85 for (uint32_t y = h / 2; y < h; y++) { 86 uint32_t *scanline = reinterpret_cast<uint32_t *>(buf8 + y * pitch); 87 for (uint32_t x = 0; x < w / 2; x++) 88 scanline[x] = 0xFFFF00FF; 89 for (uint32_t x = w / 2; x < w; x++) 90 scanline[x] = 0xFFFFFFFF; 91 } 92 } 93 94 /* various helpers to call ADF and die on failure */ 95 96 void getInterfaceData(adf_interface_data &data) { 97 int err = adf_get_interface_data(intf, &data); 98 ASSERT_GE(err, 0) << "getting ADF interface data failed: " << 99 strerror(-err); 100 } 101 102 void getCurrentMode(uint32_t &w, uint32_t &h) { 103 adf_interface_data data; 104 ASSERT_NO_FATAL_FAILURE(getInterfaceData(data)); 105 w = data.current_mode.hdisplay; 106 h = data.current_mode.vdisplay; 107 adf_free_interface_data(&data); 108 } 109 110 void blank(uint8_t mode) { 111 int err = adf_interface_blank(intf, mode); 112 ASSERT_FALSE(err < 0 && err != -EBUSY) << 113 "unblanking interface failed: " << strerror(-err); 114 } 115 116 void attach() { 117 int err = adf_device_attach(&dev, eng_id, intf_id); 118 ASSERT_FALSE(err < 0 && err != -EALREADY) << 119 "attaching overlay engine " << eng_id << " to interface " << 120 intf_id << " failed: " << strerror(-err); 121 } 122 123 void detach() { 124 int err = adf_device_detach(&dev, eng_id, intf_id); 125 ASSERT_FALSE(err < 0 && err != -EINVAL) << 126 "detaching overlay engine " << eng_id << " from interface " << 127 intf_id << " failed: " << strerror(-err); 128 } 129 130 void readVsyncTimestamp(uint64_t ×tamp) { 131 adf_event *event; 132 int err = adf_read_event(intf, &event); 133 ASSERT_GE(err, 0) << "reading ADF event failed: " << strerror(-err); 134 135 ASSERT_EQ(ADF_EVENT_VSYNC, event->type); 136 ASSERT_EQ(sizeof(adf_vsync_event), event->length); 137 138 adf_vsync_event *vsync_event = 139 reinterpret_cast<adf_vsync_event *>(event); 140 timestamp = vsync_event->timestamp; 141 free(event); 142 } 143 144protected: 145 adf_device dev; 146 adf_id_t intf_id; 147 int intf; 148 adf_id_t eng_id; 149 int eng; 150 151private: 152 const static adf_id_t dev_id = 0; 153 const static __u32 fmt8888[]; 154 const static size_t n_fmt8888; 155}; 156 157const __u32 AdfTest::fmt8888[] = { 158 DRM_FORMAT_XRGB8888, 159 DRM_FORMAT_XBGR8888, 160 DRM_FORMAT_RGBX8888, 161 DRM_FORMAT_BGRX8888, 162 DRM_FORMAT_ARGB8888, 163 DRM_FORMAT_ABGR8888, 164 DRM_FORMAT_RGBA8888, 165 DRM_FORMAT_BGRA8888 166}; 167const size_t AdfTest::n_fmt8888 = sizeof(fmt8888) / sizeof(fmt8888[0]); 168 169TEST(adf, devices) { 170 adf_id_t *devs; 171 ssize_t n_devs = adf_devices(&devs); 172 free(devs); 173 174 ASSERT_GE(n_devs, 0) << "enumerating ADF devices failed: " << 175 strerror(-n_devs); 176 ASSERT_TRUE(devs != NULL); 177} 178 179TEST_F(AdfTest, device_data) { 180 adf_device_data data; 181 int err = adf_get_device_data(&dev, &data); 182 ASSERT_GE(err, 0) << "getting ADF device data failed: " << strerror(-err); 183 184 EXPECT_LT(data.n_attachments, ADF_MAX_ATTACHMENTS); 185 EXPECT_GT(data.n_allowed_attachments, 0U); 186 EXPECT_LT(data.n_allowed_attachments, ADF_MAX_ATTACHMENTS); 187 EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE); 188 adf_free_device_data(&data); 189} 190 191TEST_F(AdfTest, interface_data) { 192 adf_interface_data data; 193 ASSERT_NO_FATAL_FAILURE(getInterfaceData(data)); 194 195 EXPECT_LT(data.type, ADF_INTF_TYPE_MAX); 196 EXPECT_LE(data.dpms_state, DRM_MODE_DPMS_OFF); 197 EXPECT_EQ(1, data.hotplug_detect); 198 EXPECT_GT(data.n_available_modes, 0U); 199 EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE); 200 adf_free_interface_data(&data); 201} 202 203TEST_F(AdfTest, overlay_engine_data) { 204 adf_overlay_engine_data data; 205 int err = adf_get_overlay_engine_data(eng, &data); 206 ASSERT_GE(err, 0) << "getting ADF overlay engine failed: " << 207 strerror(-err); 208 209 EXPECT_GT(data.n_supported_formats, 0U); 210 EXPECT_LT(data.n_supported_formats, ADF_MAX_SUPPORTED_FORMATS); 211 EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE); 212 adf_free_overlay_engine_data(&data); 213} 214 215TEST_F(AdfTest, blank) { 216 int err = adf_interface_blank(intf, (uint8_t)-1); 217 EXPECT_EQ(-EINVAL, err) << "setting bogus DPMS mode should have failed"; 218 219 err = adf_interface_blank(eng, DRM_MODE_DPMS_OFF); 220 EXPECT_EQ(-EINVAL, err) << "blanking overlay engine should have failed"; 221 222 ASSERT_NO_FATAL_FAILURE(blank(DRM_MODE_DPMS_OFF)); 223 err = adf_interface_blank(intf, DRM_MODE_DPMS_OFF); 224 EXPECT_EQ(-EBUSY, err) << "blanking interface twice should have failed"; 225 226 ASSERT_NO_FATAL_FAILURE(blank(DRM_MODE_DPMS_ON)); 227 err = adf_interface_blank(intf, DRM_MODE_DPMS_ON); 228 EXPECT_EQ(-EBUSY, err) << "unblanking interface twice should have failed"; 229 230 adf_interface_data data; 231 ASSERT_NO_FATAL_FAILURE(getInterfaceData(data)); 232 EXPECT_EQ(DRM_MODE_DPMS_ON, data.dpms_state); 233 adf_free_interface_data(&data); 234} 235 236TEST_F(AdfTest, event) { 237 int err = adf_set_event(intf, ADF_EVENT_TYPE_MAX, true); 238 EXPECT_EQ(-EINVAL, err) << "enabling bogus ADF event should have failed"; 239 240 err = adf_set_event(intf, ADF_EVENT_TYPE_MAX, false); 241 EXPECT_EQ(-EINVAL, err) << "disabling bogus ADF event should have failed"; 242 243 err = adf_set_event(intf, ADF_EVENT_VSYNC, true); 244 ASSERT_GE(err, 0) << "enabling vsync event failed: " << strerror(-err); 245 246 err = adf_set_event(intf, ADF_EVENT_VSYNC, true); 247 EXPECT_EQ(-EALREADY, err) << 248 "enabling vsync event twice should have failed"; 249 250 ASSERT_NO_FATAL_FAILURE(blank(DRM_MODE_DPMS_ON)); 251 252 uint64_t timestamp1, timestamp2; 253 ASSERT_NO_FATAL_FAILURE(readVsyncTimestamp(timestamp1)); 254 ASSERT_NO_FATAL_FAILURE(readVsyncTimestamp(timestamp2)); 255 EXPECT_GT(timestamp2, timestamp1); 256 257 err = adf_set_event(intf, ADF_EVENT_VSYNC, false); 258 EXPECT_GE(err, 0) << "disabling vsync event failed: " << strerror(-err); 259 260 err = adf_set_event(intf, ADF_EVENT_VSYNC, false); 261 EXPECT_EQ(-EALREADY, err) << 262 "disabling vsync event twice should have failed"; 263} 264 265TEST_F(AdfTest, attach) { 266 ASSERT_NO_FATAL_FAILURE(attach()); 267 int err = adf_device_attach(&dev, eng_id, intf_id); 268 EXPECT_EQ(-EALREADY, err) << "attaching overlay engine " << eng_id << 269 " to interface " << intf_id << " twice should have failed"; 270 271 ASSERT_NO_FATAL_FAILURE(detach()); 272 err = adf_device_detach(&dev, eng_id, intf_id); 273 EXPECT_EQ(-EINVAL, err) << "detaching overlay engine " << eng_id << 274 " from interface " << intf_id << " twice should have failed"; 275 276 err = adf_device_attach(&dev, eng_id, ADF_MAX_INTERFACES); 277 EXPECT_EQ(-EINVAL, err) << "attaching overlay engine " << eng_id << 278 " to bogus interface should have failed"; 279 280 err = adf_device_detach(&dev, eng_id, ADF_MAX_INTERFACES); 281 EXPECT_EQ(-EINVAL, err) << "detaching overlay engine " << eng_id << 282 " from bogus interface should have failed"; 283} 284 285TEST_F(AdfTest, simple_buffer_alloc) { 286 uint32_t w = 0, h = 0; 287 ASSERT_NO_FATAL_FAILURE(getCurrentMode(w, h)); 288 289 uint32_t format; 290 char format_str[ADF_FORMAT_STR_SIZE]; 291 ASSERT_NO_FATAL_FAILURE(get8888Format(format, format_str)); 292 293 uint32_t offset; 294 uint32_t pitch; 295 int buf_fd = adf_interface_simple_buffer_alloc(intf, w, h, format, &offset, 296 &pitch); 297 EXPECT_GE(buf_fd, 0) << "allocating " << w << "x" << h << " " << 298 format_str << " buffer failed: " << strerror(-buf_fd); 299 EXPECT_GE(pitch, w * 4); 300 close(buf_fd); 301 302 buf_fd = adf_interface_simple_buffer_alloc(intf, w, h, 0xDEADBEEF, &offset, 303 &pitch); 304 /* n.b.: ADF only allows simple buffers with built-in RGB formats, 305 so this should fail even if a driver supports custom format 0xDEADBEEF */ 306 EXPECT_EQ(-EINVAL, buf_fd) << 307 "allocating buffer with bogus format should have failed"; 308} 309 310TEST_F(AdfTest, simple_buffer) { 311 uint32_t w = 0, h = 0; 312 ASSERT_NO_FATAL_FAILURE(getCurrentMode(w, h)); 313 314 uint32_t format = 0; 315 char format_str[ADF_FORMAT_STR_SIZE]; 316 ASSERT_NO_FATAL_FAILURE(get8888Format(format, format_str)); 317 318 uint32_t offset; 319 uint32_t pitch; 320 int buf_fd = adf_interface_simple_buffer_alloc(intf, w, h, format, &offset, 321 &pitch); 322 ASSERT_GE(buf_fd, 0) << "allocating " << w << "x" << h << " " << 323 format_str << " buffer failed: " << strerror(-buf_fd); 324 EXPECT_GE(pitch, w * 4); 325 326 void *mapped = mmap(NULL, pitch * h, PROT_WRITE, MAP_SHARED, buf_fd, 327 offset); 328 ASSERT_NE(mapped, MAP_FAILED) << "mapping " << w << "x" << h << " " << 329 format_str << " buffer failed: " << strerror(-errno); 330 drawCheckerboard(mapped, w, h, pitch); 331 munmap(mapped, pitch * h); 332 333 ASSERT_NO_FATAL_FAILURE(attach()); 334 ASSERT_NO_FATAL_FAILURE(blank(DRM_MODE_DPMS_ON)); 335 336 int release_fence = adf_interface_simple_post(intf, eng_id, w, h, format, 337 buf_fd, offset, pitch, -1); 338 close(buf_fd); 339 ASSERT_GE(release_fence, 0) << "posting " << w << "x" << h << " " << 340 format_str << " buffer failed: " << strerror(-release_fence); 341 close(release_fence); 342} 343