| /* |
| * Copyright © 2016 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| * IN THE SOFTWARE. |
| */ |
| |
| #include "igt.h" |
| #include "drmtest.h" |
| #include <errno.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <time.h> |
| |
| struct additional_test { |
| const char *name; |
| uint32_t obj_type; |
| void (*prop_test)(int fd, uint32_t id, uint32_t type, drmModePropertyPtr prop, |
| uint32_t prop_id, uint64_t prop_value, bool atomic); |
| }; |
| |
| static void prepare_pipe(igt_display_t *display, enum pipe pipe, igt_output_t *output, struct igt_fb *fb) |
| { |
| drmModeModeInfo *mode = igt_output_get_mode(output); |
| |
| igt_create_pattern_fb(display->drm_fd, mode->hdisplay, mode->vdisplay, |
| DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, fb); |
| |
| igt_output_set_pipe(output, pipe); |
| |
| igt_plane_set_fb(igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY), fb); |
| |
| igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); |
| } |
| |
| static void cleanup_pipe(igt_display_t *display, enum pipe pipe, igt_output_t *output, struct igt_fb *fb) |
| { |
| igt_plane_t *plane; |
| |
| for_each_plane_on_pipe(display, pipe, plane) |
| igt_plane_set_fb(plane, NULL); |
| |
| igt_output_set_pipe(output, PIPE_NONE); |
| |
| igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); |
| |
| igt_remove_fb(display->drm_fd, fb); |
| } |
| |
| static bool ignore_property(uint32_t obj_type, uint32_t prop_flags, |
| const char *name, bool atomic) |
| { |
| if (prop_flags & DRM_MODE_PROP_IMMUTABLE) |
| return true; |
| |
| switch (obj_type) { |
| case DRM_MODE_OBJECT_CONNECTOR: |
| if (atomic && !strcmp(name, "DPMS")) |
| return true; |
| break; |
| default: |
| break; |
| } |
| |
| return false; |
| } |
| |
| static void max_bpc_prop_test(int fd, uint32_t id, uint32_t type, drmModePropertyPtr prop, |
| uint32_t prop_id, uint64_t prop_value, bool atomic) |
| { |
| drmModeAtomicReqPtr req = NULL; |
| int i, ret; |
| |
| if (atomic) |
| req = drmModeAtomicAlloc(); |
| |
| for ( i = prop->values[0]; i < prop->values[1] ; i++) { |
| if (!atomic) { |
| ret = drmModeObjectSetProperty(fd, id, type, prop_id, i); |
| |
| igt_assert_eq(ret, 0); |
| } else { |
| ret = drmModeAtomicAddProperty(req, id, prop_id, i); |
| igt_assert(ret >= 0); |
| |
| ret = drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); |
| igt_assert_eq(ret, 0); |
| } |
| } |
| |
| if (atomic) |
| drmModeAtomicFree(req); |
| } |
| |
| static const struct additional_test property_functional_test[] = { |
| {"max bpc", DRM_MODE_OBJECT_CONNECTOR, |
| max_bpc_prop_test}, |
| }; |
| |
| static bool has_additional_test_lookup(uint32_t obj_type, const char *name, |
| bool atomic, int *index) |
| { |
| int i; |
| |
| for (i = 0; i < ARRAY_SIZE(property_functional_test); i++) |
| if (property_functional_test[i].obj_type == obj_type && |
| !strcmp(name, property_functional_test[i].name)) { |
| *index = i; |
| return true; |
| } |
| |
| return false; |
| } |
| static void test_properties(int fd, uint32_t type, uint32_t id, bool atomic) |
| { |
| drmModeObjectPropertiesPtr props = |
| drmModeObjectGetProperties(fd, id, type); |
| int i, j, ret; |
| drmModeAtomicReqPtr req = NULL; |
| |
| igt_assert(props); |
| |
| if (atomic) |
| req = drmModeAtomicAlloc(); |
| |
| for (i = 0; i < props->count_props; i++) { |
| uint32_t prop_id = props->props[i]; |
| uint64_t prop_value = props->prop_values[i]; |
| drmModePropertyPtr prop = drmModeGetProperty(fd, prop_id); |
| |
| igt_assert(prop); |
| |
| if (ignore_property(type, prop->flags, prop->name, atomic)) { |
| igt_debug("Ignoring property \"%s\"\n", prop->name); |
| |
| continue; |
| } |
| |
| igt_debug("Testing property \"%s\"\n", prop->name); |
| |
| if (!atomic) { |
| ret = drmModeObjectSetProperty(fd, id, type, prop_id, prop_value); |
| |
| igt_assert_eq(ret, 0); |
| } else { |
| ret = drmModeAtomicAddProperty(req, id, prop_id, prop_value); |
| igt_assert(ret >= 0); |
| |
| ret = drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_TEST_ONLY, NULL); |
| igt_assert_eq(ret, 0); |
| } |
| |
| if (has_additional_test_lookup(type, prop->name, atomic, &j)) |
| property_functional_test[j].prop_test(fd, id, type, prop, prop_id, prop_value, atomic); |
| |
| drmModeFreeProperty(prop); |
| } |
| |
| drmModeFreeObjectProperties(props); |
| |
| if (atomic) { |
| ret = drmModeAtomicCommit(fd, req, 0, NULL); |
| igt_assert_eq(ret, 0); |
| |
| drmModeAtomicFree(req); |
| } |
| } |
| |
| static void run_plane_property_tests(igt_display_t *display, enum pipe pipe, igt_output_t *output, bool atomic) |
| { |
| struct igt_fb fb; |
| igt_plane_t *plane; |
| |
| prepare_pipe(display, pipe, output, &fb); |
| |
| for_each_plane_on_pipe(display, pipe, plane) { |
| igt_info("Testing plane properties on %s.#%d-%s (output: %s)\n", |
| kmstest_pipe_name(pipe), plane->index, kmstest_plane_type_name(plane->type), output->name); |
| |
| test_properties(display->drm_fd, DRM_MODE_OBJECT_PLANE, plane->drm_plane->plane_id, atomic); |
| } |
| |
| cleanup_pipe(display, pipe, output, &fb); |
| } |
| |
| static void run_crtc_property_tests(igt_display_t *display, enum pipe pipe, igt_output_t *output, bool atomic) |
| { |
| struct igt_fb fb; |
| |
| prepare_pipe(display, pipe, output, &fb); |
| |
| igt_info("Testing crtc properties on %s (output: %s)\n", kmstest_pipe_name(pipe), output->name); |
| |
| test_properties(display->drm_fd, DRM_MODE_OBJECT_CRTC, display->pipes[pipe].crtc_id, atomic); |
| |
| cleanup_pipe(display, pipe, output, &fb); |
| } |
| |
| static void run_connector_property_tests(igt_display_t *display, enum pipe pipe, igt_output_t *output, bool atomic) |
| { |
| struct igt_fb fb; |
| |
| if (pipe != PIPE_NONE) |
| prepare_pipe(display, pipe, output, &fb); |
| |
| igt_info("Testing connector properties on output %s (pipe: %s)\n", output->name, kmstest_pipe_name(pipe)); |
| |
| test_properties(display->drm_fd, DRM_MODE_OBJECT_CONNECTOR, output->id, atomic); |
| |
| if (pipe != PIPE_NONE) |
| cleanup_pipe(display, pipe, output, &fb); |
| } |
| |
| static void plane_properties(igt_display_t *display, bool atomic) |
| { |
| bool found_any = false, found; |
| igt_output_t *output; |
| enum pipe pipe; |
| |
| if (atomic) |
| igt_skip_on(!display->is_atomic); |
| |
| for_each_pipe(display, pipe) { |
| found = false; |
| |
| for_each_valid_output_on_pipe(display, pipe, output) { |
| found_any = found = true; |
| |
| run_plane_property_tests(display, pipe, output, atomic); |
| break; |
| } |
| } |
| |
| igt_skip_on(!found_any); |
| } |
| |
| static void crtc_properties(igt_display_t *display, bool atomic) |
| { |
| bool found_any_valid_pipe = false, found; |
| enum pipe pipe; |
| igt_output_t *output; |
| |
| if (atomic) |
| igt_skip_on(!display->is_atomic); |
| |
| for_each_pipe(display, pipe) { |
| found = false; |
| |
| for_each_valid_output_on_pipe(display, pipe, output) { |
| found_any_valid_pipe = found = true; |
| |
| run_crtc_property_tests(display, pipe, output, atomic); |
| break; |
| } |
| } |
| |
| igt_skip_on(!found_any_valid_pipe); |
| } |
| |
| static void connector_properties(igt_display_t *display, bool atomic) |
| { |
| int i; |
| enum pipe pipe; |
| igt_output_t *output; |
| |
| if (atomic) |
| igt_skip_on(!display->is_atomic); |
| |
| for_each_connected_output(display, output) { |
| bool found = false; |
| |
| for_each_pipe(display, pipe) { |
| if (!igt_pipe_connector_valid(pipe, output)) |
| continue; |
| |
| found = true; |
| run_connector_property_tests(display, pipe, output, atomic); |
| break; |
| } |
| |
| igt_assert_f(found, "Connected output should have at least 1 valid crtc\n"); |
| } |
| |
| for (i = 0; i < display->n_outputs; i++) |
| if (!igt_output_is_connected(&display->outputs[i])) |
| run_connector_property_tests(display, PIPE_NONE, &display->outputs[i], atomic); |
| } |
| |
| static void test_invalid_properties(int fd, |
| uint32_t id1, |
| uint32_t type1, |
| uint32_t id2, |
| uint32_t type2, |
| bool atomic) |
| { |
| drmModeObjectPropertiesPtr props1 = |
| drmModeObjectGetProperties(fd, id1, type1); |
| drmModeObjectPropertiesPtr props2 = |
| drmModeObjectGetProperties(fd, id2, type2); |
| |
| int i, j, ret; |
| drmModeAtomicReqPtr req; |
| |
| igt_assert(props1 && props2); |
| |
| for (i = 0; i < props2->count_props; i++) { |
| uint32_t prop_id = props2->props[i]; |
| uint64_t prop_value = props2->prop_values[i]; |
| drmModePropertyPtr prop = drmModeGetProperty(fd, prop_id); |
| bool found = false; |
| |
| igt_assert(prop); |
| |
| for (j = 0; j < props1->count_props; j++) |
| if (props1->props[j] == prop_id) { |
| found = true; |
| break; |
| } |
| |
| if (found) |
| continue; |
| |
| igt_debug("Testing property \"%s\" on [%x:%u]\n", prop->name, type1, id1); |
| |
| if (!atomic) { |
| ret = drmModeObjectSetProperty(fd, id1, type1, prop_id, prop_value); |
| |
| igt_assert_eq(ret, -EINVAL); |
| } else { |
| req = drmModeAtomicAlloc(); |
| igt_assert(req); |
| |
| ret = drmModeAtomicAddProperty(req, id1, prop_id, prop_value); |
| igt_assert(ret >= 0); |
| |
| ret = drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); |
| igt_assert_eq(ret, -ENOENT); |
| |
| drmModeAtomicFree(req); |
| } |
| |
| drmModeFreeProperty(prop); |
| } |
| |
| drmModeFreeObjectProperties(props1); |
| drmModeFreeObjectProperties(props2); |
| } |
| static void test_object_invalid_properties(igt_display_t *display, |
| uint32_t id, uint32_t type, bool atomic) |
| { |
| igt_output_t *output; |
| igt_plane_t *plane; |
| enum pipe pipe; |
| int i; |
| |
| for_each_pipe(display, pipe) |
| test_invalid_properties(display->drm_fd, id, type, display->pipes[pipe].crtc_id, DRM_MODE_OBJECT_CRTC, atomic); |
| |
| for_each_pipe(display, pipe) |
| for_each_plane_on_pipe(display, pipe, plane) |
| test_invalid_properties(display->drm_fd, id, type, plane->drm_plane->plane_id, DRM_MODE_OBJECT_PLANE, atomic); |
| |
| for (i = 0, output = &display->outputs[0]; i < display->n_outputs; output = &display->outputs[++i]) |
| test_invalid_properties(display->drm_fd, id, type, output->id, DRM_MODE_OBJECT_CONNECTOR, atomic); |
| } |
| |
| static void validate_range_prop(const struct drm_mode_get_property *prop, |
| uint64_t value) |
| { |
| const uint64_t *values = from_user_pointer(prop->values_ptr); |
| bool is_unsigned = prop->flags & DRM_MODE_PROP_RANGE; |
| bool immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; |
| |
| igt_assert_eq(prop->count_values, 2); |
| igt_assert_eq(prop->count_enum_blobs, 0); |
| igt_assert(values[0] != values[1] || immutable); |
| |
| if (is_unsigned) { |
| igt_assert_lte_u64(values[0], values[1]); |
| igt_assert_lte_u64(values[0], value); |
| igt_assert_lte_u64(value, values[1]); |
| } else { |
| igt_assert_lte_s64(values[0], values[1]); |
| igt_assert_lte_s64(values[0], value); |
| igt_assert_lte_s64(value, values[1]); |
| } |
| |
| } |
| |
| static void validate_enums(const struct drm_mode_get_property *prop) |
| { |
| const uint64_t *values = from_user_pointer(prop->values_ptr); |
| const struct drm_mode_property_enum *enums = |
| from_user_pointer(prop->enum_blob_ptr); |
| |
| for (int i = 0; i < prop->count_enum_blobs; i++) { |
| int name_len = strnlen(enums[i].name, |
| sizeof(enums[i].name)); |
| |
| igt_assert_lte(1, name_len); |
| igt_assert_lte(name_len, sizeof(enums[i].name) - 1); |
| |
| /* no idea why we have this duplicated */ |
| igt_assert_eq_u64(values[i], enums[i].value); |
| } |
| } |
| |
| static void validate_enum_prop(const struct drm_mode_get_property *prop, |
| uint64_t value) |
| { |
| const uint64_t *values = from_user_pointer(prop->values_ptr); |
| bool immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; |
| int i; |
| |
| igt_assert_lte(1, prop->count_values); |
| igt_assert_eq(prop->count_enum_blobs, prop->count_values); |
| igt_assert(prop->count_values != 1 || immutable); |
| |
| for (i = 0; i < prop->count_values; i++) { |
| if (value == values[i]) |
| break; |
| } |
| igt_assert(i != prop->count_values); |
| |
| validate_enums(prop); |
| } |
| |
| static void validate_bitmask_prop(const struct drm_mode_get_property *prop, |
| uint64_t value) |
| { |
| const uint64_t *values = from_user_pointer(prop->values_ptr); |
| bool immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; |
| uint64_t mask = 0; |
| |
| igt_assert_lte(1, prop->count_values); |
| igt_assert_eq(prop->count_enum_blobs, prop->count_values); |
| igt_assert(prop->count_values != 1 || immutable); |
| |
| for (int i = 0; i < prop->count_values; i++) { |
| igt_assert_lte_u64(values[i], 63); |
| mask |= 1ULL << values[i]; |
| } |
| |
| igt_assert_eq_u64(value & ~mask, 0); |
| igt_assert_neq_u64(value & mask, 0); |
| |
| validate_enums(prop); |
| } |
| |
| static void validate_blob_prop(int fd, |
| const struct drm_mode_get_property *prop, |
| uint64_t value) |
| { |
| struct drm_mode_get_blob blob; |
| |
| /* |
| * Despite what libdrm makes you believe, we never supply |
| * additional information for BLOB properties, only for enums |
| * and bitmasks |
| */ |
| igt_assert_eq(prop->count_values, 0); |
| igt_assert_eq(prop->count_enum_blobs, 0); |
| |
| igt_assert_lte_u64(value, 0xffffffff); |
| |
| /* |
| * Immutable blob properties can have value==0. |
| * Happens for example with the "EDID" property |
| * when there is nothing hooked up to the connector. |
| */ |
| |
| if (!value) |
| return; |
| |
| memset(&blob, 0, sizeof(blob)); |
| blob.blob_id = value; |
| |
| do_ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob); |
| } |
| |
| static void validate_object_prop(int fd, |
| const struct drm_mode_get_property *prop, |
| uint64_t value) |
| { |
| const uint64_t *values = from_user_pointer(prop->values_ptr); |
| bool immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; |
| struct drm_mode_crtc crtc; |
| struct drm_mode_fb_cmd fb; |
| |
| igt_assert_eq(prop->count_values, 1); |
| igt_assert_eq(prop->count_enum_blobs, 0); |
| |
| igt_assert_lte_u64(value, 0xffffffff); |
| igt_assert(!immutable || value != 0); |
| |
| switch (values[0]) { |
| case DRM_MODE_OBJECT_CRTC: |
| if (!value) |
| break; |
| memset(&crtc, 0, sizeof(crtc)); |
| crtc.crtc_id = value; |
| do_ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc); |
| break; |
| case DRM_MODE_OBJECT_FB: |
| if (!value) |
| break; |
| memset(&fb, 0, sizeof(fb)); |
| fb.fb_id = value; |
| do_ioctl(fd, DRM_IOCTL_MODE_GETFB, &fb); |
| break; |
| default: |
| /* These are the only types we have so far */ |
| igt_assert(0); |
| } |
| } |
| |
| static void validate_property(int fd, |
| const struct drm_mode_get_property *prop, |
| uint64_t value, bool atomic) |
| { |
| uint32_t flags = prop->flags; |
| uint32_t legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE; |
| uint32_t ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE; |
| |
| igt_assert_eq((flags & ~(DRM_MODE_PROP_LEGACY_TYPE | |
| DRM_MODE_PROP_EXTENDED_TYPE | |
| DRM_MODE_PROP_IMMUTABLE | |
| DRM_MODE_PROP_ATOMIC)), 0); |
| |
| igt_assert(atomic || |
| (flags & DRM_MODE_PROP_ATOMIC) == 0); |
| |
| igt_assert_neq(!legacy_type, !ext_type); |
| |
| igt_assert(legacy_type == 0 || |
| is_power_of_two(legacy_type)); |
| |
| switch (legacy_type) { |
| case DRM_MODE_PROP_RANGE: |
| validate_range_prop(prop, value); |
| break; |
| case DRM_MODE_PROP_ENUM: |
| validate_enum_prop(prop, value); |
| break; |
| case DRM_MODE_PROP_BITMASK: |
| validate_bitmask_prop(prop, value); |
| break; |
| case DRM_MODE_PROP_BLOB: |
| validate_blob_prop(fd, prop, value); |
| break; |
| default: |
| igt_assert_eq(legacy_type, 0); |
| } |
| |
| switch (ext_type) { |
| case DRM_MODE_PROP_OBJECT: |
| validate_object_prop(fd, prop, value); |
| break; |
| case DRM_MODE_PROP_SIGNED_RANGE: |
| validate_range_prop(prop, value); |
| break; |
| default: |
| igt_assert_eq(ext_type, 0); |
| } |
| } |
| |
| static void validate_prop(int fd, uint32_t prop_id, uint64_t value, bool atomic) |
| { |
| struct drm_mode_get_property prop; |
| struct drm_mode_property_enum *enums = NULL; |
| uint64_t *values = NULL; |
| |
| memset(&prop, 0, sizeof(prop)); |
| prop.prop_id = prop_id; |
| |
| do_ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop); |
| |
| if (prop.count_values) { |
| values = calloc(prop.count_values, sizeof(values[0])); |
| igt_assert(values); |
| memset(values, 0x5c, sizeof(values[0])*prop.count_values); |
| prop.values_ptr = to_user_pointer(values); |
| } |
| |
| if (prop.count_enum_blobs) { |
| enums = calloc(prop.count_enum_blobs, sizeof(enums[0])); |
| memset(enums, 0x5c, sizeof(enums[0])*prop.count_enum_blobs); |
| igt_assert(enums); |
| prop.enum_blob_ptr = to_user_pointer(enums); |
| } |
| |
| do_ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop); |
| |
| for (int i = 0; i < prop.count_values; i++) |
| igt_assert_neq_u64(values[i], 0x5c5c5c5c5c5c5c5cULL); |
| |
| for (int i = 0; i < prop.count_enum_blobs; i++) |
| igt_assert_neq_u64(enums[i].value, 0x5c5c5c5c5c5c5c5cULL); |
| |
| validate_property(fd, &prop, value, atomic); |
| |
| free(values); |
| free(enums); |
| } |
| |
| static void validate_props(int fd, uint32_t obj_type, uint32_t obj_id, bool atomic) |
| { |
| struct drm_mode_obj_get_properties properties; |
| uint32_t *props = NULL; |
| uint64_t *values = NULL; |
| uint32_t count; |
| |
| memset(&properties, 0, sizeof(properties)); |
| properties.obj_type = obj_type; |
| properties.obj_id = obj_id; |
| |
| do_ioctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties); |
| |
| count = properties.count_props; |
| |
| if (count) { |
| props = calloc(count, sizeof(props[0])); |
| memset(props, 0x5c, sizeof(props[0])*count); |
| igt_assert(props); |
| properties.props_ptr = to_user_pointer(props); |
| |
| values = calloc(count, sizeof(values[0])); |
| memset(values, 0x5c, sizeof(values[0])*count); |
| igt_assert(values); |
| properties.prop_values_ptr = to_user_pointer(values); |
| } |
| |
| do_ioctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties); |
| |
| igt_assert(properties.count_props == count); |
| |
| for (int i = 0; i < count; i++) |
| validate_prop(fd, props[i], values[i], atomic); |
| |
| free(values); |
| free(props); |
| } |
| |
| static void expect_no_props(int fd, uint32_t obj_type, uint32_t obj_id) |
| { |
| struct drm_mode_obj_get_properties properties; |
| |
| memset(&properties, 0, sizeof(properties)); |
| properties.obj_type = obj_type; |
| properties.obj_id = obj_id; |
| |
| igt_assert_neq(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties), 0); |
| } |
| |
| static void get_prop_sanity(igt_display_t *display, bool atomic) |
| { |
| int fd = display->drm_fd; |
| drmModePlaneResPtr plane_res; |
| drmModeResPtr res; |
| |
| res = drmModeGetResources(fd); |
| plane_res = drmModeGetPlaneResources(fd); |
| |
| for (int i = 0; i < plane_res->count_planes; i++) { |
| validate_props(fd, DRM_MODE_OBJECT_PLANE, |
| plane_res->planes[i], atomic); |
| } |
| |
| for (int i = 0; i < res->count_crtcs; i++) { |
| validate_props(fd, DRM_MODE_OBJECT_CRTC, |
| res->crtcs[i], atomic); |
| } |
| |
| for (int i = 0; i < res->count_connectors; i++) { |
| validate_props(fd, DRM_MODE_OBJECT_CONNECTOR, |
| res->connectors[i], atomic); |
| } |
| |
| for (int i = 0; i < res->count_encoders; i++) { |
| expect_no_props(fd, DRM_MODE_OBJECT_ENCODER, |
| res->encoders[i]); |
| } |
| |
| drmModeFreePlaneResources(plane_res); |
| drmModeFreeResources(res); |
| } |
| |
| static void invalid_properties(igt_display_t *display, bool atomic) |
| { |
| igt_output_t *output; |
| igt_plane_t *plane; |
| enum pipe pipe; |
| int i; |
| |
| if (atomic) |
| igt_skip_on(!display->is_atomic); |
| |
| for_each_pipe(display, pipe) |
| test_object_invalid_properties(display, display->pipes[pipe].crtc_id, DRM_MODE_OBJECT_CRTC, atomic); |
| |
| for_each_pipe(display, pipe) |
| for_each_plane_on_pipe(display, pipe, plane) |
| test_object_invalid_properties(display, plane->drm_plane->plane_id, DRM_MODE_OBJECT_PLANE, atomic); |
| |
| for (i = 0, output = &display->outputs[0]; i < display->n_outputs; output = &display->outputs[++i]) |
| test_object_invalid_properties(display, output->id, DRM_MODE_OBJECT_CONNECTOR, atomic); |
| } |
| |
| igt_main |
| { |
| igt_display_t display; |
| |
| igt_skip_on_simulation(); |
| |
| igt_fixture { |
| display.drm_fd = drm_open_driver_master(DRIVER_ANY); |
| |
| kmstest_set_vt_graphics_mode(); |
| |
| igt_display_require(&display, display.drm_fd); |
| } |
| |
| igt_subtest("plane-properties-legacy") |
| plane_properties(&display, false); |
| |
| igt_subtest("plane-properties-atomic") |
| plane_properties(&display, true); |
| |
| igt_subtest("crtc-properties-legacy") |
| crtc_properties(&display, false); |
| |
| igt_subtest("crtc-properties-atomic") |
| crtc_properties(&display, true); |
| |
| igt_subtest("connector-properties-legacy") |
| connector_properties(&display, false); |
| |
| igt_subtest("connector-properties-atomic") |
| connector_properties(&display, true); |
| |
| igt_subtest("invalid-properties-legacy") |
| invalid_properties(&display, false); |
| |
| igt_subtest("invalid-properties-atomic") |
| invalid_properties(&display, true); |
| |
| igt_subtest("get_properties-sanity-atomic") { |
| igt_skip_on(!display.is_atomic); |
| get_prop_sanity(&display, true); |
| } |
| |
| igt_subtest("get_properties-sanity-non-atomic") { |
| if (display.is_atomic) |
| igt_assert_eq(drmSetClientCap(display.drm_fd, DRM_CLIENT_CAP_ATOMIC, 0), 0); |
| |
| get_prop_sanity(&display, false); |
| |
| if (display.is_atomic) |
| igt_assert_eq(drmSetClientCap(display.drm_fd, DRM_CLIENT_CAP_ATOMIC, 1), 0); |
| } |
| |
| igt_fixture { |
| igt_display_fini(&display); |
| } |
| } |