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 ofstatic 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 CRTfunctions:They told me to fix this in the kernel.So, I suppose:1.) cursor x should be rather clamped instead tostatic 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'timplement 3.)Please help!Best regards-Carsten
_______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel