Hi, See bellow: On Wed, Mar 09, 2016 at 07:43:54PM +0530, Mayuresh Gharpure wrote: > Co-Author : Marius Vlad > Co-Author : Pratik Vishwakarma > > So far we have had only two commit styles, COMMIT_LEGACY > and COMMIT_UNIVERSAL. This patch adds another commit style > COMMIT_ATOMIC which makes use of drmModeAtomicCommit() > > v2: (Marius) > i)Set CRTC_ID to zero while disabling plane > ii)Modified the log message in igt_atomic_prepare_plane_commit > https://patchwork.freedesktop.org/patch/71945/ > > v3: (Marius)Set FB_ID to zero while disabling plane > https://patchwork.freedesktop.org/patch/72179/ > > v4: (Maarten) Corrected the typo in commit message > https://patchwork.freedesktop.org/patch/72598/ > > v5: Added check for DRM_CLIENT_CAP_ATOMIC in igt_display_init > (Marius) > i)Removed unused props from igt_display_init > ii)Removed unused ret. Changed function to void > iii)Declare the variable before checking if we have > DRM_CLIENT_CAP_ATOMIC. > https://patchwork.freedesktop.org/patch/73505/ > > v6: (Jani) Corrected typo in commit message > > v7: Added is_atomic check for DRM_CLIENT_CAP_ATOMIC in > igt_display_init and igt_atomic_commit > > v8: (Matthew Auld) Replaced for loops by for_each_connected_output and > for_each_plane_on_pipe > (Lionel) Populate properties only if the value has changed > Remove the resetting of values in disable case > Note : I've used Maarten's diff patch > > Signed-off-by: Mayuresh Gharpure > Signed-off-by: Pratik Vishwakarma > Signed-off-by: Mayuresh Gharpure > --- > Incorporated Comments Matthew and Lionel > lib/igt_kms.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > lib/igt_kms.h | 72 ++++++++++++++- > 2 files changed, 359 insertions(+), 2 deletions(-) > > diff --git a/lib/igt_kms.c b/lib/igt_kms.c > index 9f18aef..5b6c324 100644 > --- a/lib/igt_kms.c > +++ b/lib/igt_kms.c > @@ -145,6 +145,120 @@ const unsigned char* igt_kms_get_base_edid(void) > * > * Returns: an alternate edid block > */ > +static const char *igt_plane_prop_names[IGT_NUM_PLANE_PROPS] = { > + "SRC_X", > + "SRC_Y", > + "SRC_W", > + "SRC_H", > + "CRTC_X", > + "CRTC_Y", > + "CRTC_W", > + "CRTC_H", > + "FB_ID", > + "CRTC_ID", > + "type", > + "rotation" > +}; > + > +static const char *igt_crtc_prop_names[IGT_NUM_CRTC_PROPS] = { > + "background_color" > +}; > + > +static const char *igt_connector_prop_names[IGT_NUM_CONNECTOR_PROPS] = { > + "scaling mode", > + "DPMS" > +}; > + > +/* > + * Retrieve all the properies specified in props_name and store them into > + * plane->atomic_props_plane. > + */ > +static void > +igt_atomic_fill_plane_props(igt_display_t *display, igt_plane_t *plane, > + int num_props, const char **prop_names) > +{ > + drmModeObjectPropertiesPtr props; > + int i, j, fd; > + > + fd = display->drm_fd; > + > + props = drmModeObjectGetProperties(fd, plane->drm_plane->plane_id, DRM_MODE_OBJECT_PLANE); > + igt_assert(props); > + > + for (i = 0; i < props->count_props; i++) { > + drmModePropertyPtr prop = > + drmModeGetProperty(fd, props->props[i]); > + > + for (j = 0; j < num_props; j++) { > + if (strcmp(prop->name, prop_names[j]) != 0) > + continue; > + > + plane->atomic_props_plane[j] = props->props[i]; > + break; > + } > + > + drmModeFreeProperty(prop); > + } > + > + drmModeFreeObjectProperties(props); > +} > + > +/* > + * Retrieve all the properies specified in props_name and store them into > + * config->atomic_props_crtc and 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, > + int num_connector_props, const char **conn_prop_names) > +{ > + drmModeObjectPropertiesPtr props; > + int i, j, fd; > + > + fd = display->drm_fd; > + > + props = drmModeObjectGetProperties(fd, output->config.crtc->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_crtc_props; j++) { > + if (strcmp(prop->name, crtc_prop_names[j]) != 0) > + continue; > + > + output->config.atomic_props_crtc[j] = props->props[i]; > + break; > + } > + > + drmModeFreeProperty(prop); > + } > + > + drmModeFreeObjectProperties(props); > + props = NULL; > + props = drmModeObjectGetProperties(fd, output->config.connector->connector_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_connector_props; j++) { > + if (strcmp(prop->name, conn_prop_names[j]) != 0) > + continue; > + > + output->config.atomic_props_connector[j] = props->props[i]; > + break; > + } > + > + drmModeFreeProperty(prop); > + } > + > + drmModeFreeObjectProperties(props); > + > +} > + > const unsigned char* igt_kms_get_alt_edid(void) > { > update_edid_csum(alt_edid); > @@ -1000,6 +1114,8 @@ static void igt_output_refresh(igt_output_t *output) > 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 > @@ -1069,6 +1185,7 @@ void igt_display_init(igt_display_t *display, int drm_fd) > drmModeRes *resources; > drmModePlaneRes *plane_resources; > int i; > + int is_atomic = 0; > > memset(display, 0, sizeof(igt_display_t)); > > @@ -1086,6 +1203,7 @@ void igt_display_init(igt_display_t *display, int drm_fd) > display->n_pipes = resources->count_crtcs; > > drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); > + is_atomic = drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1); > plane_resources = drmModeGetPlaneResources(display->drm_fd); > igt_assert(plane_resources); > > @@ -1142,6 +1260,10 @@ void igt_display_init(igt_display_t *display, int drm_fd) > > plane->pipe = pipe; > plane->drm_plane = drm_plane; > + if (is_atomic == 0) { > + display->is_atomic = 1; > + igt_atomic_fill_plane_props(display, plane, IGT_NUM_PLANE_PROPS, igt_plane_prop_names); > + } > > get_plane_property(display->drm_fd, drm_plane->plane_id, > "rotation", > @@ -1397,6 +1519,79 @@ static uint32_t igt_plane_get_fb_gem_handle(igt_plane_t *plane) > igt_assert(r == 0); \ > } > > + > + > + > +/* > + * 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, > + drmModeAtomicReq *req) > +{ > + > + igt_display_t *display = output->display; > + uint32_t fb_id, crtc_id; > + > + igt_assert(plane->drm_plane); > + > + /* it's an error to try an unsupported feature */ > + igt_assert(igt_plane_supports_rotation(plane) || > + !plane->rotation_changed); > + > + fb_id = igt_plane_get_fb_id(plane); > + crtc_id = output->config.crtc->crtc_id; > + > + LOG(display, > + "%s: populating plane data: %s.%d, fb %u\n", > + igt_output_name(output), > + kmstest_pipe_name(output->config.pipe), > + plane->index, > + fb_id); > + > + if (plane->fb_changed) { > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_CRTC_ID, fb_id ? crtc_id : 0); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_FB_ID, fb_id); > + } > + > + if (plane->position_changed || plane->size_changed) { > + uint32_t src_x = IGT_FIXED(plane->fb->src_x, 0); /* src_x */ > + uint32_t src_y = IGT_FIXED(plane->fb->src_y, 0); /* src_y */ > + uint32_t src_w = IGT_FIXED(plane->fb->src_w, 0); /* src_w */ > + uint32_t src_h = IGT_FIXED(plane->fb->src_h, 0); /* src_h */ > + int32_t crtc_x = plane->crtc_x; > + int32_t crtc_y = plane->crtc_y; > + uint32_t crtc_w = plane->crtc_w; > + uint32_t crtc_h = plane->crtc_h; > + > + LOG(display, > + "src = (%d, %d) %u x %u " > + "dst = (%d, %d) %u x %u\n", > + src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16, > + crtc_x, crtc_y, crtc_w, crtc_h); > + > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_SRC_X, src_x); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_SRC_Y, src_y); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_SRC_W, src_w); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_SRC_H, src_h); > + > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_CRTC_X, crtc_x); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_CRTC_Y, crtc_y); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_CRTC_W, crtc_w); > + igt_atomic_populate_plane_req(req, plane, IGT_PLANE_CRTC_H, crtc_h); > + } > + > + 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; > +} > + > + > + > /* > * Commit position and fb changes to a DRM plane via the SetPlane ioctl; if the > * DRM call to program the plane fails, we'll either fail immediately (for > @@ -1649,7 +1844,7 @@ static int igt_plane_commit(igt_plane_t *plane, > return igt_primary_plane_commit_legacy(plane, output, > fail_on_error); > } else { > - return igt_drm_plane_commit(plane, output, fail_on_error); > + return igt_drm_plane_commit(plane, output, fail_on_error); > } > } > > @@ -1703,6 +1898,90 @@ static int igt_output_commit(igt_output_t *output, > return 0; > } > > + > +/* > + * Add crtc property changes to the atomic property set > + */ > +static void igt_atomic_prepare_crtc_commit(igt_output_t *output, drmModeAtomicReq *req) > +{ > + > + igt_pipe_t *pipe_obj = igt_output_get_driving_pipe(output); > + > + if (pipe_obj->background_changed) > + igt_atomic_populate_crtc_req(req, output, IGT_CRTC_BACKGROUND, pipe_obj->background); > + > + /* > + * TODO: Add all crtc level properties here > + */ > + > +} > + > +/* > + * Add connector property changes to the atomic property set > + */ > +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 > + */ > + > +} > + > +/* > + * Commit all the changes of all the planes,crtcs, connectors > + * atomically using drmModeAtomicCommit() > + */ > +static int igt_atomic_commit(igt_display_t *display) > +{ > + > + int ret = 0; > + int i = 0; This is not used. > + drmModeAtomicReq *req; > + igt_output_t *output; > + if (display->is_atomic != 1) > + return -1; > + req = drmModeAtomicAlloc(); > + drmModeAtomicSetCursor(req, 0); > + > + for_each_connected_output(display, output) { for_each_connected_output() combined with for_each_plane_on_pipe() will yield a shadow declaration on the same variable (i__). > + 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); > + > + /* > + * Add Connector Properties to the property set > + */ > + igt_atomic_prepare_connector_commit(output, req); > + > + > + pipe_obj = igt_output_get_driving_pipe(output); > + > + pipe = pipe_obj->pipe; > + > + for_each_plane_on_pipe(display, pipe, plane) { > + igt_atomic_prepare_plane_commit(plane, output, req); > + } > + > + } > + > + ret = drmModeAtomicCommit(display->drm_fd, req, 0, NULL); > + drmModeAtomicFree(req); > + return ret; > + > +} > /* > * Commit all plane changes across all outputs of the display. > * > @@ -1722,6 +2001,14 @@ static int do_display_commit(igt_display_t *display, > > igt_display_refresh(display); > > + if (s == COMMIT_ATOMIC) { > + > + ret = igt_atomic_commit(display); > + CHECK_RETURN(ret, fail_on_error); > + return 0; > + > + } > + > for (i = 0; i < display->n_outputs; i++) { > igt_output_t *output = &display->outputs[i]; > > diff --git a/lib/igt_kms.h b/lib/igt_kms.h > index 5744ed0..d6e2f12 100644 > --- a/lib/igt_kms.h > +++ b/lib/igt_kms.h > @@ -106,11 +106,28 @@ int kmstest_get_pipe_from_crtc_id(int fd, int crtc_id); > void kmstest_set_vt_graphics_mode(void); > void kmstest_restore_vt_mode(void); > > +enum igt_atomic_crtc_properties { > + IGT_CRTC_BACKGROUND = 0, > + IGT_NUM_CRTC_PROPS > +}; > + > +enum igt_atomic_connector_properties { > + IGT_CONNECTOR_SCALING_MODE = 0, > + IGT_CONNECTOR_DPMS, > + IGT_NUM_CONNECTOR_PROPS > +}; > + > struct kmstest_connector_config { > drmModeCrtc *crtc; > drmModeConnector *connector; > 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]; > + uint32_t atomic_props_connector[IGT_NUM_CONNECTOR_PROPS]; > int crtc_idx; > int pipe; > }; > @@ -163,9 +180,28 @@ uint32_t kmstest_find_crtc_for_connector(int fd, drmModeRes *res, > enum igt_commit_style { > COMMIT_LEGACY = 0, > COMMIT_UNIVERSAL, > - /* We'll add atomic here eventually. */ > + COMMIT_ATOMIC, > }; > > +enum igt_atomic_plane_properties { > + IGT_PLANE_SRC_X = 0, > + IGT_PLANE_SRC_Y, > + IGT_PLANE_SRC_W, > + IGT_PLANE_SRC_H, > + > + IGT_PLANE_CRTC_X, > + IGT_PLANE_CRTC_Y, > + IGT_PLANE_CRTC_W, > + IGT_PLANE_CRTC_H, > + > + IGT_PLANE_FB_ID, > + IGT_PLANE_CRTC_ID, > + IGT_PLANE_TYPE, > + IGT_PLANE_ROTATION, > + IGT_NUM_PLANE_PROPS > +}; > + > + > typedef struct igt_display igt_display_t; > typedef struct igt_pipe igt_pipe_t; > typedef uint32_t igt_fixed_t; /* 16.16 fixed point */ > @@ -207,6 +243,7 @@ typedef struct { > /* panning offset within the fb */ > unsigned int pan_x, pan_y; > igt_rotation_t rotation; > + uint32_t atomic_props_plane[IGT_NUM_PLANE_PROPS]; > } igt_plane_t; > > struct igt_pipe { > @@ -242,6 +279,7 @@ struct igt_display { > igt_output_t *outputs; > igt_pipe_t pipes[I915_MAX_PIPES]; > bool has_universal_planes; > + bool is_atomic; > }; > > void igt_display_init(igt_display_t *display, int drm_fd); > @@ -288,6 +326,38 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe); > > #define IGT_FIXED(i,f) ((i) << 16 | (f)) > > +/** > + * igt_atomic_populate_plane_req: > + * @req: A pointer to drmModeAtomicReq > + * @plane: A pointer igt_plane_t > + * @prop: one of igt_atomic_plane_properties > + * @value: the value to add > + */ > +#define igt_atomic_populate_plane_req(req, plane, prop, value) \ > + igt_assert_lt(0, drmModeAtomicAddProperty(req, plane->drm_plane->plane_id,\ > + plane->atomic_props_plane[prop], value)) > + > +/** > + * igt_atomic_populate_crtc_req: > + * @req: A pointer to drmModeAtomicReq > + * @output: A pointer igt_output_t > + * @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)) > +/** > + * igt_atomic_populate_connector_req: > + * @req: A pointer to drmModeAtomicReq > + * @output: A pointer igt_output_t > + * @prop: one of igt_atomic_connector_properties > + * @value: the value to add > + */ > +#define igt_atomic_populate_connector_req(req, output, prop, value) \ > + igt_assert_lt(0, drmModeAtomicAddProperty(req, output->config.connector->connector_id,\ > + output->config.atomic_props_connector[prop], value)) > + > void igt_enable_connectors(void); > void igt_reset_connectors(void); > > -- > 1.9.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx