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.behl...@googlemail.com>: > 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: > > https://www.spinics.net/lists/xorg/msg58969.html > > 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@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel