Re: [PATCH RFC v4 6/7] drm/msm/dpu: Allow NULL FBs in atomic commit
On Fri, 30 Jun 2023 03:52:37 +0300 Dmitry Baryshkov wrote: > On 30/06/2023 03:25, Jessica Zhang wrote: > > Since solid fill planes allow for a NULL framebuffer in a valid commit, > > add NULL framebuffer checks to atomic commit calls within DPU. > > > > Signed-off-by: Jessica Zhang > > --- > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 ++- > > drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 45 > > +++ > > 2 files changed, 36 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c > > index 1edf2b6b0a26..d1b37d2cc202 100644 > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c > > @@ -451,6 +451,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc > > *crtc, > > struct drm_plane_state *state; > > struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); > > struct dpu_plane_state *pstate = NULL; > > + const struct msm_format *fmt; > > struct dpu_format *format; > > struct dpu_hw_ctl *ctl = mixer->lm_ctl; > > > > @@ -470,7 +471,13 @@ static void _dpu_crtc_blend_setup_mixer(struct > > drm_crtc *crtc, > > pstate = to_dpu_plane_state(state); > > fb = state->fb; > > > > - format = to_dpu_format(msm_framebuffer_format(pstate->base.fb)); > > + if (state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb) > > + fmt = msm_framebuffer_format(pstate->base.fb); > > + else > > + fmt = dpu_get_msm_format(&_dpu_crtc_get_kms(crtc)->base, > > + DRM_FORMAT_RGBA, 0); > > The DRM_FORMAT_RGBA should be defined somewhere in patch 1 as format > for the solid_fill, then that define can be used in this patch. Isn't this just a driver-specific decision to convert a RGB323232 solid_fill to be presented as a RGBA? Though, below there is ABGR used for something... inconsistent? Thanks, pq > > > + > > + format = to_dpu_format(fmt); > > > > if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable) > > bg_alpha_enable = true; > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > > index 5f0984ce62b1..4476722f03bb 100644 > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > > @@ -837,8 +837,10 @@ static int dpu_plane_atomic_check(struct drm_plane > > *plane, > > > > pipe_cfg->dst_rect = new_plane_state->dst; > > > > - fb_rect.x2 = new_plane_state->fb->width; > > - fb_rect.y2 = new_plane_state->fb->height; > > + if (new_plane_state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && > > new_plane_state->fb) { > > + fb_rect.x2 = new_plane_state->fb->width; > > + fb_rect.y2 = new_plane_state->fb->height; > > + } > > > > /* Ensure fb size is supported */ > > if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH || > > @@ -848,10 +850,13 @@ static int dpu_plane_atomic_check(struct drm_plane > > *plane, > > return -E2BIG; > > } > > > > - fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb)); > > - > > max_linewidth = pdpu->catalog->caps->max_linewidth; > > > > + if (drm_plane_solid_fill_enabled(new_plane_state)) > > + fmt = dpu_get_dpu_format(DRM_FORMAT_ABGR); > > + else > > + fmt = > > to_dpu_format(msm_framebuffer_format(new_plane_state->fb)); > > + > > if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) { > > /* > > * In parallel multirect case only the half of the usual width > > @@ -1082,21 +1087,32 @@ static void dpu_plane_sspp_atomic_update(struct > > drm_plane *plane) > > struct drm_crtc *crtc = state->crtc; > > struct drm_framebuffer *fb = state->fb; > > bool is_rt_pipe; > > - const struct dpu_format *fmt = > > - to_dpu_format(msm_framebuffer_format(fb)); > > + const struct dpu_format *fmt; > > struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; > > struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; > > struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); > > struct msm_gem_address_space *aspace = kms->base.aspace; > > struct dpu_hw_fmt_layout layout; > > bool layout_valid = false; > > - int ret; > > > > - ret = dpu_format_populate_layout(aspace, fb, &layout); > > - if (ret) > > - DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); > > - else > > - layout_valid = true; > > + if (state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb) { > > + int ret; > > + > > + fmt = to_dpu_format(msm_framebuffer_format(fb)); > > + > > + ret = dpu_format_populate_layout(aspace, fb, &layout); > > + if (ret) > > + DPU_ERROR_PLANE(pdpu, "fai
Re: [PATCH RFC v4 7/7] drm/msm/dpu: Use DRM solid_fill property
On Thu, 29 Jun 2023 17:25:06 -0700 Jessica Zhang wrote: > Drop DPU_PLANE_COLOR_FILL_FLAG and check the DRM solid_fill property to > determine if the plane is solid fill. In addition drop the DPU plane > color_fill field as we can now use drm_plane_state.solid_fill instead, > and pass in drm_plane_state.alpha to _dpu_plane_color_fill_pipe() to > allow userspace to configure the alpha value for the solid fill color. > > Signed-off-by: Jessica Zhang > --- > drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 21 +++-- > 1 file changed, 15 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > index 4476722f03bb..11d4fb771a1f 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > @@ -42,7 +42,6 @@ > #define SHARP_SMOOTH_THR_DEFAULT 8 > #define SHARP_NOISE_THR_DEFAULT 2 > > -#define DPU_PLANE_COLOR_FILL_FLAGBIT(31) > #define DPU_ZPOS_MAX 255 > > /* > @@ -82,7 +81,6 @@ struct dpu_plane { > > enum dpu_sspp pipe; > > - uint32_t color_fill; > bool is_error; > bool is_rt_pipe; > const struct dpu_mdss_cfg *catalog; > @@ -606,6 +604,17 @@ static void _dpu_plane_color_fill_pipe(struct > dpu_plane_state *pstate, > _dpu_plane_setup_scaler(pipe, fmt, true, &pipe_cfg, pstate->rotation); > } > > +static uint32_t _dpu_plane_get_fill_color(struct drm_solid_fill solid_fill) > +{ > + uint32_t ret = 0; > + > + ret |= ((uint8_t) solid_fill.b) << 16; > + ret |= ((uint8_t) solid_fill.g) << 8; > + ret |= ((uint8_t) solid_fill.r); solid_fill.r, g and b are uint32_t, yes? What's the value encoding in the UAPI? That doc was missing. I wouldn't expect the UAPI to use 32-bit variables if it was essentially 8-bit, so this conversion looks wrong. Nominal color value 1.0 in u8 is 0xff. The same in u32 is probably 0x? So a simple cast to u8 won't work. You'd want to take the upper 8 bits instead. Thanks, pq > + > + return ret; > +} > + > /** > * _dpu_plane_color_fill - enables color fill on plane > * @pdpu: Pointer to DPU plane object > @@ -977,9 +986,9 @@ void dpu_plane_flush(struct drm_plane *plane) > if (pdpu->is_error) > /* force white frame with 100% alpha pipe output on error */ > _dpu_plane_color_fill(pdpu, 0xFF, 0xFF); > - else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) > - /* force 100% alpha */ > - _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF); > + else if (drm_plane_solid_fill_enabled(plane->state)) > + _dpu_plane_color_fill(pdpu, > _dpu_plane_get_fill_color(plane->state->solid_fill), > + plane->state->alpha); > else { > dpu_plane_flush_csc(pdpu, &pstate->pipe); > dpu_plane_flush_csc(pdpu, &pstate->r_pipe); > @@ -1024,7 +1033,7 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane > *plane, > } > > /* override for color fill */ > - if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) { > + if (drm_plane_solid_fill_enabled(plane->state)) { > _dpu_plane_set_qos_ctrl(plane, pipe, false); > > /* skip remaining processing on color fill */ > pgpMQc1w_Z33P.pgp Description: OpenPGP digital signature
Re: [PATCH RFC v4 1/7] drm: Introduce solid fill DRM plane property
On Thu, 29 Jun 2023 17:25:00 -0700 Jessica Zhang wrote: > Document and add support for solid_fill property to drm_plane. In > addition, add support for setting and getting the values for solid_fill. > > To enable solid fill planes, userspace must assign a property blob to > the "solid_fill" plane property containing the following information: > > struct drm_solid_fill_info { > u8 version; > u32 r, g, b; > }; > > Signed-off-by: Jessica Zhang Hi Jessica, I've left some general UAPI related comments here. > --- > drivers/gpu/drm/drm_atomic_state_helper.c | 9 + > drivers/gpu/drm/drm_atomic_uapi.c | 55 > +++ > drivers/gpu/drm/drm_blend.c | 33 +++ > include/drm/drm_blend.h | 1 + > include/drm/drm_plane.h | 43 > 5 files changed, 141 insertions(+) > > diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c > b/drivers/gpu/drm/drm_atomic_state_helper.c > index 784e63d70a42..fe14be2bd2b2 100644 > --- a/drivers/gpu/drm/drm_atomic_state_helper.c > +++ b/drivers/gpu/drm/drm_atomic_state_helper.c > @@ -253,6 +253,11 @@ void __drm_atomic_helper_plane_state_reset(struct > drm_plane_state *plane_state, > plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; > plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; > > + if (plane_state->solid_fill_blob) { > + drm_property_blob_put(plane_state->solid_fill_blob); > + plane_state->solid_fill_blob = NULL; > + } > + > if (plane->color_encoding_property) { > if (!drm_object_property_get_default_value(&plane->base, > > plane->color_encoding_property, > @@ -335,6 +340,9 @@ void __drm_atomic_helper_plane_duplicate_state(struct > drm_plane *plane, > if (state->fb) > drm_framebuffer_get(state->fb); > > + if (state->solid_fill_blob) > + drm_property_blob_get(state->solid_fill_blob); > + > state->fence = NULL; > state->commit = NULL; > state->fb_damage_clips = NULL; > @@ -384,6 +392,7 @@ void __drm_atomic_helper_plane_destroy_state(struct > drm_plane_state *state) > drm_crtc_commit_put(state->commit); > > drm_property_blob_put(state->fb_damage_clips); > + drm_property_blob_put(state->solid_fill_blob); > } > EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); > > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c > b/drivers/gpu/drm/drm_atomic_uapi.c > index d867e7f9f2cd..a28b4ee79444 100644 > --- a/drivers/gpu/drm/drm_atomic_uapi.c > +++ b/drivers/gpu/drm/drm_atomic_uapi.c > @@ -316,6 +316,51 @@ drm_atomic_set_crtc_for_connector(struct > drm_connector_state *conn_state, > } > EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector); > > +static int drm_atomic_set_solid_fill_prop(struct drm_plane_state *state, > + struct drm_property_blob *blob) > +{ > + int ret = 0; > + int blob_version; > + > + if (blob == state->solid_fill_blob) > + return 0; > + > + drm_property_blob_put(state->solid_fill_blob); > + state->solid_fill_blob = NULL; Is it ok to destroy old state before it is guaranteed that the new state is accepted? > + > + memset(&state->solid_fill, 0, sizeof(state->solid_fill)); > + > + if (blob) { > + struct drm_solid_fill_info *user_info = (struct > drm_solid_fill_info *)blob->data; > + > + if (blob->length != sizeof(struct drm_solid_fill_info)) { > + drm_dbg_atomic(state->plane->dev, > +"[PLANE:%d:%s] bad solid fill blob > length: %zu\n", > +state->plane->base.id, > state->plane->name, > +blob->length); > + return -EINVAL; > + } > + > + blob_version = user_info->version; > + > + /* Add more versions if necessary */ > + if (blob_version == 1) { > + state->solid_fill.r = user_info->r; > + state->solid_fill.g = user_info->g; > + state->solid_fill.b = user_info->b; > + } else { > + drm_dbg_atomic(state->plane->dev, > +"[PLANE:%d:%s] failed to set solid fill > (ret=%d)\n", > +state->plane->base.id, > state->plane->name, > +ret); > + return -EINVAL; Btw. how does the atomic check machinery work here? I expect that a TEST_ONLY atomic commit will do all the above checks and return failure if anything is not right. Right? > + } > + state->solid_fill_blob = drm_property_blob_get(blob); > + } > + > + return ret; > +} > + > static void set_out_fence_for_crtc(struct drm_atomic_state *state, >
Re: [PATCH RFC v4 2/7] drm: Introduce pixel_source DRM plane property
On Fri, 30 Jun 2023 03:42:28 +0300 Dmitry Baryshkov wrote: > On 30/06/2023 03:25, Jessica Zhang wrote: > > Add support for pixel_source property to drm_plane and related > > documentation. > > > > This enum property will allow user to specify a pixel source for the > > plane. Possible pixel sources will be defined in the > > drm_plane_pixel_source enum. > > > > The current possible pixel sources are DRM_PLANE_PIXEL_SOURCE_FB and > > DRM_PLANE_PIXEL_SOURCE_COLOR. The default value is *_SOURCE_FB. > > I think, this should come before the solid fill property addition. First > you tell that there is a possibility to define other pixel sources, then > additional sources are defined. Hi, that would be logical indeed. > > > > Signed-off-by: Jessica Zhang > > --- > > drivers/gpu/drm/drm_atomic_state_helper.c | 1 + > > drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ > > drivers/gpu/drm/drm_blend.c | 81 > > +++ > > include/drm/drm_blend.h | 2 + > > include/drm/drm_plane.h | 21 > > 5 files changed, 109 insertions(+) > > > > diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c > > b/drivers/gpu/drm/drm_atomic_state_helper.c > > index fe14be2bd2b2..86fb876efbe6 100644 > > --- a/drivers/gpu/drm/drm_atomic_state_helper.c > > +++ b/drivers/gpu/drm/drm_atomic_state_helper.c > > @@ -252,6 +252,7 @@ void __drm_atomic_helper_plane_state_reset(struct > > drm_plane_state *plane_state, > > > > plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; > > plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; > > + plane_state->pixel_source = DRM_PLANE_PIXEL_SOURCE_FB; > > > > if (plane_state->solid_fill_blob) { > > drm_property_blob_put(plane_state->solid_fill_blob); > > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c > > b/drivers/gpu/drm/drm_atomic_uapi.c > > index a28b4ee79444..6e59c21af66b 100644 > > --- a/drivers/gpu/drm/drm_atomic_uapi.c > > +++ b/drivers/gpu/drm/drm_atomic_uapi.c > > @@ -596,6 +596,8 @@ static int drm_atomic_plane_set_property(struct > > drm_plane *plane, > > drm_property_blob_put(solid_fill); > > > > return ret; > > + } else if (property == plane->pixel_source_property) { > > + state->pixel_source = val; > > } else if (property == plane->alpha_property) { > > state->alpha = val; > > } else if (property == plane->blend_mode_property) { > > I think, it was pointed out in the discussion that drm_mode_setplane() > (a pre-atomic IOCTL to turn the plane on and off) should also reset > pixel_source to FB. > > > @@ -671,6 +673,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, > > } else if (property == plane->solid_fill_property) { > > *val = state->solid_fill_blob ? > > state->solid_fill_blob->base.id : 0; > > + } else if (property == plane->pixel_source_property) { > > + *val = state->pixel_source; > > } else if (property == plane->alpha_property) { > > *val = state->alpha; > > } else if (property == plane->blend_mode_property) { > > diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c > > index 38c3c5d6453a..8c100a957ee2 100644 > > --- a/drivers/gpu/drm/drm_blend.c > > +++ b/drivers/gpu/drm/drm_blend.c > > @@ -189,6 +189,18 @@ > >*solid_fill is set up with > > drm_plane_create_solid_fill_property(). It > >*contains pixel data that drivers can use to fill a plane. > >* > > + * pixel_source: > > + * pixel_source is set up with drm_plane_create_pixel_source_property(). > > + * It is used to toggle the source of pixel data for the plane. Other sources than the selected one are ignored? > > + * > > + * Possible values: Wouldn't hurt to explicitly mention here that this is an enum. > > + * > > + * "FB": > > + * Framebuffer source > > + * > > + * "COLOR": > > + * solid_fill source I think these two should be more explicit. Framebuffer source is the usual source from the property "FB_ID". Solid fill source comes from the property "solid_fill". Why "COLOR" and not, say, "SOLID_FILL"? > > + * > >* Note that all the property extensions described here apply either to > > the > >* plane or the CRTC (e.g. for the background color, which currently is > > not > >* exposed and assumed to be black). > > @@ -648,3 +660,72 @@ int drm_plane_create_solid_fill_property(struct > > drm_plane *plane) > > return 0; > > } > > EXPORT_SYMBOL(drm_plane_create_solid_fill_property); > > + > > +/** > > + * drm_plane_create_pixel_source_property - create a new pixel source > > property > > + * @plane: drm plane > > + * @supported_sources: bitmask of supported pixel_sources for the driver > > (NOT > > + * including DRM_PLANE_PIXEL_SOURCE_FB, as it will be > > supported > > + * by default). > > I'd say this is too strong. I'd
Re: [PATCH RFC v4 1/7] drm: Introduce solid fill DRM plane property
On 30/06/2023 03:25, Jessica Zhang wrote: Document and add support for solid_fill property to drm_plane. In addition, add support for setting and getting the values for solid_fill. To enable solid fill planes, userspace must assign a property blob to the "solid_fill" plane property containing the following information: struct drm_solid_fill_info { u8 version; u32 r, g, b; }; Signed-off-by: Jessica Zhang --- drivers/gpu/drm/drm_atomic_state_helper.c | 9 + drivers/gpu/drm/drm_atomic_uapi.c | 55 +++ drivers/gpu/drm/drm_blend.c | 33 +++ include/drm/drm_blend.h | 1 + include/drm/drm_plane.h | 43 5 files changed, 141 insertions(+) Also, I think the point which we missed up to now. Could you please add both new properties to dri/N/state debugfs? -- With best wishes Dmitry
Re: [PATCH RFC v4 2/7] drm: Introduce pixel_source DRM plane property
On Fri, Jun 30, 2023 at 2:26 AM Jessica Zhang wrote: > > Add support for pixel_source property to drm_plane and related > documentation. > > This enum property will allow user to specify a pixel source for the > plane. Possible pixel sources will be defined in the > drm_plane_pixel_source enum. > > The current possible pixel sources are DRM_PLANE_PIXEL_SOURCE_FB and > DRM_PLANE_PIXEL_SOURCE_COLOR. The default value is *_SOURCE_FB. > > Signed-off-by: Jessica Zhang > --- > drivers/gpu/drm/drm_atomic_state_helper.c | 1 + > drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ > drivers/gpu/drm/drm_blend.c | 81 > +++ > include/drm/drm_blend.h | 2 + > include/drm/drm_plane.h | 21 > 5 files changed, 109 insertions(+) > > diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c > b/drivers/gpu/drm/drm_atomic_state_helper.c > index fe14be2bd2b2..86fb876efbe6 100644 > --- a/drivers/gpu/drm/drm_atomic_state_helper.c > +++ b/drivers/gpu/drm/drm_atomic_state_helper.c > @@ -252,6 +252,7 @@ void __drm_atomic_helper_plane_state_reset(struct > drm_plane_state *plane_state, > > plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; > plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; > + plane_state->pixel_source = DRM_PLANE_PIXEL_SOURCE_FB; > > if (plane_state->solid_fill_blob) { > drm_property_blob_put(plane_state->solid_fill_blob); > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c > b/drivers/gpu/drm/drm_atomic_uapi.c > index a28b4ee79444..6e59c21af66b 100644 > --- a/drivers/gpu/drm/drm_atomic_uapi.c > +++ b/drivers/gpu/drm/drm_atomic_uapi.c > @@ -596,6 +596,8 @@ static int drm_atomic_plane_set_property(struct drm_plane > *plane, > drm_property_blob_put(solid_fill); > > return ret; > + } else if (property == plane->pixel_source_property) { > + state->pixel_source = val; > } else if (property == plane->alpha_property) { > state->alpha = val; > } else if (property == plane->blend_mode_property) { > @@ -671,6 +673,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, > } else if (property == plane->solid_fill_property) { > *val = state->solid_fill_blob ? > state->solid_fill_blob->base.id : 0; > + } else if (property == plane->pixel_source_property) { > + *val = state->pixel_source; > } else if (property == plane->alpha_property) { > *val = state->alpha; > } else if (property == plane->blend_mode_property) { > diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c > index 38c3c5d6453a..8c100a957ee2 100644 > --- a/drivers/gpu/drm/drm_blend.c > +++ b/drivers/gpu/drm/drm_blend.c > @@ -189,6 +189,18 @@ > * solid_fill is set up with drm_plane_create_solid_fill_property(). It > * contains pixel data that drivers can use to fill a plane. > * > + * pixel_source: > + * pixel_source is set up with drm_plane_create_pixel_source_property(). > + * It is used to toggle the source of pixel data for the plane. > + * > + * Possible values: > + * > + * "FB": > + * Framebuffer source > + * > + * "COLOR": > + * solid_fill source > + * > * Note that all the property extensions described here apply either to the > * plane or the CRTC (e.g. for the background color, which currently is not > * exposed and assumed to be black). > @@ -648,3 +660,72 @@ int drm_plane_create_solid_fill_property(struct > drm_plane *plane) > return 0; > } > EXPORT_SYMBOL(drm_plane_create_solid_fill_property); > + > +/** > + * drm_plane_create_pixel_source_property - create a new pixel source > property > + * @plane: drm plane > + * @supported_sources: bitmask of supported pixel_sources for the driver (NOT > + * including DRM_PLANE_PIXEL_SOURCE_FB, as it will be > supported > + * by default). > + * > + * This creates a new property describing the current source of pixel data > for the > + * plane. > + * > + * The property is exposed to userspace as an enumeration property called > + * "pixel_source" and has the following enumeration values: > + * > + * "FB": > + * Framebuffer pixel source > + * > + * "COLOR": > + * Solid fill color pixel source Can we add a "NONE" value? I know it has been discussed earlier if we *need* this and I don't think we do. I just think it would be better API design to disable planes this way than having to know that a framebuffer pixel source with a NULL framebuffer disables the plane. Obviously also keep the old behavior for backwards compatibility. > + * > + * Returns: > + * Zero on success, negative errno on failure. > + */ > +int drm_plane_create_pixel_source_property(struct drm_plane *plane, > + unsigned int supported_sources) > +{ > +
Re: [PATCH RFC v4 1/7] drm: Introduce solid fill DRM plane property
On 6/30/2023 3:33 AM, Dmitry Baryshkov wrote: On 30/06/2023 03:25, Jessica Zhang wrote: Document and add support for solid_fill property to drm_plane. In addition, add support for setting and getting the values for solid_fill. To enable solid fill planes, userspace must assign a property blob to the "solid_fill" plane property containing the following information: struct drm_solid_fill_info { u8 version; u32 r, g, b; }; Signed-off-by: Jessica Zhang --- drivers/gpu/drm/drm_atomic_state_helper.c | 9 + drivers/gpu/drm/drm_atomic_uapi.c | 55 +++ drivers/gpu/drm/drm_blend.c | 33 +++ include/drm/drm_blend.h | 1 + include/drm/drm_plane.h | 43 5 files changed, 141 insertions(+) Also, I think the point which we missed up to now. Could you please add both new properties to dri/N/state debugfs? Hi Dmitry, Good catch -- acked. Thanks, Jessica Zhang -- With best wishes Dmitry
Re: [PATCH RFC v4 3/7] drm/atomic: Move framebuffer checks to helper
On 6/29/2023 5:43 PM, Dmitry Baryshkov wrote: On 30/06/2023 03:25, Jessica Zhang wrote: Currently framebuffer checks happen directly in drm_atomic_plane_check(). Move these checks into their own helper method. Signed-off-by: Jessica Zhang --- drivers/gpu/drm/drm_atomic.c | 130 --- 1 file changed, 74 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index b4c6ffc438da..404b984d2d9f 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -580,6 +580,76 @@ plane_switching_crtc(const struct drm_plane_state *old_plane_state, return true; } +static int drm_atomic_check_fb(const struct drm_plane_state *state) +{ + struct drm_plane *plane = state->plane; + const struct drm_framebuffer *fb = state->fb; + struct drm_mode_rect *clips; + + uint32_t num_clips; + unsigned int fb_width, fb_height; + int ret; + + /* Check whether this plane supports the fb pixel format. */ + ret = drm_plane_check_pixel_format(plane, fb->format->format, + fb->modifier); + + if (ret) { + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid pixel format %p4cc, modifier 0x%llx\n", + plane->base.id, plane->name, + &fb->format->format, fb->modifier); + return ret; + } + + fb_width = fb->width << 16; + fb_height = fb->height << 16; + + /* Make sure source coordinates are inside the fb. */ + if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid source coordinates " + "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n", + plane->base.id, plane->name, + state->src_w >> 16, + ((state->src_w & 0x) * 15625) >> 10, + state->src_h >> 16, + ((state->src_h & 0x) * 15625) >> 10, + state->src_x >> 16, + ((state->src_x & 0x) * 15625) >> 10, + state->src_y >> 16, + ((state->src_y & 0x) * 15625) >> 10, + fb->width, fb->height); + return -ENOSPC; + } + + clips = __drm_plane_get_damage_clips(state); + num_clips = drm_plane_get_damage_clips_count(state); + + /* Make sure damage clips are valid and inside the fb. */ + while (num_clips > 0) { + if (clips->x1 >= clips->x2 || + clips->y1 >= clips->y2 || + clips->x1 < 0 || + clips->y1 < 0 || + clips->x2 > fb_width || + clips->y2 > fb_height) { + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid damage clip %d %d %d %d\n", + plane->base.id, plane->name, clips->x1, + clips->y1, clips->x2, clips->y2); + return -EINVAL; + } + clips++; + num_clips--; + } + + return 0; +} + /** * drm_atomic_plane_check - check plane state * @old_plane_state: old plane state to check @@ -596,9 +666,6 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, struct drm_plane *plane = new_plane_state->plane; struct drm_crtc *crtc = new_plane_state->crtc; const struct drm_framebuffer *fb = new_plane_state->fb; - unsigned int fb_width, fb_height; - struct drm_mode_rect *clips; - uint32_t num_clips; int ret; /* either *both* CRTC and FB must be set, or neither */ @@ -625,17 +692,6 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, return -EINVAL; } - /* Check whether this plane supports the fb pixel format. */ - ret = drm_plane_check_pixel_format(plane, fb->format->format, - fb->modifier); - if (ret) { - drm_dbg_atomic(plane->dev, - "[PLANE:%d:%s] invalid pixel format %p4cc, modifier 0x%llx\n", - plane->base.id, plane->name, - &fb->format->format, fb->modifier); - return ret; - } - /* Give drivers some help against integer overflows */ if (new_plane_state->crtc_w > INT_MAX || new_plane_state->crtc_x > INT_MAX - (int32_t) new_plane_state->crtc_w || @@ -649,49 +705,11 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, return -ERANGE; } - fb_width = fb->width << 16; - fb_height = fb->height << 16; - /* Make sure source coordinates are inside the fb. */ - if (new_plane_state->src_w > fb_width || - new_plane_state->src_x > fb_width - new_plane_state->src_w || - new_plane_state->src_h > fb_height || - new_plane_state->src_y > fb_height - new_plane_state->
Re: [PATCH RFC v4 2/7] drm: Introduce pixel_source DRM plane property
On 6/30/2023 7:43 AM, Sebastian Wick wrote: On Fri, Jun 30, 2023 at 2:26 AM Jessica Zhang wrote: Add support for pixel_source property to drm_plane and related documentation. This enum property will allow user to specify a pixel source for the plane. Possible pixel sources will be defined in the drm_plane_pixel_source enum. The current possible pixel sources are DRM_PLANE_PIXEL_SOURCE_FB and DRM_PLANE_PIXEL_SOURCE_COLOR. The default value is *_SOURCE_FB. Signed-off-by: Jessica Zhang --- drivers/gpu/drm/drm_atomic_state_helper.c | 1 + drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ drivers/gpu/drm/drm_blend.c | 81 +++ include/drm/drm_blend.h | 2 + include/drm/drm_plane.h | 21 5 files changed, 109 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index fe14be2bd2b2..86fb876efbe6 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -252,6 +252,7 @@ void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state, plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; + plane_state->pixel_source = DRM_PLANE_PIXEL_SOURCE_FB; if (plane_state->solid_fill_blob) { drm_property_blob_put(plane_state->solid_fill_blob); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index a28b4ee79444..6e59c21af66b 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -596,6 +596,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, drm_property_blob_put(solid_fill); return ret; + } else if (property == plane->pixel_source_property) { + state->pixel_source = val; } else if (property == plane->alpha_property) { state->alpha = val; } else if (property == plane->blend_mode_property) { @@ -671,6 +673,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, } else if (property == plane->solid_fill_property) { *val = state->solid_fill_blob ? state->solid_fill_blob->base.id : 0; + } else if (property == plane->pixel_source_property) { + *val = state->pixel_source; } else if (property == plane->alpha_property) { *val = state->alpha; } else if (property == plane->blend_mode_property) { diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 38c3c5d6453a..8c100a957ee2 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -189,6 +189,18 @@ * solid_fill is set up with drm_plane_create_solid_fill_property(). It * contains pixel data that drivers can use to fill a plane. * + * pixel_source: + * pixel_source is set up with drm_plane_create_pixel_source_property(). + * It is used to toggle the source of pixel data for the plane. + * + * Possible values: + * + * "FB": + * Framebuffer source + * + * "COLOR": + * solid_fill source + * * Note that all the property extensions described here apply either to the * plane or the CRTC (e.g. for the background color, which currently is not * exposed and assumed to be black). @@ -648,3 +660,72 @@ int drm_plane_create_solid_fill_property(struct drm_plane *plane) return 0; } EXPORT_SYMBOL(drm_plane_create_solid_fill_property); + +/** + * drm_plane_create_pixel_source_property - create a new pixel source property + * @plane: drm plane + * @supported_sources: bitmask of supported pixel_sources for the driver (NOT + * including DRM_PLANE_PIXEL_SOURCE_FB, as it will be supported + * by default). + * + * This creates a new property describing the current source of pixel data for the + * plane. + * + * The property is exposed to userspace as an enumeration property called + * "pixel_source" and has the following enumeration values: + * + * "FB": + * Framebuffer pixel source + * + * "COLOR": + * Solid fill color pixel source Can we add a "NONE" value? I know it has been discussed earlier if we *need* this and I don't think we do. I just think it would be better API design to disable planes this way than having to know that a framebuffer pixel source with a NULL framebuffer disables the plane. Obviously also keep the old behavior for backwards compatibility. Hi Sebastian, Sounds good. So if pixel_source == NONE disables the planes, would that mean cases where pixel_source == COLOR && solid_fill_blob == NULL, the atomic commit should throw an error? Thanks, Jessica Zhang + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_plane_create_pixel_source_property(struct drm_plane *plane,
Re: [PATCH RFC v4 4/7] drm/atomic: Loosen FB atomic checks
On 6/29/2023 5:48 PM, Dmitry Baryshkov wrote: On 30/06/2023 03:25, Jessica Zhang wrote: Loosen the requirements for atomic and legacy commit so that, in cases where solid fill planes is enabled but no FB is set, the commit can still go through. This includes adding framebuffer NULL checks in other areas to account for FB being NULL when solid fill is enabled. Signed-off-by: Jessica Zhang --- drivers/gpu/drm/drm_atomic.c | 14 +++--- drivers/gpu/drm/drm_atomic_helper.c | 34 -- drivers/gpu/drm/drm_plane.c | 8 include/drm/drm_atomic_helper.h | 4 ++-- include/drm/drm_plane.h | 28 5 files changed, 61 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 404b984d2d9f..ec9681c25366 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -668,14 +668,14 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, const struct drm_framebuffer *fb = new_plane_state->fb; int ret; - /* either *both* CRTC and FB must be set, or neither */ - if (crtc && !fb) { - drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] CRTC set but no FB\n", + /* either *both* CRTC and pixel source must be set, or neither */ + if (crtc && !drm_plane_has_visible_data(new_plane_state)) { + drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] CRTC set but no visible data\n", plane->base.id, plane->name); return -EINVAL; - } else if (fb && !crtc) { - drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] FB set but no CRTC\n", - plane->base.id, plane->name); + } else if (drm_plane_has_visible_data(new_plane_state) && !crtc) { + drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] Source %d has visible data but no CRTC\n", + plane->base.id, plane->name, new_plane_state->pixel_source); return -EINVAL; } @@ -706,7 +706,7 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, } - if (fb) { + if (new_plane_state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb) { ret = drm_atomic_check_fb(new_plane_state); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 41b8066f61ff..d05ec9ef2b3e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -864,7 +864,7 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, *src = drm_plane_state_src(plane_state); *dst = drm_plane_state_dest(plane_state); - if (!fb) { + if (!drm_plane_has_visible_data(plane_state)) { plane_state->visible = false; return 0; } @@ -881,25 +881,31 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, return -EINVAL; } - drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation); + if (plane_state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb) { + drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation); - /* Check scaling */ - hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); - vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); - if (hscale < 0 || vscale < 0) { - drm_dbg_kms(plane_state->plane->dev, - "Invalid scaling of plane\n"); - drm_rect_debug_print("src: ", &plane_state->src, true); - drm_rect_debug_print("dst: ", &plane_state->dst, false); - return -ERANGE; + /* Check scaling */ + hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); + vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); + + if (hscale < 0 || vscale < 0) { + drm_dbg_kms(plane_state->plane->dev, + "Invalid scaling of plane\n"); + drm_rect_debug_print("src: ", &plane_state->src, true); + drm_rect_debug_print("dst: ", &plane_state->dst, false); + return -ERANGE; + } } if (crtc_state->enable) drm_mode_get_hv_timing(&crtc_state->mode, &clip.x2, &clip.y2); - plane_state->visible = drm_rect_clip_scaled(src, dst, &clip); - - drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); + if (plane_state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb) { + plane_state->visible = drm_rect_clip_scaled(src, dst, &clip); + drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); + } else if (drm_plane_solid_fill_enabled(plane_state)) { + plane_state->visible = true; + } if (!plane_state->visible) /* diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 24e7998d1731..5f19a27ba182 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@
Re: [PATCH RFC v4 5/7] drm/msm/dpu: Add solid fill and pixel source properties
On 6/29/2023 5:49 PM, Dmitry Baryshkov wrote: On 30/06/2023 03:25, Jessica Zhang wrote: Add solid_fill and pixel_source properties to DPU plane Signed-off-by: Jessica Zhang --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 ++ 1 file changed, 2 insertions(+) This should be the last commit. Hi Dmitry, Acked, will move this to the end. Thanks, Jessica Zhang Otherwise: Reviewed-by: Dmitry Baryshkov diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index c2aaaded07ed..5f0984ce62b1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1429,6 +1429,8 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, DPU_ERROR("failed to install zpos property, rc = %d\n", ret); drm_plane_create_alpha_property(plane); + drm_plane_create_solid_fill_property(plane); + drm_plane_create_pixel_source_property(plane, BIT(DRM_PLANE_PIXEL_SOURCE_COLOR)); drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) | -- With best wishes Dmitry
Re: [PATCH RFC v4 6/7] drm/msm/dpu: Allow NULL FBs in atomic commit
On 6/30/2023 1:21 AM, Pekka Paalanen wrote: On Fri, 30 Jun 2023 03:52:37 +0300 Dmitry Baryshkov wrote: On 30/06/2023 03:25, Jessica Zhang wrote: Since solid fill planes allow for a NULL framebuffer in a valid commit, add NULL framebuffer checks to atomic commit calls within DPU. Signed-off-by: Jessica Zhang --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 45 +++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 1edf2b6b0a26..d1b37d2cc202 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -451,6 +451,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_plane_state *state; struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); struct dpu_plane_state *pstate = NULL; + const struct msm_format *fmt; struct dpu_format *format; struct dpu_hw_ctl *ctl = mixer->lm_ctl; @@ -470,7 +471,13 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, pstate = to_dpu_plane_state(state); fb = state->fb; - format = to_dpu_format(msm_framebuffer_format(pstate->base.fb)); + if (state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb) + fmt = msm_framebuffer_format(pstate->base.fb); + else + fmt = dpu_get_msm_format(&_dpu_crtc_get_kms(crtc)->base, + DRM_FORMAT_RGBA, 0); The DRM_FORMAT_RGBA should be defined somewhere in patch 1 as format for the solid_fill, then that define can be used in this patch. Isn't this just a driver-specific decision to convert a RGB323232 solid_fill to be presented as a RGBA? Hi Dmitry and Pekka, Yes, the ABGR format is specific to msm/dpu. In earlier revisions of the series, we had come to an agreement that the solid fill property should take RGB323232 to match the similar Wayland single pixel buffer protocol [1]. [1] https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/104 Though, below there is ABGR used for something... inconsistent? Typo on my part. The format should be consistently ABGR. Thanks, Jessica Zhang Thanks, pq + + format = to_dpu_format(fmt); if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable) bg_alpha_enable = true; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 5f0984ce62b1..4476722f03bb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -837,8 +837,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, pipe_cfg->dst_rect = new_plane_state->dst; - fb_rect.x2 = new_plane_state->fb->width; - fb_rect.y2 = new_plane_state->fb->height; + if (new_plane_state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && new_plane_state->fb) { + fb_rect.x2 = new_plane_state->fb->width; + fb_rect.y2 = new_plane_state->fb->height; + } /* Ensure fb size is supported */ if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH || @@ -848,10 +850,13 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, return -E2BIG; } - fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb)); - max_linewidth = pdpu->catalog->caps->max_linewidth; + if (drm_plane_solid_fill_enabled(new_plane_state)) + fmt = dpu_get_dpu_format(DRM_FORMAT_ABGR); + else + fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb)); + if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) { /* * In parallel multirect case only the half of the usual width @@ -1082,21 +1087,32 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) struct drm_crtc *crtc = state->crtc; struct drm_framebuffer *fb = state->fb; bool is_rt_pipe; - const struct dpu_format *fmt = - to_dpu_format(msm_framebuffer_format(fb)); + const struct dpu_format *fmt; struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); struct msm_gem_address_space *aspace = kms->base.aspace; struct dpu_hw_fmt_layout layout; bool layout_valid = false; - int ret; - ret = dpu_format_populate_layout(aspace, fb, &layout); - if (ret) - DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); - else - layout_valid = true; + if (state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB
Re: [PATCH RFC v4 7/7] drm/msm/dpu: Use DRM solid_fill property
On 6/29/2023 5:59 PM, Dmitry Baryshkov wrote: On 30/06/2023 03:25, Jessica Zhang wrote: Drop DPU_PLANE_COLOR_FILL_FLAG and check the DRM solid_fill property to determine if the plane is solid fill. In addition drop the DPU plane color_fill field as we can now use drm_plane_state.solid_fill instead, and pass in drm_plane_state.alpha to _dpu_plane_color_fill_pipe() to allow userspace to configure the alpha value for the solid fill color. Signed-off-by: Jessica Zhang Reviewed-by: Dmitry Baryshkov Minor suggestion below. --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 4476722f03bb..11d4fb771a1f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -42,7 +42,6 @@ #define SHARP_SMOOTH_THR_DEFAULT 8 #define SHARP_NOISE_THR_DEFAULT 2 -#define DPU_PLANE_COLOR_FILL_FLAG BIT(31) #define DPU_ZPOS_MAX 255 /* @@ -82,7 +81,6 @@ struct dpu_plane { enum dpu_sspp pipe; - uint32_t color_fill; bool is_error; bool is_rt_pipe; const struct dpu_mdss_cfg *catalog; @@ -606,6 +604,17 @@ static void _dpu_plane_color_fill_pipe(struct dpu_plane_state *pstate, _dpu_plane_setup_scaler(pipe, fmt, true, &pipe_cfg, pstate->rotation); } +static uint32_t _dpu_plane_get_fill_color(struct drm_solid_fill solid_fill) Please consider accepting drm_plane_state instead and handling alpha here. Then _dpu_color_fill can accept rgba colour instead of separate RGB and alpha values. Hi Dmitry, Do you mean adding a patch to refactor _dpu_plane_color_fill() to accept an RGBA color? Since, currently, the `color` parameter gets truncated to a BGR888 value and OR'd with the `alpha` parameter [1]. Thanks, Jessica Zhang [1] https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c#L682 +{ + uint32_t ret = 0; + + ret |= ((uint8_t) solid_fill.b) << 16; + ret |= ((uint8_t) solid_fill.g) << 8; + ret |= ((uint8_t) solid_fill.r); + + return ret; +} + /** * _dpu_plane_color_fill - enables color fill on plane * @pdpu: Pointer to DPU plane object @@ -977,9 +986,9 @@ void dpu_plane_flush(struct drm_plane *plane) if (pdpu->is_error) /* force white frame with 100% alpha pipe output on error */ _dpu_plane_color_fill(pdpu, 0xFF, 0xFF); - else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) - /* force 100% alpha */ - _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF); + else if (drm_plane_solid_fill_enabled(plane->state)) + _dpu_plane_color_fill(pdpu, _dpu_plane_get_fill_color(plane->state->solid_fill), + plane->state->alpha); else { dpu_plane_flush_csc(pdpu, &pstate->pipe); dpu_plane_flush_csc(pdpu, &pstate->r_pipe); @@ -1024,7 +1033,7 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane, } /* override for color fill */ - if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) { + if (drm_plane_solid_fill_enabled(plane->state)) { _dpu_plane_set_qos_ctrl(plane, pipe, false); /* skip remaining processing on color fill */ -- With best wishes Dmitry
[PATCH v4 0/6] drm: Add support for atomic async page-flip
Hi, This work from me and Simon adds support for DRM_MODE_PAGE_FLIP_ASYNC through the atomic API. This feature is already available via the legacy API. The use case is to be able to present a new frame immediately (or as soon as possible), even if after missing a vblank. This might result in tearing, but it's useful when a high framerate is desired, such as for gaming. Differently from earlier versions, this one refuses to flip if any prop changes for async flips. The idea is that the fast path of immediate page flips doesn't play well with modeset changes, so only the fb_id can be changed. The exception is for mode_id changes, that might be referring to an identical mode (which would skip a modeset). This is done to make the async API more similar to the normal API. Thanks, André Changes from v3: - Add new patch to reject prop changes - Add a documentation clarifying the KMS atomic state set v3: https://lore.kernel.org/dri-devel/20220929184307.258331-1-cont...@emersion.fr/ - User-space patch: https://github.com/Plagman/gamescope/pull/595 - IGT tests: https://gitlab.freedesktop.org/andrealmeid/igt-gpu-tools/-/tree/atomic_async_page_flip André Almeida (2): drm: Refuse to async flip with atomic prop changes drm/doc: Define KMS atomic state set Simon Ser (4): drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP drm: introduce drm_mode_config.atomic_async_page_flip_not_supported amd/display: indicate support for atomic async page-flips on DC Documentation/gpu/drm-uapi.rst | 19 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 1 + drivers/gpu/drm/drm_atomic_helper.c | 5 ++ drivers/gpu/drm/drm_atomic_uapi.c| 80 ++-- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_ioctl.c | 5 ++ drivers/gpu/drm/drm_mode_object.c| 2 +- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/nouveau/nouveau_display.c| 1 + include/drm/drm_mode_config.h| 11 +++ include/uapi/drm/drm.h | 10 ++- include/uapi/drm/drm_mode.h | 9 +++ 12 files changed, 137 insertions(+), 9 deletions(-) -- 2.41.0
[PATCH v4 1/6] drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits
From: Simon Ser If the driver supports it, allow user-space to supply the DRM_MODE_PAGE_FLIP_ASYNC flag to request an async page-flip. Set drm_crtc_state.async_flip accordingly. Document that drivers will reject atomic commits if an async flip isn't possible. This allows user-space to fall back to something else. For instance, Xorg falls back to a blit. Another option is to wait as close to the next vblank as possible before performing the page-flip to reduce latency. Signed-off-by: Simon Ser Reviewed-by: Alex Deucher Co-developed-by: André Almeida Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/drm_atomic_uapi.c | 28 +--- include/uapi/drm/drm_mode.h | 9 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index d867e7f9f2cd..dfd4cf7169df 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1286,6 +1286,18 @@ static void complete_signaling(struct drm_device *dev, kfree(fence_state); } +static void +set_async_flip(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + crtc_state->async_flip = true; + } +} + int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1326,9 +1338,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, } if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) { - drm_dbg_atomic(dev, - "commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n"); - return -EINVAL; + if (!dev->mode_config.async_page_flip) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n"); + return -EINVAL; + } + if (dev->mode_config.atomic_async_page_flip_not_supported) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported with atomic\n"); + return -EINVAL; + } } /* can't test and expect an event at the same time. */ @@ -1426,6 +1445,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, if (ret) goto out; + if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) + set_async_flip(state); + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 46becedf5b2f..56342ba2c11a 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -949,6 +949,15 @@ struct hdr_output_metadata { * Request that the page-flip is performed as soon as possible, ie. with no * delay due to waiting for vblank. This may cause tearing to be visible on * the screen. + * + * When used with atomic uAPI, the driver will return an error if the hardware + * doesn't support performing an asynchronous page-flip for this update. + * User-space should handle this, e.g. by falling back to a regular page-flip. + * + * Note, some hardware might need to perform one last synchronous page-flip + * before being able to switch to asynchronous page-flips. As an exception, + * the driver will return success even though that first page-flip is not + * asynchronous. */ #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 -- 2.41.0
[PATCH v4 2/6] drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP
From: Simon Ser This new kernel capability indicates whether async page-flips are supported via the atomic uAPI. DRM clients can use it to check for support before feeding DRM_MODE_PAGE_FLIP_ASYNC to the kernel. Make it clear that DRM_CAP_ASYNC_PAGE_FLIP is for legacy uAPI only. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/drm_ioctl.c | 5 + include/uapi/drm/drm.h | 10 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7c9d66ee917d..8f756b99260d 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -302,6 +302,11 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_CRTC_IN_VBLANK_EVENT: req->value = 1; break; + case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP: + req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) && +dev->mode_config.async_page_flip && + !dev->mode_config.atomic_async_page_flip_not_supported; + break; default: return -EINVAL; } diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index a87ca2d4..54c558f81f3c 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -706,7 +706,8 @@ struct drm_gem_open { /** * DRM_CAP_ASYNC_PAGE_FLIP * - * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC. + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for legacy + * page-flips. */ #define DRM_CAP_ASYNC_PAGE_FLIP0x7 /** @@ -767,6 +768,13 @@ struct drm_gem_open { * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". */ #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 +/** + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP + * + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for atomic + * commits. + */ +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 /* DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- 2.41.0
[PATCH v4 3/6] drm: introduce drm_mode_config.atomic_async_page_flip_not_supported
From: Simon Ser This new field indicates whether the driver has the necessary logic to support async page-flips via the atomic uAPI. This is leveraged by the next commit to allow user-space to use this functionality. All atomic drivers setting drm_mode_config.async_page_flip are updated to also set drm_mode_config.atomic_async_page_flip_not_supported. We will gradually check and update these drivers to properly handle drm_crtc_state.async_flip in their atomic logic. The goal of this negative flag is the same as fb_modifiers_not_supported: we want to eventually get rid of all drivers missing atomic support for async flips. New drivers should not set this flag, instead they should support atomic async flips (if they support async flips at all). IOW, we don't want more drivers with async flip support for legacy but not atomic. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 1 + drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/nouveau/nouveau_display.c | 1 + include/drm/drm_mode_config.h | 11 +++ 5 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7acd73e5004f..258461826140 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3970,6 +3970,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ adev_to_drm(adev)->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.atomic_async_page_flip_not_supported = true; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 29603561d501..8afb22b1e730 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -639,6 +639,7 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev) dev->mode_config.max_height = dc->desc->max_height; dev->mode_config.funcs = &mode_config_funcs; dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0aae9a1eb3d5..a5c503ca9168 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8318,6 +8318,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915) mode_config->helper_private = &intel_mode_config_funcs; mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915); + mode_config->atomic_async_page_flip_not_supported = true; /* * Maximum framebuffer dimensions, chosen to match diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index ec3487fc..f497dcd9e22f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -709,6 +709,7 @@ nouveau_display_create(struct drm_device *dev) dev->mode_config.async_page_flip = false; else dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 973119a9176b..47b005671e6a 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -918,6 +918,17 @@ struct drm_mode_config { */ bool async_page_flip; + /** +* @atomic_async_page_flip_not_supported: +* +* If true, the driver does not support async page-flips with the +* atomic uAPI. This is only used by old drivers which haven't yet +* accomodated for &drm_crtc_state.async_flip in their atomic logic, +* even if they have &drm_mode_config.async_page_flip set to true. +* New drivers shall not set this flag. +*/ + bool atomic_async_page_flip_not_supported; + /** * @fb_modifiers_not_supported: * -- 2.41.0
[PATCH v4 4/6] amd/display: indicate support for atomic async page-flips on DC
From: Simon Ser amdgpu_dm_commit_planes() already sets the flip_immediate flag for async page-flips. This flag is used to set the UNP_FLIP_CONTROL register. Thus, no additional change is required to handle async page-flips with the atomic uAPI. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- v4: no changes --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 258461826140..7acd73e5004f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3970,7 +3970,6 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ adev_to_drm(adev)->mode_config.async_page_flip = true; - adev_to_drm(adev)->mode_config.atomic_async_page_flip_not_supported = true; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) -- 2.41.0
[PATCH v4 5/6] drm: Refuse to async flip with atomic prop changes
Given that prop changes may lead to modesetting, which would defeat the fast path of the async flip, refuse any atomic prop change for async flips in atomic API. The only exceptions are the framebuffer ID to flip to and the mode ID, that could be referring to an identical mode. Signed-off-by: André Almeida --- v4: new patch --- drivers/gpu/drm/drm_atomic_helper.c | 5 +++ drivers/gpu/drm/drm_atomic_uapi.c | 52 +++-- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_mode_object.c | 2 +- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2c2c9caf0be5..1e2973f0e1f6 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -629,6 +629,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) { + if (new_crtc_state->async_flip) { + drm_dbg_atomic(dev, "[CRTC:%d:%s] no mode changes allowed during async flip\n", + crtc->base.id, crtc->name); + return -EINVAL; + } drm_dbg_atomic(dev, "[CRTC:%d:%s] mode changed\n", crtc->base.id, crtc->name); new_crtc_state->mode_changed = true; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index dfd4cf7169df..536c21f53b5f 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -972,13 +972,28 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, return ret; } +static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value, +struct drm_property *prop) +{ + if (ret != 0 || old_val != prop_value) { + drm_dbg_atomic(prop->dev, + "[PROP:%d:%s] No prop can be changed during async flip\n", + prop->base.id, prop->name); + return -EINVAL; + } + + return 0; +} + int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, struct drm_property *prop, - uint64_t prop_value) + uint64_t prop_value, + bool async_flip) { struct drm_mode_object *ref; + uint64_t old_val; int ret; if (!drm_property_change_valid_get(prop, prop_value, &ref)) @@ -995,6 +1010,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip) { + ret = drm_atomic_connector_get_property(connector, connector_state, + prop, &old_val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_connector_set_property(connector, connector_state, file_priv, prop, prop_value); @@ -1003,6 +1025,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, case DRM_MODE_OBJECT_CRTC: { struct drm_crtc *crtc = obj_to_crtc(obj); struct drm_crtc_state *crtc_state; + struct drm_mode_config *config = &crtc->dev->mode_config; crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) { @@ -1010,6 +1033,18 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + /* +* We allow mode_id changes here for async flips, because we +* check later on drm_atomic_helper_check_modeset() callers if +* there are modeset changes or they are equal +*/ + if (async_flip && prop != config->prop_mode_id) { + ret = drm_atomic_crtc_get_property(crtc, crtc_state, + prop, &old_val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_crtc_set_property(crtc, crtc_state, prop, prop_value); break; @@ -1017,6 +1052,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, case DRM_MODE_OBJECT_PLANE: { struct drm
[PATCH v4 6/6] drm/doc: Define KMS atomic state set
Specify how the atomic state is maintained between userspace and kernel, plus the special case for async flips. Signed-off-by: André Almeida --- v4: new patch --- Documentation/gpu/drm-uapi.rst | 19 +++ 1 file changed, 19 insertions(+) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 65fb3036a580..5464376051cc 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -486,3 +486,22 @@ and the CRTC index is its position in this array. .. kernel-doc:: include/uapi/drm/drm_mode.h :internal: + +KMS atomic state + + +If a userspace using the DRM atomic API would like to change the modeset, it +needs to do in an atomic way, changing all desired properties in a single +commit. Following commits may contain the same properties again, as if they were +new. The kernel can then judge if those properties requires modesetting and real +changes, or it's just the same state as before. In summary, userspace commits do +not need to set the minimal state as possible and can commit redundant +information, and the kernel will ignore it. + +An observation must be made for atomic operations with DRM_MODE_PAGE_FLIP_ASYNC. +In such scenarios properties values can be sent, but the if they change +something, the kernel will reject the flip. This is done because property +changes can lead to modesetting, that would defeat the goal of flipping as fast +as possible. The only exceptions are the framebuffer ID to be flipped to and +mode IDs changes, which could be referring to an identical mode, thus not +requiring modeset. -- 2.41.0