mirror of
https://github.com/X11Libre/xserver.git
synced 2026-11-15 05:23:40 +00:00
kdrive/modesetting: Implement hw cursor RandR
Discovered a bug where, when Xmodesetting is started with an initially-rotated screen, the cursor position is incorectly clamped to the unrotated screen width and height. This doesn't happen when Xmodesetting is started without any rotations and then rotated with xrandr. Needs investigating Signed-off-by: stefan11111 <stefan11111github@gmail.com>
This commit is contained in:
parent
143fe031c6
commit
5e06d2b3b1
2 changed files with 122 additions and 12 deletions
|
|
@ -34,6 +34,9 @@ typedef struct _msPriv {
|
|||
typedef struct _msCursPriv {
|
||||
struct gbm_bo *bo;
|
||||
|
||||
/* For RandR */
|
||||
uint32_t *shadow;
|
||||
|
||||
int xhot;
|
||||
int yhot;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,91 @@
|
|||
|
||||
static Bool msShowCursor(ScreenPtr pScreen);
|
||||
|
||||
/*
|
||||
* Given a screen coordinate, rotate back to a cursor source coordinate
|
||||
*/
|
||||
static void
|
||||
KdRotateCoord(Rotation rotation,
|
||||
int width, int height,
|
||||
int x_dst, int y_dst,
|
||||
int *x_src, int *y_src)
|
||||
{
|
||||
int t;
|
||||
|
||||
switch (rotation & 0xf) {
|
||||
case RR_Rotate_0:
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
t = x_dst;
|
||||
x_dst = width - y_dst - 1;
|
||||
y_dst = t;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
x_dst = width - x_dst - 1;
|
||||
y_dst = height - y_dst - 1;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
t = x_dst;
|
||||
x_dst = y_dst;
|
||||
y_dst = height - t - 1;
|
||||
break;
|
||||
}
|
||||
if (rotation & RR_Reflect_X)
|
||||
x_dst = width - x_dst - 1;
|
||||
if (rotation & RR_Reflect_Y)
|
||||
y_dst = height - y_dst - 1;
|
||||
|
||||
if (x_dst < 0) {
|
||||
x_dst = 0;
|
||||
}
|
||||
|
||||
if (y_dst < 0) {
|
||||
y_dst = 0;
|
||||
}
|
||||
|
||||
*x_src = x_dst;
|
||||
*y_src = y_dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a cursor source coordinate, rotate to a screen coordinate
|
||||
*/
|
||||
static void
|
||||
KdRotateCoordBack(Rotation rotation,
|
||||
int width, int height,
|
||||
int x_dst, int y_dst,
|
||||
int *x_src, int *y_src)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (rotation & RR_Reflect_X)
|
||||
x_dst = width - x_dst - 1;
|
||||
if (rotation & RR_Reflect_Y)
|
||||
y_dst = height - y_dst - 1;
|
||||
|
||||
switch (rotation & 0xf) {
|
||||
case RR_Rotate_0:
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
t = x_dst;
|
||||
x_dst = y_dst;
|
||||
y_dst = width - t - 1;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
x_dst = width - x_dst - 1;
|
||||
y_dst = height - y_dst - 1;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
t = x_dst;
|
||||
x_dst = height - y_dst - 1;
|
||||
y_dst = t;
|
||||
break;
|
||||
}
|
||||
|
||||
*x_src = x_dst;
|
||||
*y_src = y_dst;
|
||||
}
|
||||
|
||||
static void
|
||||
msGetCursorSizes(int fd, int *w, int *h)
|
||||
{
|
||||
|
|
@ -83,7 +168,8 @@ msLoadCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
|||
uint32_t width = gbm_bo_get_width(pCurPriv->bo);
|
||||
uint32_t height = gbm_bo_get_width(pCurPriv->bo);
|
||||
uint32_t stride = gbm_bo_get_stride(pCurPriv->bo) / sizeof(uint32_t);
|
||||
uint32_t *ram = gbm_bo_get_map(pCurPriv->bo);
|
||||
uint32_t *map = gbm_bo_get_map(pCurPriv->bo);
|
||||
uint32_t *ram = map;
|
||||
|
||||
int x, y;
|
||||
|
||||
|
|
@ -97,7 +183,14 @@ msLoadCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
|||
h = height;
|
||||
}
|
||||
|
||||
/* TODO: Deal with rotations */
|
||||
if (scrpriv->randr != RR_Rotate_0) {
|
||||
if (!pCurPriv->shadow) {
|
||||
pCurPriv->shadow = calloc(width * stride, sizeof(*ram));
|
||||
}
|
||||
if (pCurPriv->shadow) {
|
||||
ram = pCurPriv->shadow;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits->argb) {
|
||||
srcLine = bits->argb;
|
||||
|
|
@ -157,9 +250,24 @@ msLoadCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
|||
}
|
||||
}
|
||||
|
||||
if (scrpriv->randr != RR_Rotate_0) {
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
int x_in, y_in;
|
||||
KdRotateCoord(scrpriv->randr,
|
||||
width, height,
|
||||
x, y,
|
||||
&x_in, &y_in);
|
||||
map[y * stride + x] = ram[y_in * stride + x_in];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the cursor glyph hotspot */
|
||||
pCurPriv->xhot = bits->xhot;
|
||||
pCurPriv->yhot = bits->yhot;
|
||||
KdRotateCoordBack(scrpriv->randr,
|
||||
width, height,
|
||||
bits->xhot, bits->yhot,
|
||||
&pCurPriv->xhot, &pCurPriv->yhot);
|
||||
|
||||
return msShowCursor(pScreen);
|
||||
}
|
||||
|
|
@ -218,18 +326,15 @@ msMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
|
|||
|
||||
int fd = gbm_device_get_fd(priv->gbm);
|
||||
|
||||
KdRotateCoordBack(scrpriv->randr,
|
||||
pScreen->width, pScreen->height,
|
||||
x, y,
|
||||
&x, &y);
|
||||
|
||||
/* Offset the cursor position, so that the cursor hotspot looks right */
|
||||
x -= pCurPriv->xhot;
|
||||
y -= pCurPriv->yhot;
|
||||
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
drmModeMoveCursor(fd, scrpriv->crtc_id, x, y);
|
||||
}
|
||||
|
||||
|
|
@ -342,6 +447,8 @@ msCursorFini(ScreenPtr pScreen)
|
|||
msScrPriv *scrpriv = screen->driver;
|
||||
msCursPriv *pCurPriv = &scrpriv->cursor;
|
||||
|
||||
free(pCurPriv->shadow);
|
||||
|
||||
pScreen->QueryBestSize = pCurPriv->QueryBestSize;
|
||||
|
||||
gbm_bo_destroy(pCurPriv->bo);
|
||||
|
|
|
|||
Loading…
Reference in a new issue