On Thu, May 15, 2014 at 06:17:29PM -0700, Matt Roper wrote: > The DRM core will translate calls to legacy cursor ioctls into universal > cursor calls automatically, so there's no need to maintain the legacy > cursor support. This greatly simplifies the transition since we don't > have to handle reference counting differently depending on which cursor > interface was called. > > The aim here is to transition to the universal plane interface with > minimal code change. There's a lot of cleanup that can be done (e.g., > using state stored in crtc->cursor->fb rather than intel_crtc) that is > left to future patches. > > Signed-off-by: Matt Roper <matthew.d.roper@xxxxxxxxx> Bunch of comments below. I think for testing we have good coverage of functional cursor tests already, and with the backwards-compat code in the drm core we'll excerise the cursor plane code sufficiently imo. But there's a bit of corner-case checking: - Interactions between legacy cursor ioctl and the new stuff to check the refcounting and correctness wrt set_bo and visible and fun like that. - Maybe some checks for the no-upscaling and no-clipping stuff. Hopefully you can easily copy&paste this from the primary plane tests. But in the end you're worked on this and are the expert, so if you think a different focus gives a better payoff then I'm all ears - we want to write tests that have a good chance of catching real bugs after all ;-) Cheers, Daniel > --- > drivers/gpu/drm/i915/intel_display.c | 194 ++++++++++++++++++++++++----------- > drivers/gpu/drm/i915/intel_drv.h | 1 - > 2 files changed, 136 insertions(+), 59 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 7e75b13..d145130 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -68,6 +68,11 @@ static const uint32_t intel_primary_formats_gen4[] = { > DRM_FORMAT_ABGR2101010, > }; > > +/* Cursor formats */ > +static const uint32_t intel_cursor_formats[] = { > + DRM_FORMAT_ARGB8888, > +}; > + > #define DIV_ROUND_CLOSEST_ULL(ll, d) \ > ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; }) > > @@ -7967,8 +7972,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > int pipe = intel_crtc->pipe; > - int x = intel_crtc->cursor_x; > - int y = intel_crtc->cursor_y; > + int x = crtc->cursor_x; > + int y = crtc->cursor_y; > u32 base = 0, pos = 0; > bool visible; > > @@ -8023,8 +8028,6 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, > * @height: cursor height > * > * Programs a crtc's cursor plane with the specified GEM object. > - * intel_crtc_cursor_set() should be used instead if we have a userspace buffer > - * handle rather than the actual GEM object. > */ > static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, > struct drm_i915_gem_object *obj, > @@ -8143,48 +8146,6 @@ fail: > return ret; > } > > -/** > - * intel_crtc_cursor_set - Update cursor buffer > - * @crtc: crtc to set cursor for > - * @handle: userspace handle of buffer to set cursor to > - * @width: cursor width > - * @height: cursor height > - * > - * Programs a crtc's cursor plane with the buffer referred to by userspace > - * handle @handle. > - */ > -static int intel_crtc_cursor_set(struct drm_crtc *crtc, > - struct drm_file *file, > - uint32_t handle, > - uint32_t width, uint32_t height) > -{ > - struct drm_device *dev = crtc->dev; > - struct drm_i915_gem_object *obj; > - > - if (handle) { > - obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); > - if (&obj->base == NULL) > - return -ENOENT; > - } else { > - obj = NULL; > - } > - > - return intel_crtc_cursor_set_obj(crtc, obj, width, height); > -} > - > -static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) > -{ > - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > - > - intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX); > - intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); > - > - if (intel_crtc->active) > - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); > - > - return 0; > -} > - > static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, > u16 *blue, uint32_t start, uint32_t size) > { > @@ -8806,7 +8767,7 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) > kfree(work); > } > > - intel_crtc_cursor_set(crtc, NULL, 0, 0, 0); > + intel_crtc_cursor_set_obj(crtc, NULL, 0, 0); This shouldn't be needed any more with the plane cleanup code - all the refcounting is now done with fbs. > > drm_crtc_cleanup(crtc); > > @@ -10784,8 +10745,6 @@ out_config: > } > > static const struct drm_crtc_funcs intel_crtc_funcs = { > - .cursor_set = intel_crtc_cursor_set, > - .cursor_move = intel_crtc_cursor_move, > .gamma_set = intel_crtc_gamma_set, > .set_config = intel_crtc_set_config, > .destroy = intel_crtc_destroy, > @@ -11018,7 +10977,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, > return 0; > } > > -static void intel_primary_plane_destroy(struct drm_plane *plane) > +/* Common destruction function for both primary and cursor planes */ > +static void intel_plane_destroy(struct drm_plane *plane) Actually a review comment for your primary plane series: We have this function as intel_destroy_plane in intel_sprite.c already ;-) > { > struct intel_plane *intel_plane = to_intel_plane(plane); > drm_plane_cleanup(plane); > @@ -11028,7 +10988,7 @@ static void intel_primary_plane_destroy(struct drm_plane *plane) > static const struct drm_plane_funcs intel_primary_plane_funcs = { > .update_plane = intel_primary_plane_setplane, > .disable_plane = intel_primary_plane_disable, > - .destroy = intel_primary_plane_destroy, > + .destroy = intel_plane_destroy, > }; > > static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, > @@ -11064,11 +11024,116 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, > return &primary->base; > } > > +static int > +intel_cursor_plane_disable(struct drm_plane *plane) > +{ > + if (!plane->fb) > + return 0; > + > + BUG_ON(!plane->crtc); > + > + return intel_crtc_cursor_set_obj(plane->crtc, NULL, 0, 0); > +} > + > +static int > +intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, > + struct drm_framebuffer *fb, int crtc_x, int crtc_y, > + unsigned int crtc_w, unsigned int crtc_h, > + uint32_t src_x, uint32_t src_y, > + uint32_t src_w, uint32_t src_h) > +{ > + struct drm_device *dev = crtc->dev; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); > + struct drm_i915_gem_object *obj = intel_fb->obj; > + struct drm_rect dest = { > + /* integer pixels */ > + .x1 = crtc_x, > + .y1 = crtc_y, > + .x2 = crtc_x + crtc_w, > + .y2 = crtc_y + crtc_h, > + }; > + struct drm_rect src = { > + /* 16.16 fixed point */ > + .x1 = src_x, > + .y1 = src_y, > + .x2 = src_x + src_w, > + .y2 = src_y + src_h, > + }; > + const struct drm_rect clip = { > + /* integer pixels */ > + .x2 = intel_crtc->config.pipe_src_w, > + .y2 = intel_crtc->config.pipe_src_h, > + }; > + int hscale, vscale; > + bool visible; > + > + /* Check scaling */ > + hscale = drm_rect_calc_hscale(&src, &dest, > + DRM_PLANE_HELPER_NO_SCALING, > + DRM_PLANE_HELPER_NO_SCALING); > + vscale = drm_rect_calc_vscale(&src, &dest, > + DRM_PLANE_HELPER_NO_SCALING, > + DRM_PLANE_HELPER_NO_SCALING); > + if (hscale < 0 || vscale < 0) { > + DRM_DEBUG_KMS("Invalid scaling of cursor plane\n"); > + return -ERANGE; > + } Can't we reuse the check helpers for primary planes here? We again want to scaling and no additional clipping (besides the viewport clipping). > + > + /* Check dimensions */ > + if (!((crtc_w == 64 && crtc_h == 64) || > + (crtc_w == 128 && crtc_h == 128 && !IS_GEN2(dev)) || > + (crtc_w == 256 && crtc_h == 256 && !IS_GEN2(dev)))) { > + DRM_DEBUG_KMS("Cursor dimension not supported: %dx%d\n", > + crtc_w, crtc_h); > + return -EINVAL; > + } Isn't this check redudnant with the one in cursor_set_obj? > + > + /* Clip to display; if no longer visible after clipping, disable */ > + visible = drm_rect_clip_scaled(&src, &dest, &clip, hscale, vscale); > + > + crtc->cursor_x = crtc_x; > + crtc->cursor_y = crtc_y; > + if (fb != crtc->cursor->fb) { > + return intel_crtc_cursor_set_obj(crtc, visible ? obj : NULL, > + crtc_w, crtc_h); > + } else { > + intel_crtc_update_cursor(crtc, true); > + return 0; > + } > +} > +static const struct drm_plane_funcs intel_cursor_plane_funcs = { > + .update_plane = intel_cursor_plane_update, > + .disable_plane = intel_cursor_plane_disable, > + .destroy = intel_plane_destroy, > +}; > + > +static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, > + int pipe) > +{ > + struct intel_plane *cursor; > + > + cursor = kzalloc(sizeof(*cursor), GFP_KERNEL); > + if (cursor == NULL) > + return NULL; > + > + cursor->can_scale = false; > + cursor->max_downscale = 1; > + cursor->pipe = pipe; > + cursor->plane = pipe; > + > + drm_plane_init(dev, &cursor->base, 0, > + &intel_cursor_plane_funcs, intel_cursor_formats, > + ARRAY_SIZE(intel_cursor_formats), DRM_PLANE_TYPE_CURSOR); > + return &cursor->base; > +} > + > static void intel_crtc_init(struct drm_device *dev, int pipe) > { > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_crtc *intel_crtc; > - struct drm_plane *primary; > + struct drm_plane *primary = NULL; > + struct drm_plane *cursor = NULL; > int i, ret; > > intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); > @@ -11076,13 +11141,17 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > return; > > primary = intel_primary_plane_create(dev, pipe); > + if (!primary) > + goto fail; > + > + cursor = intel_cursor_plane_create(dev, pipe); > + if (!cursor) > + goto fail; > + > ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary, > - NULL, &intel_crtc_funcs); > - if (ret) { > - drm_plane_cleanup(primary); > - kfree(intel_crtc); > - return; > - } > + cursor, &intel_crtc_funcs); > + if (ret) > + goto fail; > > drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); > for (i = 0; i < 256; i++) { > @@ -11110,6 +11179,15 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; > > drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); > + > + return; > + > +fail: > + if (primary) > + drm_plane_cleanup(primary); > + if (cursor) > + drm_plane_cleanup(cursor); > + kfree(intel_crtc); > } > > enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 32a74e1..8374f37a 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -378,7 +378,6 @@ struct intel_crtc { > > struct drm_i915_gem_object *cursor_bo; > uint32_t cursor_addr; > - int16_t cursor_x, cursor_y; > int16_t cursor_width, cursor_height; > bool cursor_visible; > > -- > 1.8.5.1 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel