On 10/22, Daniel Vetter wrote: > On Mon, Oct 22, 2018 at 09:27:18AM -0300, Rodrigo Siqueira wrote: > > Hi, > > > > I started to work for add the writeback feature into the VKMS, and this > > RFC represents my first draft. As a result, I have some questions which > > I list below. > > > > 1. In this patch, I replaced the virtual connector by the writeback > > connector. Is it a good idea? Or should I keep both connectors? If I > > keep both connectors, should I add a module parameter to enable the > > writeback? > > Yeah separate connector is imo better, with module config knob. Eventually > we can move that into configfs or similar. > > > 2. When I added the writeback connector (in > > drm_writeback_connector_init()), I noticed that I had to indicate the > > struct drm_encoder_helper_funcs. However, I think that VKMS does not > > need anything sophisticated related to encoders at the writeback > > perspective. Am I right? Or did I missed something? > > Yeah, you don't need anything fancy in the drm_encoder. I think you could > reuse the same dummy drm_encoder as we use for the normal connector. > > > 3. I just discovered that the writeback connectors are not exposed as a > > connector for the userspace, as a result, IGT tests do not work and > > Wayland is unable to run as well. Simon Ser and Daniel Stone, explained > > to me that I have to update the compositor (in my case Weston) to set > > DRM_CLIENT_CAP_WRITEBACK_CONNECTORS via drmSetClientCap(). Since I do > > not have experience with userspace, anyone can point me out another > > aspect that I have to take a look to make the writeback work in the user > > space? Also, Is it possible to update the IGT test or do I need to > > create a new set of tests? > > Yeah, writeback connector doesn't work like a normal connector, so it's > hidden by default. There should be special writeback connector tests in > igt though, but I guess those haven't been merged yet. Ask Liviu and Brian > from arm where they're stuck. Without those it's going to be rather hard > to make this work correctly. Hi, thanks for the feedbacks I will improve the code based on your comments, and for the testing mechanism, I want to try to make rootston run on top of VKMS. Best Regards > Cheers, Daniel > > > > > Thanks! > > > > Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@xxxxxxxxx> > > --- > > drivers/gpu/drm/vkms/vkms_crc.c | 9 ++- > > drivers/gpu/drm/vkms/vkms_crtc.c | 2 + > > drivers/gpu/drm/vkms/vkms_drv.h | 3 +- > > drivers/gpu/drm/vkms/vkms_output.c | 107 +++++++++++++++++++++-------- > > 4 files changed, 89 insertions(+), 32 deletions(-) > > > > diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c > > index 9d9e8146db90..5d9ac45e00f2 100644 > > --- a/drivers/gpu/drm/vkms/vkms_crc.c > > +++ b/drivers/gpu/drm/vkms/vkms_crc.c > > @@ -109,7 +109,8 @@ static void compose_cursor(struct vkms_crc_data *cursor_crc, > > } > > > > static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc, > > - struct vkms_crc_data *cursor_crc) > > + struct vkms_crc_data *cursor_crc, > > + struct vkms_output *out) > > { > > struct drm_framebuffer *fb = &primary_crc->fb; > > struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); > > @@ -130,6 +131,10 @@ static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc, > > } > > > > memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size); > > + // TODO: Remove this copy from crc, and make this sort of operation > > + // generic since we can use in different places > > + memcpy(out->connector.base.state->writeback_job->fb, > > + vkms_obj->vaddr, vkms_obj->gem.size); > > mutex_unlock(&vkms_obj->pages_lock); > > > > if (cursor_crc) > > @@ -193,7 +198,7 @@ void vkms_crc_work_handle(struct work_struct *work) > > } > > > > if (primary_crc) > > - crc32 = _vkms_get_crc(primary_crc, cursor_crc); > > + crc32 = _vkms_get_crc(primary_crc, cursor_crc, out); > > > > frame_end = drm_crtc_accurate_vblank_count(crtc); > > > > diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c > > index 177bbcb38306..d33ddcc40a29 100644 > > --- a/drivers/gpu/drm/vkms/vkms_crtc.c > > +++ b/drivers/gpu/drm/vkms/vkms_crtc.c > > @@ -48,6 +48,8 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) > > > > _vblank_handle(output); > > > > + drm_writeback_signal_completion(&output->connector, 0); > > + > > ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer, > > output->period_ns); > > > > diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h > > index 1c93990693e3..1e8184ad872f 100644 > > --- a/drivers/gpu/drm/vkms/vkms_drv.h > > +++ b/drivers/gpu/drm/vkms/vkms_drv.h > > @@ -5,6 +5,7 @@ > > #include <drm/drm.h> > > #include <drm/drm_gem.h> > > #include <drm/drm_encoder.h> > > +#include <drm/drm_writeback.h> > > #include <linux/hrtimer.h> > > > > #define XRES_MIN 20 > > @@ -61,7 +62,7 @@ struct vkms_crtc_state { > > struct vkms_output { > > struct drm_crtc crtc; > > struct drm_encoder encoder; > > - struct drm_connector connector; > > + struct drm_writeback_connector connector; > > struct hrtimer vblank_hrtimer; > > ktime_t period_ns; > > struct drm_pending_vblank_event *event; > > diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c > > index 271a0eb9042c..46622d012107 100644 > > --- a/drivers/gpu/drm/vkms/vkms_output.c > > +++ b/drivers/gpu/drm/vkms/vkms_output.c > > @@ -9,6 +9,13 @@ > > #include "vkms_drv.h" > > #include <drm/drm_crtc_helper.h> > > #include <drm/drm_atomic_helper.h> > > +#include <drm/drm_writeback.h> > > + > > +#define to_wb_state(_state) (struct vkms_writeback_connector_state *)(_state) > > + > > +struct vkms_writeback_connector_state { > > + struct drm_connector_state base; > > +}; > > > > static void vkms_connector_destroy(struct drm_connector *connector) > > { > > @@ -16,11 +23,48 @@ static void vkms_connector_destroy(struct drm_connector *connector) > > drm_connector_cleanup(connector); > > } > > > > +static void vkms_connector_reset(struct drm_connector *connector) > > +{ > > + struct vkms_writeback_connector_state *wb_state = > > + kzalloc(sizeof(*wb_state), GFP_KERNEL); > > + > > + if (connector->state) > > + __drm_atomic_helper_connector_destroy_state(connector->state); > > + > > + kfree(connector->state); > > + __drm_atomic_helper_connector_reset(connector, &wb_state->base); > > +} > > + > > +static struct drm_connector_state * > > +vkms_connector_duplicate_state(struct drm_connector *connector) > > +{ > > + struct vkms_writeback_connector_state *wb_state; > > + > > + if (WARN_ON(!connector->state)) > > + return NULL; > > + > > + wb_state = kzalloc(sizeof(*wb_state), GFP_KERNEL); > > + if (!wb_state) > > + return NULL; > > + > > + __drm_atomic_helper_connector_duplicate_state(connector, > > + &wb_state->base); > > + > > + return &wb_state->base; > > +} > > + > > +static enum drm_connector_status > > +vkms_connector_detect(struct drm_connector *connector, bool force) > > +{ > > + return connector_status_connected; > > +} > > + > > static const struct drm_connector_funcs vkms_connector_funcs = { > > + .reset = vkms_connector_reset, > > + .detect = vkms_connector_detect, > > .fill_modes = drm_helper_probe_single_connector_modes, > > .destroy = vkms_connector_destroy, > > - .reset = drm_atomic_helper_connector_reset, > > - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > > + .atomic_duplicate_state = vkms_connector_duplicate_state, > > .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > > }; > > > > @@ -42,12 +86,35 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = { > > .get_modes = vkms_conn_get_modes, > > }; > > > > +static int vkms_encoder_atomic_check(struct drm_encoder *encoder, > > + struct drm_crtc_state *crtc_state, > > + struct drm_connector_state *conn_state) > > +{ > > + struct drm_framebuffer *fb; > > + > > + if (!conn_state->writeback_job || !conn_state->writeback_job->fb) > > + return 0; > > + > > + fb = conn_state->writeback_job->fb; > > + if (fb->width != crtc_state->mode.hdisplay || > > + fb->height != crtc_state->mode.vdisplay) { > > + DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n", > > + fb->width, fb->height); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static const struct drm_encoder_helper_funcs vkms_encoder_helper_funcs = { > > + .atomic_check = vkms_encoder_atomic_check, > > +}; > > + > > int vkms_output_init(struct vkms_device *vkmsdev) > > { > > struct vkms_output *output = &vkmsdev->output; > > struct drm_device *dev = &vkmsdev->drm; > > - struct drm_connector *connector = &output->connector; > > - struct drm_encoder *encoder = &output->encoder; > > + struct drm_writeback_connector *connector = &output->connector; > > struct drm_crtc *crtc = &output->crtc; > > struct drm_plane *primary, *cursor = NULL; > > int ret; > > @@ -68,47 +135,29 @@ int vkms_output_init(struct vkms_device *vkmsdev) > > if (ret) > > goto err_crtc; > > > > - ret = drm_connector_init(dev, connector, &vkms_connector_funcs, > > - DRM_MODE_CONNECTOR_VIRTUAL); > > + ret = drm_writeback_connector_init(dev, connector, > > + &vkms_connector_funcs, > > + &vkms_encoder_helper_funcs, > > + vkms_formats, 1); > > if (ret) { > > DRM_ERROR("Failed to init connector\n"); > > goto err_connector; > > } > > > > - drm_connector_helper_add(connector, &vkms_conn_helper_funcs); > > + drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs); > > > > - ret = drm_connector_register(connector); > > + ret = drm_connector_register(&connector->base); > > if (ret) { > > DRM_ERROR("Failed to register connector\n"); > > goto err_connector_register; > > } > > > > - ret = drm_encoder_init(dev, encoder, &vkms_encoder_funcs, > > - DRM_MODE_ENCODER_VIRTUAL, NULL); > > - if (ret) { > > - DRM_ERROR("Failed to init encoder\n"); > > - goto err_encoder; > > - } > > - encoder->possible_crtcs = 1; > > - > > - ret = drm_connector_attach_encoder(connector, encoder); > > - if (ret) { > > - DRM_ERROR("Failed to attach connector to encoder\n"); > > - goto err_attach; > > - } > > - > > drm_mode_config_reset(dev); > > > > return 0; > > > > -err_attach: > > - drm_encoder_cleanup(encoder); > > - > > -err_encoder: > > - drm_connector_unregister(connector); > > - > > err_connector_register: > > - drm_connector_cleanup(connector); > > + drm_connector_cleanup(&connector->base); > > > > err_connector: > > drm_crtc_cleanup(crtc); > > -- > > 2.19.1 > > > > > > -- > > Rodrigo Siqueira > > https://siqueira.tech > > https://twitter.com/siqueirajordao > > Graduate Student > > Department of Computer Science > > University of São Paulo > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel