summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2016-06-28 14:28:20 +0200
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2016-06-29 14:57:11 +0200
commit4a1859781f154513f19cd6392e04f50dbe6c030a (patch)
treeda14cdfd797fff62301fa0423532f51b02bd589f
parentd31b9b307f164668ddd23da6bef619c002e75a14 (diff)
igt_kms: Add modeset support for atomic style commits.
All pipes are now updated in the loop first, before connectors are read out. The mode_id and active crtc properties are added, and crtc_id for connectors. These are required to do a modeset, and the behavior during atomic commits is changed slightly too. A lot of code will do the following: - Init. - igt_output_set_pipe(output, pipe); - commit. Since legacy setcrtc and atomic commit differ, there are some differences in how we commit pipes and connectors too. For atomic we set output->crtc during igt_output_set_pipe, and use it in atomic commit. This may be set to NULL, in which case the output is disconnected from the crtc. Unlike legacy we won't attempt to bind all connectors to all pipes, only the ones that were explicitly set. As a test, convert kms_rmfb.c Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-rw-r--r--lib/igt_kms.c481
-rw-r--r--lib/igt_kms.h32
-rw-r--r--tests/kms_rmfb.c10
3 files changed, 358 insertions, 165 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index f9e32a5a..56ef21e4 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -167,11 +167,13 @@ static const char *igt_crtc_prop_names[IGT_NUM_CRTC_PROPS] = {
"DEGAMMA_LUT",
"CTM",
"GAMMA_LUT",
+ "MODE_ID",
+ "ACTIVE",
};
static const char *igt_connector_prop_names[IGT_NUM_CONNECTOR_PROPS] = {
"scaling mode",
- "DPMS"
+ "CRTC_ID",
};
/*
@@ -210,11 +212,10 @@ igt_atomic_fill_plane_props(igt_display_t *display, igt_plane_t *plane,
/*
* Retrieve all the properies specified in props_name and store them into
- * config->atomic_props_crtc and config->atomic_props_connector.
+ * config->atomic_props_connector.
*/
static void
-igt_atomic_fill_props(igt_display_t *display, igt_output_t *output,
- int num_crtc_props, const char **crtc_prop_names,
+igt_atomic_fill_output_props(igt_display_t *display, igt_output_t *output,
int num_connector_props, const char **conn_prop_names)
{
drmModeObjectPropertiesPtr props;
@@ -222,18 +223,18 @@ igt_atomic_fill_props(igt_display_t *display, igt_output_t *output,
fd = display->drm_fd;
- props = drmModeObjectGetProperties(fd, output->config.crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
+ props = drmModeObjectGetProperties(fd, output->id, DRM_MODE_OBJECT_CONNECTOR);
igt_assert(props);
for (i = 0; i < props->count_props; i++) {
drmModePropertyPtr prop =
drmModeGetProperty(fd, props->props[i]);
- for (j = 0; j < num_crtc_props; j++) {
- if (strcmp(prop->name, crtc_prop_names[j]) != 0)
+ for (j = 0; j < num_connector_props; j++) {
+ if (strcmp(prop->name, conn_prop_names[j]) != 0)
continue;
- output->config.atomic_props_crtc[j] = props->props[i];
+ output->config.atomic_props_connector[j] = props->props[i];
break;
}
@@ -241,27 +242,54 @@ igt_atomic_fill_props(igt_display_t *display, igt_output_t *output,
}
drmModeFreeObjectProperties(props);
- props = NULL;
- props = drmModeObjectGetProperties(fd, output->config.connector->connector_id, DRM_MODE_OBJECT_CONNECTOR);
+
+}
+
+static void
+igt_fill_pipe_props(igt_display_t *display, igt_pipe_t *pipe_obj,
+ int num_crtc_props, const char **crtc_prop_names)
+{
+ drmModeObjectPropertiesPtr props;
+ int i, j, fd;
+ uint64_t prop_value = 0;
+
+ fd = display->drm_fd;
+
+ props = drmModeObjectGetProperties(fd, pipe_obj->crtc_id, DRM_MODE_OBJECT_CRTC);
igt_assert(props);
for (i = 0; i < props->count_props; i++) {
drmModePropertyPtr prop =
drmModeGetProperty(fd, props->props[i]);
- for (j = 0; j < num_connector_props; j++) {
- if (strcmp(prop->name, conn_prop_names[j]) != 0)
+ for (j = 0; j < num_crtc_props; j++) {
+ if (strcmp(prop->name, crtc_prop_names[j]) != 0)
continue;
- output->config.atomic_props_connector[j] = props->props[i];
+ pipe_obj->atomic_props_crtc[j] = props->props[i];
break;
}
drmModeFreeProperty(prop);
}
- drmModeFreeObjectProperties(props);
+ igt_pipe_get_property(pipe_obj, "background_color",
+ &pipe_obj->background_property, &prop_value, NULL);
+ pipe_obj->background = (uint32_t)prop_value;
+
+ igt_pipe_get_property(pipe_obj, "DEGAMMA_LUT", &pipe_obj->degamma_property, NULL, NULL);
+
+ igt_pipe_get_property(pipe_obj, "CTM", &pipe_obj->ctm_property, NULL, NULL);
+
+ igt_pipe_get_property(pipe_obj, "GAMMA_LUT", &pipe_obj->gamma_property, NULL, NULL);
+ igt_pipe_get_property(pipe_obj, "ACTIVE", NULL, &prop_value, NULL);
+ pipe_obj->active = (uint32_t)prop_value;
+
+ pipe_obj->mode_id = 0;
+ igt_pipe_get_property(pipe_obj, "MODE_ID", NULL, &pipe_obj->mode_id, NULL);
+
+ drmModeFreeObjectProperties(props);
}
const unsigned char* igt_kms_get_alt_edid(void)
@@ -755,6 +783,33 @@ bool kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
return true;
}
+static void
+_kmstest_connector_config_crtc_mask(int drm_fd,
+ drmModeConnector *connector,
+ struct kmstest_connector_config *config)
+{
+ int i;
+
+ config->valid_crtc_idx_mask = 0;
+
+ /* Now get a compatible encoder */
+ for (i = 0; i < connector->count_encoders; i++) {
+ drmModeEncoder *encoder = drmModeGetEncoder(drm_fd,
+ connector->encoders[i]);
+
+ if (!encoder) {
+ igt_warn("could not get encoder %d: %s\n",
+ connector->encoders[i],
+ strerror(errno));
+
+ continue;
+ }
+
+ config->valid_crtc_idx_mask |= encoder->possible_crtcs;
+ drmModeFreeEncoder(encoder);
+ }
+}
+
/**
* _kmstest_connector_config:
* @drm_fd: DRM fd
@@ -773,8 +828,9 @@ static bool _kmstest_connector_config(int drm_fd, uint32_t connector_id,
{
drmModeRes *resources;
drmModeConnector *connector;
- drmModeEncoder *encoder, *found = NULL;
- int i, j, pipe;
+ drmModeEncoder *found = NULL;
+ int i, pipe;
+ uint32_t valid_crtc_mask;
resources = drmModeGetResources(drm_fd);
if (!resources) {
@@ -810,32 +866,31 @@ static bool _kmstest_connector_config(int drm_fd, uint32_t connector_id,
* In both cases find the first compatible encoder and skip the CRTC
* if there is non such.
*/
- config->valid_crtc_idx_mask = 0;
- for (i = 0; i < resources->count_crtcs; i++) {
- if (!resources->crtcs[i])
- continue;
+ _kmstest_connector_config_crtc_mask(drm_fd, connector, config);
- /* Now get a compatible encoder */
- for (j = 0; j < connector->count_encoders; j++) {
- encoder = drmModeGetEncoder(drm_fd,
- connector->encoders[j]);
+ valid_crtc_mask = config->valid_crtc_idx_mask & crtc_idx_mask;
+ if (!valid_crtc_mask)
+ goto err3;
- if (!encoder) {
- igt_warn("could not get encoder %d: %s\n",
- resources->encoders[j],
- strerror(errno));
+ pipe = ffs(valid_crtc_mask) - 1;
- continue;
- }
+ for (i = 0; i < connector->count_encoders; i++) {
+ drmModeEncoder *encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]);
- config->valid_crtc_idx_mask |= encoder->possible_crtcs;
+ if (!encoder) {
+ igt_warn("could not get encoder %d: %s\n",
+ connector->encoders[i],
+ strerror(errno));
- if (!found && (crtc_idx_mask & encoder->possible_crtcs & (1 << i))) {
- found = encoder;
- pipe = i;
- } else
- drmModeFreeEncoder(encoder);
+ continue;
}
+
+ if (!found && (encoder->possible_crtcs & (1 << pipe))) {
+ found = encoder;
+ break;
+ }
+
+ drmModeFreeEncoder(encoder);
}
if (!found)
@@ -858,7 +913,10 @@ static bool _kmstest_connector_config(int drm_fd, uint32_t connector_id,
err4:
drmModeFreeEncoder(found);
err3:
- drmModeFreeConnector(connector);
+ config->connector = connector;
+ config->crtc = NULL;
+ config->encoder = NULL;
+ config->pipe = PIPE_ANY;
err2:
drmModeFreeResources(resources);
err1:
@@ -1159,7 +1217,7 @@ static void igt_display_log_shift(igt_display_t *display, int shift)
igt_assert(display->log_shift >= 0);
}
-static void igt_output_refresh(igt_output_t *output)
+static void igt_output_refresh(igt_output_t *output, bool from_init)
{
igt_display_t *display = output->display;
bool ret;
@@ -1171,17 +1229,42 @@ static void igt_output_refresh(igt_output_t *output)
if (output->valid)
kmstest_free_connector_config(&output->config);
- ret = kmstest_get_connector_config(display->drm_fd,
- output->id,
- crtc_idx_mask,
- &output->config);
- if (ret)
- output->valid = true;
- else
- output->valid = false;
+ igt_atomic_fill_output_props(display, output, IGT_NUM_CONNECTOR_PROPS, igt_connector_prop_names);
+
+ if (!from_init || !display->is_atomic) {
+ ret = kmstest_get_connector_config(display->drm_fd,
+ output->id,
+ crtc_idx_mask,
+ &output->config);
+ if (ret)
+ output->valid = true;
+ else
+ output->valid = false;
+ } else {
+ uint64_t crtc_id = 0;
- if (!output->valid)
- return;
+ kmstest_get_property(display->drm_fd, output->id, DRM_MODE_OBJECT_CONNECTOR,
+ "CRTC_ID", NULL, &crtc_id, NULL);
+
+ output->config.connector = drmModeGetConnectorCurrent(display->drm_fd, output->id);
+ output->valid = output->config.connector->connection == DRM_MODE_CONNECTED;
+ output->config.encoder = NULL;
+ output->config.crtc = NULL;
+ output->config.crtc_idx = crtc_id;
+
+ _kmstest_connector_config_crtc_mask(display->drm_fd, output->config.connector, &output->config);
+
+ if (output->valid)
+ kmstest_get_connector_default_mode(display->drm_fd, output->config.connector,
+ &output->config.default_mode);
+
+ if (crtc_id) {
+ output->config.crtc = drmModeGetCrtc(display->drm_fd, crtc_id);
+
+ output->config.pipe = kmstest_get_pipe_from_crtc_id(display->drm_fd, crtc_id);
+ } else
+ output->config.pipe = PIPE_ANY;
+ }
if (output->use_override_mode)
output->config.default_mode = output->override_mode;
@@ -1193,12 +1276,22 @@ static void igt_output_refresh(igt_output_t *output)
-1);
}
+ if (!output->valid) {
+ LOG(display, "%s: Disconnected\n", output->name);
+
+ return;
+ }
+
+ if (!output->config.crtc) {
+ LOG(display, "%s: Not connected to a pipe\n", output->name);
+
+ return;
+ }
+
LOG(display, "%s: Selecting pipe %s\n", output->name,
kmstest_pipe_name(output->config.pipe));
display->pipes_in_use |= 1 << output->config.pipe;
- igt_atomic_fill_props(display, output, IGT_NUM_CRTC_PROPS, igt_crtc_prop_names,
- IGT_NUM_CONNECTOR_PROPS, igt_connector_prop_names);
}
static bool
@@ -1397,6 +1490,11 @@ void igt_display_init(igt_display_t *display, int drm_fd)
/* make sure we don't overflow the plane array */
igt_assert(pipe->n_planes <= IGT_MAX_PLANES);
+
+ igt_fill_pipe_props(display, pipe, IGT_NUM_CRTC_PROPS, igt_crtc_prop_names);
+ igt_atomic_fill_plane_props(display, plane, IGT_NUM_PLANE_PROPS, igt_plane_prop_names);
+
+ LOG(display, "Pipe %s active %u mode_id %"PRIu64"\n", kmstest_pipe_name(i), pipe->active, pipe->mode_id);
}
/*
@@ -1409,7 +1507,6 @@ void igt_display_init(igt_display_t *display, int drm_fd)
igt_assert(display->outputs);
for (i = 0; i < display->n_outputs; i++) {
- int j;
igt_output_t *output = &display->outputs[i];
/*
@@ -1420,36 +1517,7 @@ void igt_display_init(igt_display_t *display, int drm_fd)
output->id = resources->connectors[i];
output->display = display;
- igt_output_refresh(output);
-
- for (j = 0; j < display->n_pipes; j++) {
- uint64_t prop_value;
- igt_pipe_t *pipe = &display->pipes[j];
-
- if (output->config.crtc) {
- get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
- "background_color",
- &pipe->background_property,
- &prop_value,
- NULL);
- pipe->background = (uint32_t)prop_value;
- get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
- "DEGAMMA_LUT",
- &pipe->degamma_property,
- NULL,
- NULL);
- get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
- "CTM",
- &pipe->ctm_property,
- NULL,
- NULL);
- get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
- "GAMMA_LUT",
- &pipe->gamma_property,
- NULL,
- NULL);
- }
- }
+ igt_output_refresh(output, true);
}
drmModeFreePlaneResources(plane_resources);
@@ -1545,7 +1613,7 @@ static void igt_display_refresh(igt_display_t *display)
if (output->pending_crtc_idx_mask == -1UL)
continue;
- igt_output_refresh(output);
+ igt_output_refresh(output, false);
}
for (i = 0; i < display->n_outputs; i++) {
igt_output_t *output = &display->outputs[i];
@@ -1553,7 +1621,7 @@ static void igt_display_refresh(igt_display_t *display)
if (output->pending_crtc_idx_mask != -1UL)
continue;
- igt_output_refresh(output);
+ igt_output_refresh(output, false);
}
}
@@ -1636,12 +1704,12 @@ static uint32_t igt_plane_get_fb_gem_handle(igt_plane_t *plane)
* Add position and fb changes of a plane to the atomic property set
*/
static void
-igt_atomic_prepare_plane_commit(igt_plane_t *plane, igt_output_t *output,
+igt_atomic_prepare_plane_commit(igt_plane_t *plane, igt_pipe_t *pipe,
drmModeAtomicReq *req)
{
- igt_display_t *display = output->display;
- uint32_t fb_id, crtc_id;
+ igt_display_t *display = pipe->display;
+ uint32_t fb_id, crtc_id = 0;
igt_assert(plane->drm_plane);
@@ -1650,14 +1718,13 @@ igt_atomic_prepare_plane_commit(igt_plane_t *plane, igt_output_t *output,
!plane->rotation_changed);
fb_id = igt_plane_get_fb_id(plane);
- crtc_id = output->config.crtc->crtc_id;
+ crtc_id = pipe->crtc_id;
LOG(display,
- "%s: populating plane data: %s.%d, fb %u\n",
- igt_output_name(output),
- kmstest_pipe_name(output->config.pipe),
+ "populating plane data: %s.%d, fb %u, crtc %u\n",
+ kmstest_pipe_name(pipe->pipe),
plane->index,
- fb_id);
+ fb_id, crtc_id);
if (plane->fb_changed) {
igt_atomic_populate_plane_req(req, plane, IGT_PLANE_CRTC_ID, fb_id ? crtc_id : 0);
@@ -1694,11 +1761,6 @@ igt_atomic_prepare_plane_commit(igt_plane_t *plane, igt_output_t *output,
if (plane->rotation_changed)
igt_atomic_populate_plane_req(req, plane,
IGT_PLANE_ROTATION, plane->rotation);
-
- plane->fb_changed = false;
- plane->position_changed = false;
- plane->size_changed = false;
- plane->rotation_changed = false;
}
@@ -1984,8 +2046,6 @@ static int igt_output_commit(igt_output_t *output,
if (pipe->background_changed) {
igt_crtc_set_property(output, pipe->background_property,
pipe->background);
-
- pipe->background_changed = false;
}
if (pipe->color_mgmt_changed) {
@@ -1995,8 +2055,6 @@ static int igt_output_commit(igt_output_t *output,
pipe->ctm_blob);
igt_crtc_set_property(output, pipe->gamma_property,
pipe->gamma_blob);
-
- pipe->color_mgmt_changed = false;
}
for (i = 0; i < pipe->n_planes; i++) {
@@ -2024,18 +2082,27 @@ static int igt_output_commit(igt_output_t *output,
/*
* Add crtc property changes to the atomic property set
*/
-static void igt_atomic_prepare_crtc_commit(igt_output_t *output, drmModeAtomicReq *req)
+static void igt_atomic_prepare_crtc_commit(igt_pipe_t *pipe_obj, drmModeAtomicReq *req)
{
+ LOG(pipe_obj->display,
+ "populating crtc data: %s, active %u, mode id %"PRIu64", changed %u %u %u %u\n",
+ kmstest_pipe_name(pipe_obj->pipe), !!pipe_obj->active,
+ pipe_obj->mode_id, pipe_obj->active_changed, pipe_obj->mode_changed,
+ pipe_obj->background_changed, pipe_obj->color_mgmt_changed);
+
+ if (pipe_obj->active_changed)
+ igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_ACTIVE, pipe_obj->active);
- igt_pipe_t *pipe_obj = igt_output_get_driving_pipe(output);
+ if (pipe_obj->mode_changed)
+ igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_MODE_ID, pipe_obj->mode_id);
if (pipe_obj->background_changed)
- igt_atomic_populate_crtc_req(req, output, IGT_CRTC_BACKGROUND, pipe_obj->background);
+ igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_BACKGROUND, pipe_obj->background);
if (pipe_obj->color_mgmt_changed) {
- igt_atomic_populate_crtc_req(req, output, IGT_CRTC_DEGAMMA_LUT, pipe_obj->degamma_blob);
- igt_atomic_populate_crtc_req(req, output, IGT_CRTC_CTM, pipe_obj->ctm_blob);
- igt_atomic_populate_crtc_req(req, output, IGT_CRTC_GAMMA_LUT, pipe_obj->gamma_blob);
+ igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_DEGAMMA_LUT, pipe_obj->degamma_blob);
+ igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_CTM, pipe_obj->ctm_blob);
+ igt_atomic_populate_crtc_req(req, pipe_obj, IGT_CRTC_GAMMA_LUT, pipe_obj->gamma_blob);
}
/*
@@ -2048,18 +2115,17 @@ static void igt_atomic_prepare_crtc_commit(igt_output_t *output, drmModeAtomicRe
*/
static void igt_atomic_prepare_connector_commit(igt_output_t *output, drmModeAtomicReq *req)
{
-
struct kmstest_connector_config *config = &output->config;
if (config->connector_scaling_mode_changed)
igt_atomic_populate_connector_req(req, output, IGT_CONNECTOR_SCALING_MODE, config->connector_scaling_mode);
- if (config->connector_dpms_changed)
- igt_atomic_populate_connector_req(req, output, IGT_CONNECTOR_DPMS, config->connector_dpms);
/*
* TODO: Add all other connector level properties here
*/
+ if (config->crtc_changed)
+ igt_atomic_populate_connector_req(req, output, IGT_CONNECTOR_CRTC_ID, config->crtc_idx);
}
/*
@@ -2068,7 +2134,7 @@ static void igt_atomic_prepare_connector_commit(igt_output_t *output, drmModeAto
*/
static int igt_atomic_commit(igt_display_t *display)
{
-
+ enum pipe pipe;
int ret = 0;
drmModeAtomicReq *req;
igt_output_t *output;
@@ -2077,33 +2143,28 @@ static int igt_atomic_commit(igt_display_t *display)
req = drmModeAtomicAlloc();
drmModeAtomicSetCursor(req, 0);
- for_each_connected_output(display, output) {
- igt_pipe_t *pipe_obj;
- igt_plane_t *plane;
- enum pipe pipe;
-
- /*
- * Add CRTC Properties to the property set
- */
- igt_atomic_prepare_crtc_commit(output, req);
-
+ for_each_output(display, output) {
/*
* Add Connector Properties to the property set
*/
igt_atomic_prepare_connector_commit(output, req);
+ }
+ for_each_pipe(display, pipe) {
+ igt_pipe_t *pipe_obj = &display->pipes[pipe];
+ igt_plane_t *plane;
- pipe_obj = igt_output_get_driving_pipe(output);
-
- pipe = pipe_obj->pipe;
+ /*
+ * Add CRTC Properties to the property set
+ */
- for_each_plane_on_pipe(display, pipe, plane) {
- igt_atomic_prepare_plane_commit(plane, output, req);
- }
+ igt_atomic_prepare_crtc_commit(pipe_obj, req);
+ for_each_plane_on_pipe(display, pipe, plane)
+ igt_atomic_prepare_plane_commit(plane, pipe_obj, req);
}
- ret = drmModeAtomicCommit(display->drm_fd, req, 0, NULL);
+ ret = drmModeAtomicCommit(display->drm_fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
drmModeAtomicFree(req);
return ret;
@@ -2121,37 +2182,56 @@ static int do_display_commit(igt_display_t *display,
enum igt_commit_style s,
bool fail_on_error)
{
- int i, ret;
+ int ret;
int valid_outs = 0;
+ igt_output_t *output;
+ enum pipe pipe;
LOG_INDENT(display, "commit");
- igt_display_refresh(display);
-
if (s == COMMIT_ATOMIC) {
-
ret = igt_atomic_commit(display);
CHECK_RETURN(ret, fail_on_error);
- return 0;
+ valid_outs = 1;
+ goto done;
}
- for (i = 0; i < display->n_outputs; i++) {
- igt_output_t *output = &display->outputs[i];
-
- if (!output->valid)
- continue;
+ igt_display_refresh(display);
+ for_each_connected_output(display, output) {
valid_outs++;
ret = igt_output_commit(output, s, fail_on_error);
CHECK_RETURN(ret, fail_on_error);
}
+done:
LOG_UNINDENT(display);
if (valid_outs == 0)
return -1;
+ for_each_pipe(display, pipe) {
+ igt_pipe_t *pipe_obj = &display->pipes[pipe];
+ igt_plane_t *plane;
+
+ pipe_obj->background_changed = 0;
+ pipe_obj->mode_changed = 0;
+ pipe_obj->active_changed = 0;
+ pipe_obj->color_mgmt_changed = 0;
+
+ for_each_plane_on_pipe(display, pipe, plane) {
+ plane->fb_changed = 0;
+ plane->position_changed = 0;
+ plane->panning_changed = 0;
+ plane->rotation_changed = 0;
+ plane->size_changed = 0;
+ }
+ }
+
+ for_each_output(display, output)
+ output->config.crtc_changed = 0;
+
igt_debug_wait_for_keypress("modeset");
return 0;
@@ -2247,6 +2327,114 @@ void igt_output_override_mode(igt_output_t *output, drmModeModeInfo *mode)
output->use_override_mode = true;
}
+static void
+igt_pipe_replace_blob(igt_pipe_t *pipe, uint64_t *blob, void *ptr, size_t length)
+{
+ igt_display_t *display = pipe->display;
+ uint32_t blob_id = 0;
+
+ if (*blob != 0) {
+ int ret = drmModeDestroyPropertyBlob(display->drm_fd, *blob);
+
+ /* Destroying blobs originating from the kernel
+ * will fail with -EPERM, ignore it. */
+ igt_assert(ret == 0 || ret == -EPERM);
+ }
+
+ if (length > 0)
+ igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
+ ptr, length, &blob_id) == 0);
+
+ *blob = blob_id;
+}
+
+static void
+igt_output_unset_pipe_atomic(igt_output_t *output)
+{
+ igt_display_t *display = output->display;
+ enum pipe old_pipe = output->config.pipe;
+
+ if (old_pipe != PIPE_ANY) {
+ igt_pipe_t *pipe_obj = &display->pipes[old_pipe];
+ int i;
+
+ for (i = 0; i < display->n_outputs; i++)
+ if (output == &display->outputs[i])
+ break;
+
+ pipe_obj->atomic_connector_mask &= ~(1 << i);
+
+ if (!pipe_obj->atomic_connector_mask) {
+ pipe_obj->active = 0;
+ pipe_obj->active_changed = 1;
+
+ pipe_obj->mode_changed = 1;
+ igt_pipe_replace_blob(pipe_obj, &pipe_obj->mode_id, NULL, 0);
+ LOG(pipe_obj->display, "%s was last active, disabling %s\n",
+ igt_output_name(output), kmstest_pipe_name(old_pipe));
+ } else
+ LOG(pipe_obj->display, "%s Connector mask on %s is now %x\n",
+ igt_output_name(output), kmstest_pipe_name(old_pipe), pipe_obj->atomic_connector_mask);
+ }
+
+ kmstest_free_connector_config(&output->config);
+ output->config.connector = drmModeGetConnectorCurrent(display->drm_fd, output->id);
+ output->config.encoder = NULL;
+ output->config.crtc = NULL;
+ output->config.pipe = PIPE_ANY;
+ output->config.crtc_idx = 0;
+ output->config.crtc_changed = 1;
+}
+
+static void
+igt_output_set_pipe_atomic(igt_output_t *output, enum pipe pipe)
+{
+ igt_display_t *display = output->display;
+ igt_output_t *iter;
+ int i;
+
+ for (i = 0; i < display->n_outputs; i++)
+ if (output == &display->outputs[i])
+ break;
+
+ if (pipe != PIPE_ANY) {
+ for_each_output(display, iter)
+ if (iter->pending_crtc_idx_mask == -1ULL && iter->config.pipe == pipe)
+ igt_output_unset_pipe_atomic(iter);
+ }
+
+ igt_output_unset_pipe_atomic(output);
+
+ if (pipe != PIPE_ANY) {
+ igt_pipe_t *pipe_obj = &display->pipes[pipe];
+
+ output->config.pipe = pipe;
+ output->config.crtc_idx = pipe_obj->crtc_id;
+ output->config.crtc = drmModeGetCrtc(display->drm_fd, pipe_obj->crtc_id);
+
+ if (!pipe_obj->atomic_connector_mask) {
+ drmModeModeInfo *mode;
+
+ LOG(pipe_obj->display, "First active connector enabling %s\n",
+ kmstest_pipe_name(pipe));
+
+ pipe_obj->active = 1;
+ pipe_obj->active_changed = 1;
+ pipe_obj->mode_changed = 1;
+
+ mode = igt_output_get_mode(output);
+ if (output->use_override_mode)
+ mode = &output->override_mode;
+
+ igt_pipe_replace_blob(pipe_obj, &pipe_obj->mode_id, mode, sizeof(*mode));
+ } else
+ LOG(pipe_obj->display, "Connector mask on %s was %x\n",
+ kmstest_pipe_name(pipe), pipe_obj->atomic_connector_mask);
+
+ pipe_obj->atomic_connector_mask |= 1 << i;
+ }
+}
+
void igt_output_set_pipe(igt_output_t *output, enum pipe pipe)
{
igt_display_t *display = output->display;
@@ -2259,6 +2447,8 @@ void igt_output_set_pipe(igt_output_t *output, enum pipe pipe)
kmstest_pipe_name(pipe));
output->pending_crtc_idx_mask = 1 << pipe;
}
+
+ igt_output_set_pipe_atomic(output, pipe);
}
igt_plane_t *igt_output_get_plane(igt_output_t *output, enum igt_plane plane)
@@ -2432,23 +2622,6 @@ void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation)
plane->rotation_changed = true;
}
-static void
-igt_pipe_replace_blob(igt_pipe_t *pipe, uint64_t *blob, void *ptr, size_t length)
-{
- igt_display_t *display = pipe->display;
- uint32_t blob_id = 0;
-
- if (*blob != 0)
- igt_assert(drmModeDestroyPropertyBlob(display->drm_fd,
- *blob) == 0);
-
- if (length > 0)
- igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
- ptr, length, &blob_id) == 0);
-
- *blob = blob_id;
-}
-
void
igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
{
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index b66743a2..f34f6c6d 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -92,12 +92,14 @@ enum igt_atomic_crtc_properties {
IGT_CRTC_CTM,
IGT_CRTC_DEGAMMA_LUT,
IGT_CRTC_GAMMA_LUT,
+ IGT_CRTC_MODE_ID,
+ IGT_CRTC_ACTIVE,
IGT_NUM_CRTC_PROPS
};
enum igt_atomic_connector_properties {
IGT_CONNECTOR_SCALING_MODE = 0,
- IGT_CONNECTOR_DPMS,
+ IGT_CONNECTOR_CRTC_ID,
IGT_NUM_CONNECTOR_PROPS
};
@@ -107,10 +109,7 @@ struct kmstest_connector_config {
drmModeEncoder *encoder;
drmModeModeInfo default_mode;
uint64_t connector_scaling_mode;
- bool connector_scaling_mode_changed;
- uint64_t connector_dpms;
- bool connector_dpms_changed;
- uint32_t atomic_props_crtc[IGT_NUM_CRTC_PROPS];
+ bool connector_scaling_mode_changed, crtc_changed;
uint32_t atomic_props_connector[IGT_NUM_CONNECTOR_PROPS];
int crtc_idx;
int pipe;
@@ -250,11 +249,22 @@ struct igt_pipe {
enum pipe pipe;
bool enabled;
int n_planes;
+
+ uint32_t atomic_props_crtc[IGT_NUM_CRTC_PROPS];
+
igt_plane_t planes[IGT_MAX_PLANES];
uint64_t background; /* Background color MSB BGR 16bpc LSB */
uint32_t background_changed : 1;
uint32_t background_property;
+ uint64_t mode_id;
+ uint32_t mode_changed : 1;
+
+ uint32_t atomic_connector_mask;
+
+ uint32_t active;
+ uint32_t active_changed : 1;
+
uint64_t degamma_blob;
uint32_t degamma_property;
uint64_t ctm_blob;
@@ -336,6 +346,10 @@ static inline bool igt_pipe_connector_valid(enum pipe pipe,
#define for_each_if(condition) if (!(condition)) {} else
+#define for_each_output(display, output) \
+ for (int i__ = 0; i__ < (display)->n_outputs; i__++) \
+ for_each_if (((output = &(display)->outputs[i__]), 1))
+
#define for_each_connected_output(display, output) \
for (int i__ = 0; i__ < (display)->n_outputs; i__++) \
for_each_if (((output = &(display)->outputs[i__]), output->valid))
@@ -352,7 +366,7 @@ static inline bool igt_pipe_connector_valid(enum pipe pipe,
igt_pipe_connector_valid(pipe, output)))
#define for_each_valid_output_on_pipe(display, pipe, output) \
- for_each_connected_output(display, output) \
+ for_each_output(display, output) \
for_each_if (igt_pipe_connector_valid(pipe, output))
#define for_each_plane_on_pipe(display, pipe, plane) \
@@ -379,9 +393,9 @@ static inline bool igt_pipe_connector_valid(enum pipe pipe,
* @prop: one of igt_atomic_crtc_properties
* @value: the value to add
*/
-#define igt_atomic_populate_crtc_req(req, output, prop, value) \
- igt_assert_lt(0, drmModeAtomicAddProperty(req, output->config.crtc->crtc_id,\
- output->config.atomic_props_crtc[prop], value))
+#define igt_atomic_populate_crtc_req(req, pipe_obj, prop, value) \
+ igt_assert_lt(0, drmModeAtomicAddProperty(req, pipe_obj->crtc_id,\
+ pipe_obj->atomic_props_crtc[prop], value))
/**
* igt_atomic_populate_connector_req:
* @req: A pointer to drmModeAtomicReq
diff --git a/tests/kms_rmfb.c b/tests/kms_rmfb.c
index 89aa3232..d6ad41fe 100644
--- a/tests/kms_rmfb.c
+++ b/tests/kms_rmfb.c
@@ -60,7 +60,7 @@ test_rmfb(struct rmfb_data *data, igt_output_t *output, enum pipe pipe, bool reo
uint64_t cursor_width, cursor_height;
igt_output_set_pipe(output, pipe);
- igt_display_commit(&data->display);
+ igt_display_commit2(&data->display, data->display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
if (!output->valid) {
igt_output_set_pipe(output, PIPE_ANY);
@@ -129,10 +129,16 @@ test_rmfb(struct rmfb_data *data, igt_output_t *output, enum pipe pipe, bool reo
igt_assert_eq(planeres->fb_id, 0);
drmModeFreePlane(planeres);
+ igt_plane_set_fb(plane, NULL);
}
+ for_each_pipe(&data->display, pipe)
+ data->display.pipes[pipe].mode_id = 0;
+
igt_output_set_pipe(output, PIPE_ANY);
- igt_display_commit2(&data->display, data->display.is_atomic ? COMMIT_ATOMIC : COMMIT_UNIVERSAL);
+
+ if (!data->display.is_atomic)
+ igt_display_commit2(&data->display, COMMIT_UNIVERSAL);
return true;
}