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. > + } > + } 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