On Fri, Nov 15, 2019 at 12:00:01AM +0000, Mihail Atanassov wrote: > On Thursday, 14 November 2019 08:37:31 GMT james qian wang (Arm Technology China) wrote: > > On side by side mode, The full display frame will be split into two parts > > (Left/Right), and each part will be handled by a single pipeline separately > > master pipeline for left part, slave for right. > > > > To simplify the usage and implementation, komeda use the following scheme > > to do the side by side split > > 1. The planes also have been grouped into two classes: > > master-planes and slave-planes. > > 2. The master plane can display its image on any location of the final/full > > display frame, komeda will help to split the plane configuration to two > > parts and fed them into master and slave pipelines. > > 3. The slave plane only can put its display rect on the right part of the > > final display frame, and its data is only can be fed into the slave > > pipeline. > > > > From the perspective of resource usage and assignment: > > The master plane can use the resources from the master pipeline and slave > > pipeline both, but slave plane only can use the slave pipeline resources. > > > > With such scheme, the usage of master planes are same as the none > > side_by_side mode. user can easily skip the slave planes and no need to > > consider side_by_side for them. > > > > Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@xxxxxxx> > > --- > > .../drm/arm/display/komeda/komeda_pipeline.h | 33 ++- > > .../display/komeda/komeda_pipeline_state.c | 188 ++++++++++++++++++ > > .../gpu/drm/arm/display/komeda/komeda_plane.c | 7 +- > > 3 files changed, 220 insertions(+), 8 deletions(-) > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h > > index 20a076cce635..4c0946fbaac1 100644 > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h > > @@ -521,6 +521,20 @@ komeda_component_pickup_output(struct komeda_component *c, u32 avail_comps) > > return komeda_pipeline_get_first_component(c->pipeline, avail_inputs); > > } > > > > +static inline const char * > > +komeda_data_flow_msg(struct komeda_data_flow_cfg *config) > > +{ > > + static char str[128]; > > + > > + snprintf(str, sizeof(str), > > + "rot: %x src[x/y:%d/%d, w/h:%d/%d] disp[x/y:%d/%d, w/h:%d/%d]", > > + config->rot, > > + config->in_x, config->in_y, config->in_w, config->in_h, > > + config->out_x, config->out_y, config->out_w, config->out_h); > > + > > + return str; > > +} > > + > > struct komeda_plane_state; > > struct komeda_crtc_state; > > struct komeda_crtc; > > @@ -532,22 +546,27 @@ int komeda_build_layer_data_flow(struct komeda_layer *layer, > > struct komeda_plane_state *kplane_st, > > struct komeda_crtc_state *kcrtc_st, > > struct komeda_data_flow_cfg *dflow); > > -int komeda_build_wb_data_flow(struct komeda_layer *wb_layer, > > - struct drm_connector_state *conn_st, > > - struct komeda_crtc_state *kcrtc_st, > > - struct komeda_data_flow_cfg *dflow); > > -int komeda_build_display_data_flow(struct komeda_crtc *kcrtc, > > - struct komeda_crtc_state *kcrtc_st); > > - > > int komeda_build_layer_split_data_flow(struct komeda_layer *left, > > struct komeda_plane_state *kplane_st, > > struct komeda_crtc_state *kcrtc_st, > > struct komeda_data_flow_cfg *dflow); > > +int komeda_build_layer_sbs_data_flow(struct komeda_layer *layer, > > + struct komeda_plane_state *kplane_st, > > + struct komeda_crtc_state *kcrtc_st, > > + struct komeda_data_flow_cfg *dflow); > > + > > +int komeda_build_wb_data_flow(struct komeda_layer *wb_layer, > > + struct drm_connector_state *conn_st, > > + struct komeda_crtc_state *kcrtc_st, > > + struct komeda_data_flow_cfg *dflow); > > int komeda_build_wb_split_data_flow(struct komeda_layer *wb_layer, > > struct drm_connector_state *conn_st, > > struct komeda_crtc_state *kcrtc_st, > > struct komeda_data_flow_cfg *dflow); > > > > +int komeda_build_display_data_flow(struct komeda_crtc *kcrtc, > > + struct komeda_crtc_state *kcrtc_st); > > + > > int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe, > > struct komeda_crtc_state *kcrtc_st); > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c > > index 0930234abb9d..5de0d231a1c3 100644 > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c > > @@ -1130,6 +1130,194 @@ int komeda_build_layer_split_data_flow(struct komeda_layer *left, > > return err; > > } > > > > +/* split func will split configuration of master plane to two layer data > > + * flows, which will be fed into master and slave pipeline then. > > + * NOTE: @m_dflow is first used as input argument to pass the configuration of > > + * master_plane. when the split is done, @*m_dflow @*s_dflow are the > > + * output data flow for pipeline. > > + */ > > +static int > > +komeda_split_sbs_master_data_flow(struct komeda_crtc_state *kcrtc_st, > > + struct komeda_data_flow_cfg **m_dflow, > > + struct komeda_data_flow_cfg **s_dflow) > > +{ > > + struct komeda_data_flow_cfg *master = *m_dflow; > > + struct komeda_data_flow_cfg *slave = *s_dflow; > > + u32 disp_end = master->out_x + master->out_w; > > + u16 boundary; > > + > > + pipeline_composition_size(kcrtc_st, &boundary, NULL); > > + > > + if (disp_end <= boundary) { > > + /* the master viewport only located in master side, no need > > + * slave anymore > > + */ > > + *s_dflow = NULL; > > + } else if ((master->out_x < boundary) && (disp_end > boundary)) { > > + /* the master viewport across two pipelines, split it */ > > + bool flip_h = has_flip_h(master->rot); > > + bool r90 = drm_rotation_90_or_270(master->rot); > > + u32 src_x = master->in_x; > > + u32 src_y = master->in_y; > > + u32 src_w = master->in_w; > > + u32 src_h = master->in_h; > > + > > + if (master->en_scaling || master->en_img_enhancement) { > > + DRM_DEBUG_ATOMIC("sbs doesn't support to split a scaling image.\n"); > > + return -EINVAL; > > + } > > + > > + memcpy(slave, master, sizeof(*master)); > > + > > + /* master for left part of display, slave for the right part */ > > + /* split the disp_rect */ > > + master->out_w = boundary - master->out_x; > > + slave->out_w = disp_end - boundary; > > + slave->out_x = 0; > > + > > + if (r90) { > > + master->in_h = master->out_w; > > + slave->in_h = slave->out_w; > > + > > + if (flip_h) > > + master->in_y = src_y + src_h - master->in_h; > > + else > > + slave->in_y = src_y + src_h - slave->in_h; > > + } else { > > + master->in_w = master->out_w; > > + slave->in_w = slave->out_w; > > + > > + /* on flip_h, the left display content from the right-source */ > > + if (flip_h) > > + master->in_x = src_w + src_x - master->in_w; > > + else > > + slave->in_x = src_w + src_x - slave->in_w; > > It really bugs me that the order here is w/x/w but in the block above > it's y/h/h. will refine the order to x/w/w. > > + } > > + } else if (master->out_x >= boundary) { > > + /* disp_rect only locate in right part, move the dflow to slave */ > > + master->out_x -= boundary; > > + *s_dflow = master; > > + *m_dflow = NULL; > > + } > > + > > + return 0; > > +} > > + > > +static int > > +komeda_split_sbs_slave_data_flow(struct komeda_crtc_state *kcrtc_st, > > + struct komeda_data_flow_cfg *slave) > > +{ > > + u16 boundary; > > + > > + pipeline_composition_size(kcrtc_st, &boundary, NULL); > > + > > + if (slave->out_x < boundary) { > > + DRM_DEBUG_ATOMIC("SBS Slave plane is only allowed to configure the right part frame.\n"); > > + return -EINVAL; > > + } > > + > > + /* slave->disp_rect locate in the right part */ > > + slave->out_x -= boundary; > > + > > + return 0; > > +} > > + > > +/* On side by side mode, The full display frame will be split to two parts > > + * (Left/Right), and each part will be handled by a single pipeline separately, > > + * master pipeline for left part, slave for right. > > + * > > + * To simplify the usage and implementation, komeda use the following scheme > > + * to do the side by side split > > + * 1. The planes also have been grouped into two classes: > > + * master-planes and slave-planes. > > + * 2. The master plane can display its image on any location of the final/full > > + * display frame, komeda will help to split the plane configuration to two > > + * parts and fed them into master and slave pipelines. > > + * 3. The slave plane only can put its display rect on the right part of the > > + * final display frame, and its data is only can be fed into the slave > > + * pipeline. > > + * > > + * From the perspective of resource usage and assignment: > > + * The master plane can use the resources from the master pipeline and slave > > + * pipeline both, but slave plane only can use the slave pipeline resources. > > + * > > + * With such scheme, the usage of master planes are same as the none > > + * side_by_side mode. user can easily skip the slave planes and no need to > > + * consider side_by_side for them. > > + * > > + * NOTE: side_by_side split is occurred on pipeline level which split the plane > > + * data flow into pipelines, but the layer split is a pipeline > > + * internal split which splits the data flow into pipeline layers. > > + * So komeda still supports to apply a further layer split to the sbs > > + * split data flow. > > + */ > > +int komeda_build_layer_sbs_data_flow(struct komeda_layer *layer, > > + struct komeda_plane_state *kplane_st, > > + struct komeda_crtc_state *kcrtc_st, > > + struct komeda_data_flow_cfg *dflow) > > +{ > > + struct komeda_crtc *kcrtc = to_kcrtc(kcrtc_st->base.crtc); > > + struct drm_plane *plane = kplane_st->base.plane; > > + struct komeda_data_flow_cfg temp, *master_dflow, *slave_dflow; > > + struct komeda_layer *master, *slave; > > + bool master_plane = layer->base.pipeline == kcrtc->master; > > + int err; > > + > > + DRM_DEBUG_ATOMIC("SBS prepare %s-[PLANE:%d:%s]: %s.\n", > > + master_plane ? "Master" : "Slave", > > + plane->base.id, plane->name, > > + komeda_data_flow_msg(dflow)); > > + > > + if (master_plane) { > > + master = layer; > > + slave = layer->sbs_slave; > > + master_dflow = dflow; > > + slave_dflow = &temp; > > + err = komeda_split_sbs_master_data_flow(kcrtc_st, > > + &master_dflow, &slave_dflow); > > + } else { > > + master = NULL; > > + slave = layer; > > + master_dflow = NULL; > > + slave_dflow = dflow; > > + err = komeda_split_sbs_slave_data_flow(kcrtc_st, slave_dflow); > > + } > > + > > + if (err) > > + return err; > > + > > + if (master_dflow) { > > + DRM_DEBUG_ATOMIC("SBS Master-%s assigned: %s\n", > > + master->base.name, komeda_data_flow_msg(master_dflow)); > > + > > + if (master_dflow->en_split) > > + err = komeda_build_layer_split_data_flow(master, > > + kplane_st, kcrtc_st, master_dflow); > > + else > > + err = komeda_build_layer_data_flow(master, > > + kplane_st, kcrtc_st, master_dflow); > > + > > + if (err) > > + return err; > > + } > > + > > + if (slave_dflow) { > > + DRM_DEBUG_ATOMIC("SBS Slave-%s assigned: %s\n", > > + slave->base.name, komeda_data_flow_msg(slave_dflow)); > > + > > + if (slave_dflow->en_split) > > + err = komeda_build_layer_split_data_flow(slave, > > + kplane_st, kcrtc_st, slave_dflow); > > + else > > + err = komeda_build_layer_data_flow(slave, > > + kplane_st, kcrtc_st, slave_dflow); > > + if (err) > > + return err; > > + } > > + > > + return 0; > > +} > > + > > /* writeback data path: compiz -> scaler -> wb_layer -> memory */ > > int komeda_build_wb_data_flow(struct komeda_layer *wb_layer, > > struct drm_connector_state *conn_st, > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c > > index 98e915e325dd..2644f0727570 100644 > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c > > @@ -77,6 +77,7 @@ komeda_plane_atomic_check(struct drm_plane *plane, > > struct komeda_plane_state *kplane_st = to_kplane_st(state); > > struct komeda_layer *layer = kplane->layer; > > struct drm_crtc_state *crtc_st; > > + struct komeda_crtc *kcrtc; > > struct komeda_crtc_state *kcrtc_st; > > struct komeda_data_flow_cfg dflow; > > int err; > > @@ -94,13 +95,17 @@ komeda_plane_atomic_check(struct drm_plane *plane, > > if (!crtc_st->active) > > return 0; > > > > + kcrtc = to_kcrtc(crtc_st->crtc); > > kcrtc_st = to_kcrtc_st(crtc_st); > > > > err = komeda_plane_init_data_flow(state, kcrtc_st, &dflow); > > if (err) > > return err; > > > > - if (dflow.en_split) > > + if (kcrtc->side_by_side) > > + err = komeda_build_layer_sbs_data_flow(layer, > > + kplane_st, kcrtc_st, &dflow); > > + else if (dflow.en_split) > > err = komeda_build_layer_split_data_flow(layer, > > kplane_st, kcrtc_st, &dflow); > > else > > > > > -- > Mihail > > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel