Re: drm/msm/mdp5: negative x/y in cursor move

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I found the solution:

ROI has to be recalculated for negative x/y indicating using the lower/right corner of the cursor buffer. Further, MDP5_LM_CURSOR_XY_SRC_Y and MDP5_LM_CURSOR_XY_SRC_X mus be calculated for the hotspot:

Index: kernel-source/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
===================================================================
--- kernel-source.orig/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ kernel-source/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -65,7 +65,7 @@ struct mdp5_crtc {
  struct drm_gem_object *scanout_bo;
  uint64_t iova;
  uint32_t width, height;
- uint32_t x, y;
+ int x, y;
  } cursor;
 };
 #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
@@ -756,10 +756,16 @@ static void get_roi(struct drm_crtc *crt
  * (xres-x) will be new cursor width when x > (xres - cursor.width)
  * (yres-y) will be new cursor height when y > (yres - cursor.height)
  */
- *roi_w = min(mdp5_crtc->cursor.width, xres -
- mdp5_crtc->cursor.x);
- *roi_h = min(mdp5_crtc->cursor.height, yres -
- mdp5_crtc->cursor.y);
+ if (mdp5_crtc->cursor.x >= 0)
+         *roi_w = min(mdp5_crtc->cursor.width, xres -
+         mdp5_crtc->cursor.x);
+ else
+         *roi_w = mdp5_crtc->cursor.width - abs(mdp5_crtc->cursor.x);
+ if (mdp5_crtc->cursor.y >= 0)
+         *roi_h = min(mdp5_crtc->cursor.height, yres -
+         mdp5_crtc->cursor.y);
+ else
+         *roi_h = mdp5_crtc->cursor.height - abs(mdp5_crtc->cursor.y);
 }
 
 static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
@@ -769,7 +775,7 @@ static void mdp5_crtc_restore_cursor(str
  struct mdp5_kms *mdp5_kms = get_kms(crtc);
  const enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
  uint32_t blendcfg, stride;
- uint32_t x, y, width, height;
+ uint32_t x, y, src_x, src_y, width, height;
  uint32_t roi_w, roi_h;
  int lm;
 
@@ -786,6 +792,20 @@ static void mdp5_crtc_restore_cursor(str
 
  get_roi(crtc, &roi_w, &roi_h);
 
+        if (mdp5_crtc->cursor.x < 0) {
+                src_x = abs(mdp5_crtc->cursor.x);
+                x = 0;
+         } else
+                src_x = 0;
+
+        if (mdp5_crtc->cursor.y < 0) {
+                src_y = abs(mdp5_crtc->cursor.y);
+                y = 0;
+        } else
+                src_y = 0;
+
+ //printk("x=%d, y=%d roi_w=%d roi_h=%d src_x=%d src_y=%d\n", x, y, roi_w, roi_h, src_x, src_y);
+
  mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
  mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
  MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
@@ -798,6 +818,9 @@ static void mdp5_crtc_restore_cursor(str
  mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm),
  MDP5_LM_CURSOR_START_XY_Y_START(y) |
  MDP5_LM_CURSOR_START_XY_X_START(x));
+ mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_XY(lm),
+ MDP5_LM_CURSOR_XY_SRC_Y(src_y) |
+ MDP5_LM_CURSOR_XY_SRC_X(src_x));
  mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm),
  mdp5_crtc->cursor.iova);
 
@@ -903,6 +926,8 @@ static int mdp5_crtc_cursor_move(struct
  uint32_t roi_w;
  uint32_t roi_h;
  unsigned long flags;
+ int border_x = mdp5_crtc->cursor.width * (-1);
+ int border_y = mdp5_crtc->cursor.height * (-1);
 
  if (!mdp5_crtc->lm_cursor_enabled) {
  dev_warn(dev->dev,
@@ -918,8 +943,8 @@ static int mdp5_crtc_cursor_move(struct
  if (unlikely(!crtc->state->enable))
  return 0;
 
- mdp5_crtc->cursor.x = x = max(x, 0);
- mdp5_crtc->cursor.y = y = max(y, 0);
+ mdp5_crtc->cursor.x = x = max(x, border_x);
+ mdp5_crtc->cursor.y = y = max(y, border_y);
 
  get_roi(crtc, &roi_w, &roi_h);
 
Best regards
-Carsten

2018-07-10 12:11 GMT+02:00 Carsten Behling <carsten.behling@xxxxxxxxxxxxxx>:
Hi,

modesetting X11 driver may provide negative x/y cordinates in mdp5_crtc_cursor_move(...) call when rotation is enabled.

Because of

static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
{
...
mdp5_crtc->cursor.x = x = max(x, 0);
mdp5_crtc->cursor.y = y = max(y, 0);
...
}

x/y is calmped to 0/0 in those cases resulting that the cursor does not move anymore beyond mdp5_crtc->cursor.width, mdp5_crtc->cursor.height.

For e.g rotation of 180 degree that means that the upper left cursor point stays never reaches the region (0/0) to  (mdp5_crtc->cursor.width/mdp5_crtc->cursor.height).

I already asked the X men if this should be fixed in modesetting driver or in the kernel CRT
functions:


They told me to fix this in the kernel.

So, I suppose:

1.) cursor x should be rather clamped instead to

static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { 
...
mdp5_crtc->cursor.x = x = max(x, -mdp5_crtc->cursor.width);
mdp5_crtc->cursor.y = y = max(y, -mdp5_crtc->cursor.height);
...
}

 2.) The ROI calculation must be extendet to:

static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)
{
...
if (x>=0)
        *roi_w = min(mdp5_crtc->cursor.width, xres -
        mdp5_crtc->cursor.x);
else
        *roi_w = mdp5_crtc->cursor.width - abs(mdp5_crtc->cursor.x);
if (y>=0)
        *roi_h = min(mdp5_crtc->cursor.height, yres -
        mdp5_crtc->cursor.y);
else
        *roi_h = mdp5_crtc->cursor.height - abs(mdp5_crtc->cursor.y);
...
}

3.) There has to be some kind of hotspot setup in mdp5_crtc_restore_cursor(...)

Since I have no MDP5 documentation, I don't know how to setup the hotspot and I can't
implement 3.)

Please help!

Best regards
-Carsten

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux