[PATCH 2/9] compositor: Output repaint in clone mode

Zhang, Xiong Y xiong.y.zhang at intel.com
Sun Feb 16 19:05:03 PST 2014


On Fri, 2014-02-14 at 09:49 +0200, Pekka Paalanen wrote:
> On Fri, 14 Feb 2014 15:17:37 +0800
> Xiong Zhang <xiong.y.zhang at intel.com> wrote:
> 
> > Because slave output doesn't in compositor->output_list,
> > the output->repaint()is called from master output only.
> > When master output repaint,all the slave output should
> > repaint also.
> > 
> > Slave output share fb with master output,when both slave and
> > master have finished page flip, the fb obj can be released.
> 
> Hi,
> 
> ok, so core's finish_frame will be called when all flips of a master
> output and its slaves have completed. If the refresh rates of these
> outputs are different, I think it means that the perceived frame rate
> (the frequency at which finish_frame is called) will fluctuate over
> time. That will have very interesting consequences for presentation
> prediction and feedback.
Thanks for your remind. Frequency different between outputs is indeed a
challenge for clone mode.
The perceived frame rate will be the lowest refresh rate in master and
its slaves. This will have influence on presentation prediction.
> 
> OTOH, the future will bring dynamically varied refresh rate monitors,
> so client's should be prepared for fluctuations in the apparent vblank
> frequency anyway.
> 
> I'm not claiming your patch creates a problem, I think we can cope with
> it, but it will be interesting nevertheless. Just pointing out we
> should keep this in mind.
> 
> We may need to tweak finish_frame calling logic a bit, so that it gets
> the flip completion timestamp of the master output, and not whatever
> output was the last one. But that will only be a concern when the
> presentation extension lands. I think... unless we care about the
> timestamp carried by the frame callbacks.
> 
> 
yes, this is a good ideal. finish_frame should get the flip completion
timestamp of the master output.
 But client will get frame callback when both master and its slaves
finish flip.

thanks 
> Thanks,
> pq
> 
> 
> > Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
> > ---
> >  src/compositor-drm.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  src/compositor.c     |   3 +-
> >  2 files changed, 112 insertions(+), 3 deletions(-)
> > 
> > diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> > index 6773226..ce85aec 100644
> > --- a/src/compositor-drm.c
> > +++ b/src/compositor-drm.c
> > @@ -155,6 +155,7 @@ struct drm_output {
> >  
> >  	uint32_t transform;
> >  	int scale, mm_width, mm_height;
> > +	uint32_t page_flip_count;
> >  
> >  	struct gbm_surface *surface;
> >  	struct gbm_bo *cursor_bo[2];
> > @@ -591,8 +592,9 @@ drm_output_repaint(struct weston_output *output_base,
> >  	struct drm_sprite *s;
> >  	struct drm_mode *mode;
> >  	int ret = 0;
> > +	struct drm_output *clone_output;
> >  
> > -	if (output->destroy_pending)
> > +	if (output->destroy_pending || output->base.is_slave)
> >  		return -1;
> >  
> >  	if (!output->next)
> > @@ -612,6 +614,25 @@ drm_output_repaint(struct weston_output *output_base,
> >  			goto err_pageflip;
> >  		}
> >  		output_base->set_dpms(output_base, WESTON_DPMS_ON);
> > +
> > +		wl_list_for_each(clone_output, &output->base.clone_output_list,
> > +				 base.link) {
> > +			mode = container_of(clone_output->base.current_mode,
> > +					    struct drm_mode, base);
> > +
> > +			ret = drmModeSetCrtc(compositor->drm.fd,
> > +					     clone_output->crtc_id,
> > +					     output->next->fb_id, 0, 0,
> > +					     &clone_output->connector_id, 1,
> > +					     &mode->mode_info);
> > +			if (ret) {
> > +				weston_log("set mode failed:%m\n");
> > +				goto err_pageflip;
> > +			}
> > +
> > +			clone_output->base.set_dpms(&clone_output->base,
> > +						    WESTON_DPMS_ON);
> > +		}
> >  	}
> >  
> >  	if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
> > @@ -622,6 +643,23 @@ drm_output_repaint(struct weston_output *output_base,
> >  	}
> >  
> >  	output->page_flip_pending = 1;
> > +	output->page_flip_count++;
> > +
> > +	/* clone output repaint*/
> > +	wl_list_for_each(clone_output, &output->base.clone_output_list,
> > +			 base.link) {
> > +		if (drmModePageFlip(compositor->drm.fd,
> > +				    clone_output->crtc_id,
> > +				    output->next->fb_id,
> > +				    DRM_MODE_PAGE_FLIP_EVENT,
> > +				    clone_output) < 0) {
> > +			weston_log("queueing pageflip failed:%m\n");
> > +			goto err_pageflip;
> > +		}
> > +
> > +		clone_output->page_flip_pending = 1;
> > +		output->page_flip_count++;
> > +	}
> >  
> >  	drm_output_set_cursor(output);
> >  
> > @@ -691,8 +729,9 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
> >  	uint32_t fb_id;
> >  	uint32_t msec;
> >  	struct timespec ts;
> > +	struct drm_output *clone_output;
> >  
> > -	if (output->destroy_pending)
> > +	if (output->destroy_pending || output->base.is_slave)
> >  		return;
> >  
> >  	if (!output->current) {
> > @@ -707,6 +746,22 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
> >  		weston_log("queueing pageflip failed: %m\n");
> >  		goto finish_frame;
> >  	}
> > +	output->page_flip_count++;
> > +
> > +	/* clone output repaint*/
> > +	wl_list_for_each(clone_output, &output->base.clone_output_list,
> > +			 base.link) {
> > +		if (drmModePageFlip(compositor->drm.fd,
> > +				    clone_output->crtc_id,
> > +				    fb_id,
> > +				    DRM_MODE_PAGE_FLIP_EVENT,
> > +				    clone_output) < 0) {
> > +			weston_log("queueing pageflip failed:%m\n");
> > +			goto finish_frame;
> > +		}
> > +
> > +		output->page_flip_count++;
> > +	}
> >  
> >  	return;
> >  
> > @@ -745,8 +800,22 @@ page_flip_handler(int fd, unsigned int frame,
> >  		  unsigned int sec, unsigned int usec, void *data)
> >  {
> >  	struct drm_output *output = (struct drm_output *) data;
> > +	struct drm_output *master_output;
> >  	uint32_t msecs;
> >  
> > +	if (output->base.is_slave) {
> > +		master_output = (struct drm_output *)output->base.master_output;
> > +		master_output->page_flip_count--;
> > +		output->page_flip_pending = 0;
> > +		if (output->destroy_pending)
> > +			drm_output_destroy(&output->base);
> > +		output = master_output;
> > +	} else
> > +		output->page_flip_count--;
> > +
> > +	if (output->page_flip_count != 0)
> > +		return;
> > +
> >  	/* We don't set page_flip_pending on start_repaint_loop, in that case
> >  	 * we just want to page flip to the current buffer to get an accurate
> >  	 * timestamp */
> > @@ -990,10 +1059,21 @@ drm_output_set_cursor(struct drm_output *output)
> >  	uint32_t buf[64 * 64];
> >  	unsigned char *s;
> >  	int i, x, y;
> > +	struct drm_output *clone_output;
> >  
> >  	output->cursor_view = NULL;
> >  	if (ev == NULL) {
> >  		drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
> > +
> > +		if (!output->base.is_slave) {
> > +			wl_list_for_each(clone_output,
> > +					 &output->base.clone_output_list,
> > +					 base.link) {
> > +				drmModeSetCursor(c->drm.fd,
> > +						clone_output->crtc_id, 0, 0, 0);
> > +			}
> > +		}
> > +
> >  		return;
> >  	}
> >  
> > @@ -1023,6 +1103,19 @@ drm_output_set_cursor(struct drm_output *output)
> >  			weston_log("failed to set cursor: %m\n");
> >  			c->cursors_are_broken = 1;
> >  		}
> > +
> > +		if (!output->base.is_slave) {
> > +			wl_list_for_each(clone_output,
> > +					 &output->base.clone_output_list,
> > +					 base.link) {
> > +				if (drmModeSetCursor(c->drm.fd,
> > +						     clone_output->crtc_id,
> > +						     handle, 64, 64)) {
> > +					weston_log("failed to set cursor: %m\n");
> > +					c->cursors_are_broken = 1;
> > +				}
> > +			}
> > +		}
> >  	}
> >  
> >  	x = (ev->geometry.x - output->base.x) * output->base.current_scale;
> > @@ -1035,6 +1128,21 @@ drm_output_set_cursor(struct drm_output *output)
> >  
> >  		output->cursor_plane.x = x;
> >  		output->cursor_plane.y = y;
> > +
> > +		if (!output->base.is_slave) {
> > +			wl_list_for_each(clone_output,
> > +					 &output->base.clone_output_list,
> > +					 base.link) {
> > +				if (drmModeMoveCursor(c->drm.fd,
> > +						clone_output->crtc_id, x, y)) {
> > +					weston_log("failed to move cursor: %m\n");
> > +					c->cursors_are_broken = 1;
> > +				}
> > +
> > +				clone_output->cursor_plane.x = x;
> > +				clone_output->cursor_plane.y = y;
> > +			}
> > +		}
> >  	}
> >  }
> >  
> > diff --git a/src/compositor.c b/src/compositor.c
> > index 942c398..2c30334 100644
> > --- a/src/compositor.c
> > +++ b/src/compositor.c
> > @@ -3276,7 +3276,8 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
> >  	weston_output_init_zoom(output);
> >  
> >  	weston_output_init_geometry(output, x, y);
> > -	weston_output_damage(output);
> > +	if (!output->is_slave)
> > +		weston_output_damage(output);
> >  
> >  	wl_signal_init(&output->frame_signal);
> >  	wl_signal_init(&output->destroy_signal);
> 



More information about the wayland-devel mailing list