From 095da6fb73efa1cebf8f04466cd6e4b40210db0b Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Mon, 25 Jul 2016 14:49:30 -0700 Subject: [PATCH] libadf: support ADF_{POST,SIMPLE_POST}_CONFIG_V2 ioctls adf_{device,interface_simple}_post_v2 let the client choose what kind of fence is returned from the kernel: * ADF_COMPLETE_FENCE_NONE: no fence is returned * ADF_COMPLETE_FENCE_PRESENT: the returned fence fires when the specified configuration appears on the screen * ADF_COMPLETE_FENCE_RELEASE: the returned fence fires when the specified configuration is removed from the screen The "V2" calls with fence type ADF_COMPLETE_FENCE_RELEASE are functionally equivalent to "V1" calls. Test: included gtest (on Nexus 9) Change-Id: I36190d1b6cea0fbaed2af3ad64fa4729200c5520 Signed-off-by: Greg Hackmann --- adf/libadf/adf.c | 84 +++++++++-- adf/libadf/include/adf/adf.h | 45 ++++++ adf/libadf/include/video/adf.h | 55 +++++-- .../original-kernel-headers/video/adf.h | 65 +++++++++ adf/libadf/tests/Android.bp | 1 + adf/libadf/tests/adf_test.cpp | 135 +++++++++++++----- 6 files changed, 324 insertions(+), 61 deletions(-) diff --git a/adf/libadf/adf.c b/adf/libadf/adf.c index c4d66814d..10f88b007 100644 --- a/adf/libadf/adf.c +++ b/adf/libadf/adf.c @@ -180,6 +180,37 @@ int adf_device_post(struct adf_device *dev, return (int)data.complete_fence; } +int adf_device_post_v2(struct adf_device *dev, + adf_id_t *interfaces, __u32 n_interfaces, + struct adf_buffer_config *bufs, __u32 n_bufs, + void *custom_data, __u64 custom_data_size, + enum adf_complete_fence_type complete_fence_type, + int *complete_fence) +{ + int err; + struct adf_post_config_v2 data; + + memset(&data, 0, sizeof(data)); + data.interfaces = (uintptr_t)interfaces; + data.n_interfaces = n_interfaces; + data.bufs = (uintptr_t)bufs; + data.n_bufs = n_bufs; + data.custom_data = (uintptr_t)custom_data; + data.custom_data_size = custom_data_size; + data.complete_fence_type = complete_fence_type; + + err = ioctl(dev->fd, ADF_POST_CONFIG_V2, &data); + if (err < 0) + return -errno; + + if (complete_fence) + *complete_fence = data.complete_fence; + else if (data.complete_fence >= 0) + close(data.complete_fence); + + return 0; +} + static int adf_device_attachment(struct adf_device *dev, adf_id_t overlay_engine, adf_id_t interface, bool attach) { @@ -421,6 +452,21 @@ int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h, return (int)data.fd; } +static void adf_interface_simple_post_config_buf(struct adf_buffer_config *buf, + __u32 overlay_engine, __u32 w, __u32 h, __u32 format, int buf_fd, + __u32 offset, __u32 pitch, int acquire_fence) +{ + buf->overlay_engine = overlay_engine; + buf->w = w; + buf->h = h; + buf->format = format; + buf->fd[0] = buf_fd; + buf->offset[0] = offset; + buf->pitch[0] = pitch; + buf->n_planes = 1; + buf->acquire_fence = acquire_fence; +} + int adf_interface_simple_post(int fd, __u32 overlay_engine, __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, __u32 pitch, int acquire_fence) @@ -429,16 +475,8 @@ int adf_interface_simple_post(int fd, __u32 overlay_engine, struct adf_simple_post_config data; memset(&data, 0, sizeof(data)); - data.buf.overlay_engine = overlay_engine; - data.buf.w = w; - data.buf.h = h; - data.buf.format = format; - data.buf.fd[0] = buf_fd; - data.buf.offset[0] = offset; - data.buf.pitch[0] = pitch; - data.buf.n_planes = 1; - data.buf.acquire_fence = acquire_fence; - + adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format, + buf_fd, offset, pitch, acquire_fence); ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG, &data); if (ret < 0) return -errno; @@ -446,6 +484,32 @@ int adf_interface_simple_post(int fd, __u32 overlay_engine, return (int)data.complete_fence; } +int adf_interface_simple_post_v2(int fd, adf_id_t overlay_engine, + __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, + __u32 pitch, int acquire_fence, + enum adf_complete_fence_type complete_fence_type, + int *complete_fence) +{ + int ret; + struct adf_simple_post_config_v2 data; + + memset(&data, 0, sizeof(data)); + adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format, + buf_fd, offset, pitch, acquire_fence); + data.complete_fence_type = complete_fence_type; + + ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG_V2, &data); + if (ret < 0) + return -errno; + + if (complete_fence) + *complete_fence = data.complete_fence; + else if (data.complete_fence >= 0) + close(data.complete_fence); + + return 0; +} + ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines) { char pattern[64]; diff --git a/adf/libadf/include/adf/adf.h b/adf/libadf/include/adf/adf.h index b6bda3451..e4c7b28cc 100644 --- a/adf/libadf/include/adf/adf.h +++ b/adf/libadf/include/adf/adf.h @@ -74,6 +74,29 @@ int adf_device_post(struct adf_device *dev, adf_id_t *interfaces, size_t n_interfaces, struct adf_buffer_config *bufs, size_t n_bufs, void *custom_data, size_t custom_data_size); +/** + * Atomically posts a new display configuration to the specified interfaces. + * + * Compared to adf_device_post(), adf_device_post_v2(): + * + * (*) allows the client to choose the kind of sync fence returned + * (through complete_fence_type) + * + * (*) stores the returned sync fence fd in a provided buffer, so the client + * can distinguish between a permission error (ret = -1) and a successful + * call that returns no fence (*complete_fence = -1) + * + * On error, returns -errno. + * + * On devices without the corresponding kernel support, returns -ENOTTY. + */ +int adf_device_post_v2(struct adf_device *dev, + adf_id_t *interfaces, __u32 n_interfaces, + struct adf_buffer_config *bufs, __u32 n_bufs, + void *custom_data, __u64 custom_data_size, + enum adf_complete_fence_type complete_fence_type, + int *complete_fence); + /** * Attaches the specified interface and overlay engine. */ @@ -163,6 +186,28 @@ int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h, int adf_interface_simple_post(int fd, adf_id_t overlay_engine, __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, __u32 pitch, int acquire_fence); +/** + * Posts a single-plane RGB buffer to the display using the specified + * overlay engine. + * + * Compared to adf_interface_simple_post(), adf_interface_simple_post_v2(): + * + * (*) allows the client to choose the kind of sync fence returned + * (through complete_fence_type) + * + * (*) stores the returned sync fence fd in a provided buffer, so the client + * can distinguish between a permission error (ret = -1) and a successful + * call that returns no fence (*complete_fence = -1) + * + * On error, returns -errno. + * + * On devices without the corresponding kernel support, returns -ENOTTY. + */ +int adf_interface_simple_post_v2(int fd, adf_id_t overlay_engine, + __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, + __u32 pitch, int acquire_fence, + enum adf_complete_fence_type complete_fence_type, + int *complete_fence); /** * Enumerates all overlay engines belonging to an ADF device. diff --git a/adf/libadf/include/video/adf.h b/adf/libadf/include/video/adf.h index 77203a586..692a4251d 100644 --- a/adf/libadf/include/video/adf.h +++ b/adf/libadf/include/video/adf.h @@ -49,69 +49,94 @@ enum adf_event_type { ADF_EVENT_DEVICE_CUSTOM = 128, ADF_EVENT_TYPE_MAX = 255, }; -struct adf_set_event { +enum adf_complete_fence_type { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + ADF_COMPLETE_FENCE_NONE = 0, + ADF_COMPLETE_FENCE_PRESENT = 1, + ADF_COMPLETE_FENCE_RELEASE = 2, +}; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +struct adf_set_event { __u8 type; __u8 enabled; }; -struct adf_event { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +struct adf_event { __u8 type; __u32 length; }; -struct adf_vsync_event { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +struct adf_vsync_event { struct adf_event base; __aligned_u64 timestamp; }; -struct adf_hotplug_event { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +struct adf_hotplug_event { struct adf_event base; __u8 connected; }; -#define ADF_MAX_PLANES 4 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define ADF_MAX_PLANES 4 struct adf_buffer_config { __u32 overlay_engine; __u32 w; - __u32 h; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 h; __u32 format; __s32 fd[ADF_MAX_PLANES]; __u32 offset[ADF_MAX_PLANES]; - __u32 pitch[ADF_MAX_PLANES]; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 pitch[ADF_MAX_PLANES]; __u8 n_planes; __s32 acquire_fence; }; -#define ADF_MAX_BUFFERS (4096 / sizeof(struct adf_buffer_config)) /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define ADF_MAX_BUFFERS (4096 / sizeof(struct adf_buffer_config)) struct adf_post_config { size_t n_interfaces; __u32 __user * interfaces; - size_t n_bufs; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + size_t n_bufs; struct adf_buffer_config __user * bufs; size_t custom_data_size; void __user * custom_data; - __s32 complete_fence; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __s32 complete_fence; }; +struct adf_post_config_v2 { + __u32 n_interfaces; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u64 interfaces; + __u32 n_bufs; + __u64 bufs; + __u64 custom_data_size; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u64 custom_data; + __s32 complete_fence; + __u8 complete_fence_type; +}; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define ADF_MAX_INTERFACES (4096 / sizeof(__u32)) struct adf_simple_buffer_alloc { __u16 w; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __u16 h; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __u32 format; __s32 fd; __u32 offset; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __u32 pitch; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ }; struct adf_simple_post_config { struct adf_buffer_config buf; -/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __s32 complete_fence; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +}; +struct adf_simple_post_config_v2 { + struct adf_buffer_config buf; + __s32 complete_fence; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u8 complete_fence_type; }; struct adf_attachment_config { __u32 overlay_engine; @@ -177,4 +202,8 @@ struct adf_overlay_engine_data { #define ADF_ATTACH _IOW(ADF_IOCTL_TYPE, 9, struct adf_attachment_config) /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define ADF_DETACH _IOW(ADF_IOCTL_TYPE, 10, struct adf_attachment_config) +#define ADF_POST_CONFIG_V2 _IOW(ADF_IOCTL_TYPE, 11, struct adf_post_config_v2) +#define ADF_SIMPLE_POST_CONFIG_V2 _IOW(ADF_IOCTL_TYPE, 12, struct adf_simple_post_config_v2) #endif +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + diff --git a/adf/libadf/original-kernel-headers/video/adf.h b/adf/libadf/original-kernel-headers/video/adf.h index c5d2e62cd..8293c1d8b 100644 --- a/adf/libadf/original-kernel-headers/video/adf.h +++ b/adf/libadf/original-kernel-headers/video/adf.h @@ -46,6 +46,15 @@ enum adf_event_type { ADF_EVENT_TYPE_MAX = 255, }; +enum adf_complete_fence_type { + /* no fence */ + ADF_COMPLETE_FENCE_NONE = 0, + /* fence fires when the configuration appears on the screen */ + ADF_COMPLETE_FENCE_PRESENT = 1, + /* fence fires when the configuration leaves the screen */ + ADF_COMPLETE_FENCE_RELEASE = 2, +}; + /** * struct adf_set_event - start or stop subscribing to ADF events * @@ -131,6 +140,9 @@ struct adf_buffer_config { /** * struct adf_post_config - request to flip to a new set of buffers * + * This request is equivalent to &struct adf_post_config_v2 with + * @complete_fence_type = %ADF_COMPLETE_FENCE_RELEASE. + * * @n_interfaces: number of interfaces targeted by the flip (input) * @interfaces: ids of interfaces targeted by the flip (input) * @n_bufs: number of buffers displayed (input) @@ -152,6 +164,34 @@ struct adf_post_config { __s32 complete_fence; }; + +/** + * struct adf_post_config_v2 - request to flip to a new set of buffers + * + * @n_interfaces: number of interfaces targeted by the flip (input) + * @interfaces: ids of interfaces targeted by the flip (input) + * @n_bufs: number of buffers displayed (input) + * @bufs: description of buffers displayed (input) + * @custom_data_size: size of driver-private data (input) + * @custom_data: driver-private data (input) + * @complete_fence_type: one of &enum adf_complete_fence_type describing what + * fence to return (input) + * @complete_fence: sync_fence fd which will fire at the time + * requested by @complete_fence_type (output) + */ +struct adf_post_config_v2 { + __u32 n_interfaces; + __u64 interfaces; /* __u32 * packed into __u64 */ + + __u32 n_bufs; + __u64 bufs; /* struct adf_buffer_config * packed into __u64 */ + + __u64 custom_data_size; + __u64 custom_data; /* void * packed into __u64 */ + + __s32 complete_fence; + __u8 complete_fence_type; +}; #define ADF_MAX_INTERFACES (4096 / sizeof(__u32)) /** @@ -189,6 +229,9 @@ struct adf_simple_buffer_alloc { * struct adf_simple_post_config - request to flip to a single buffer without * driver-private data * + * This request is equivalent to &struct adf_simple_post_config_v2 with + * @complete_fence_type = %ADF_COMPLETE_FENCE_RELEASE. + * * @buf: description of buffer displayed (input) * @complete_fence: sync_fence fd which will clear when this buffer has left the * screen (output) @@ -198,6 +241,22 @@ struct adf_simple_post_config { __s32 complete_fence; }; +/** + * struct adf_simple_post_config_v2 - request to flip to a single buffer without + * driver-private data + * + * @buf: description of buffer displayed (input) + * @complete_fence_type: one of &enum adf_complete_fence_type describing what + * fence to return (input) + * @complete_fence: sync_fence fd which will fire at the time + * requested by @complete_fence_type (output) + */ +struct adf_simple_post_config_v2 { + struct adf_buffer_config buf; + __s32 complete_fence; + __u8 complete_fence_type; +}; + /** * struct adf_attachment_config - description of attachment between an overlay * engine and an interface @@ -318,4 +377,10 @@ struct adf_overlay_engine_data { #define ADF_DETACH _IOW(ADF_IOCTL_TYPE, 10, \ struct adf_attachment_config) +#define ADF_POST_CONFIG_V2 _IOW(ADF_IOCTL_TYPE, 11, \ + struct adf_post_config_v2) +#define ADF_SIMPLE_POST_CONFIG_V2 \ + _IOW(ADF_IOCTL_TYPE, 12, \ + struct adf_simple_post_config_v2) + #endif /* _UAPI_VIDEO_ADF_H_ */ diff --git a/adf/libadf/tests/Android.bp b/adf/libadf/tests/Android.bp index 7b333004d..9b3430e5f 100644 --- a/adf/libadf/tests/Android.bp +++ b/adf/libadf/tests/Android.bp @@ -17,6 +17,7 @@ cc_test { name: "adf-unit-tests", srcs: ["adf_test.cpp"], + shared_libs: ["libsync"], static_libs: ["libadf"], cflags: ["-Werror"], } diff --git a/adf/libadf/tests/adf_test.cpp b/adf/libadf/tests/adf_test.cpp index eaa93420a..4727c2b88 100644 --- a/adf/libadf/tests/adf_test.cpp +++ b/adf/libadf/tests/adf_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include class AdfTest : public testing::Test { public: @@ -73,24 +74,6 @@ public: FAIL(); /* this should never happen */ } - void drawCheckerboard(void *buf, uint32_t w, uint32_t h, uint32_t pitch) { - uint8_t *buf8 = reinterpret_cast(buf); - for (uint32_t y = 0; y < h / 2; y++) { - uint32_t *scanline = reinterpret_cast(buf8 + y * pitch); - for (uint32_t x = 0; x < w / 2; x++) - scanline[x] = 0xFF0000FF; - for (uint32_t x = w / 2; x < w; x++) - scanline[x] = 0xFF00FFFF; - } - for (uint32_t y = h / 2; y < h; y++) { - uint32_t *scanline = reinterpret_cast(buf8 + y * pitch); - for (uint32_t x = 0; x < w / 2; x++) - scanline[x] = 0xFFFF00FF; - for (uint32_t x = w / 2; x < w; x++) - scanline[x] = 0xFFFFFFFF; - } - } - /* various helpers to call ADF and die on failure */ void getInterfaceData(adf_interface_data &data) { @@ -141,6 +124,42 @@ public: free(event); } + void drawCheckerboard(uint32_t &w, uint32_t &h, uint32_t &format, + char format_str[ADF_FORMAT_STR_SIZE], int &buf_fd, uint32_t &offset, + uint32_t &pitch) { + ASSERT_NO_FATAL_FAILURE(getCurrentMode(w, h)); + ASSERT_NO_FATAL_FAILURE(get8888Format(format, format_str)); + + buf_fd = adf_interface_simple_buffer_alloc(intf, w, h, format, &offset, + &pitch); + ASSERT_GE(buf_fd, 0) << "allocating " << w << "x" << h << " " << + format_str << " buffer failed: " << strerror(-buf_fd); + EXPECT_GE(pitch, w * 4); + + void *mapped = mmap(NULL, pitch * h, PROT_WRITE, MAP_SHARED, buf_fd, + offset); + ASSERT_NE(mapped, MAP_FAILED) << "mapping " << w << "x" << h << " " << + format_str << " buffer failed: " << strerror(-errno); + + uint8_t *buf8 = static_cast(mapped); + for (uint32_t y = 0; y < h / 2; y++) { + uint32_t *scanline = reinterpret_cast(buf8 + y * pitch); + for (uint32_t x = 0; x < w / 2; x++) + scanline[x] = 0xFF0000FF; + for (uint32_t x = w / 2; x < w; x++) + scanline[x] = 0xFF00FFFF; + } + for (uint32_t y = h / 2; y < h; y++) { + uint32_t *scanline = reinterpret_cast(buf8 + y * pitch); + for (uint32_t x = 0; x < w / 2; x++) + scanline[x] = 0xFFFF00FF; + for (uint32_t x = w / 2; x < w; x++) + scanline[x] = 0xFFFFFFFF; + } + + munmap(mapped, pitch * h); + } + protected: adf_device dev; adf_id_t intf_id; @@ -310,27 +329,11 @@ TEST_F(AdfTest, simple_buffer_alloc) { } TEST_F(AdfTest, simple_buffer) { - uint32_t w = 0, h = 0; - ASSERT_NO_FATAL_FAILURE(getCurrentMode(w, h)); - - uint32_t format = 0; + int buf_fd; + uint32_t w, h, format, offset, pitch; char format_str[ADF_FORMAT_STR_SIZE]; - ASSERT_NO_FATAL_FAILURE(get8888Format(format, format_str)); - - uint32_t offset; - uint32_t pitch; - int buf_fd = adf_interface_simple_buffer_alloc(intf, w, h, format, &offset, - &pitch); - ASSERT_GE(buf_fd, 0) << "allocating " << w << "x" << h << " " << - format_str << " buffer failed: " << strerror(-buf_fd); - EXPECT_GE(pitch, w * 4); - - void *mapped = mmap(NULL, pitch * h, PROT_WRITE, MAP_SHARED, buf_fd, - offset); - ASSERT_NE(mapped, MAP_FAILED) << "mapping " << w << "x" << h << " " << - format_str << " buffer failed: " << strerror(-errno); - drawCheckerboard(mapped, w, h, pitch); - munmap(mapped, pitch * h); + ASSERT_NO_FATAL_FAILURE(drawCheckerboard(w, h, format, format_str, + buf_fd, offset, pitch)); ASSERT_NO_FATAL_FAILURE(attach()); ASSERT_NO_FATAL_FAILURE(blank(DRM_MODE_DPMS_ON)); @@ -342,3 +345,59 @@ TEST_F(AdfTest, simple_buffer) { format_str << " buffer failed: " << strerror(-release_fence); close(release_fence); } + +TEST_F(AdfTest, simple_buffer_v2) { + int buf_fd; + uint32_t w, h, format, offset, pitch; + char format_str[ADF_FORMAT_STR_SIZE]; + ASSERT_NO_FATAL_FAILURE(drawCheckerboard(w, h, format, format_str, + buf_fd, offset, pitch)); + + ASSERT_NO_FATAL_FAILURE(attach()); + ASSERT_NO_FATAL_FAILURE(blank(DRM_MODE_DPMS_ON)); + + int config_1_release; + int err = adf_interface_simple_post_v2(intf, eng_id, w, h, + format, buf_fd, offset, pitch, -1, ADF_COMPLETE_FENCE_RELEASE, + &config_1_release); + if (err == -ENOTTY) { + GTEST_LOG_(INFO) << "ADF_SIMPLE_POST_CONFIG_V2 not supported on this kernel"; + return; + } + ASSERT_GE(err, 0) << "posting " << w << "x" << h << " " << + format_str << " buffer failed: " << strerror(-err); + + err = sync_wait(config_1_release, 1000); + ASSERT_EQ(-1, err) << + "waiting for config 1's release fence should not have suceeded"; + ASSERT_EQ(ETIME, errno) << + "config 1's release fence should have timed out, but failed instead: " << + strerror(errno); + + int config_2_present; + err = adf_interface_simple_post_v2(intf, eng_id, w, h, + format, buf_fd, offset, pitch, -1, ADF_COMPLETE_FENCE_PRESENT, + &config_2_present); + ASSERT_GE(err, 0) << "posting " << w << "x" << h << " " << + format_str << " buffer failed: " << strerror(-err); + + err = sync_wait(config_2_present, 1000); + ASSERT_EQ(0, err) << + "waiting for config 2's present fence failed: " << strerror(errno); + err = sync_wait(config_1_release, 0); + ASSERT_EQ(0, err) << + "waiting for config 1's release fence failed: " << strerror(errno); + close(config_1_release); + close(config_2_present); + + int config_3_no_fence; + err = adf_interface_simple_post_v2(intf, eng_id, w, h, + format, buf_fd, offset, pitch, -1, ADF_COMPLETE_FENCE_NONE, + &config_3_no_fence); + ASSERT_GE(err, 0) << "posting " << w << "x" << h << " " << + format_str << " buffer failed: " << strerror(-err); + ASSERT_EQ(-1, config_3_no_fence) << + "fence returned even though the fence type was ADF_COMPLETE_FENCE_NONE"; + + close(buf_fd); +}