xf86-video-ati: Branch 'master' - 13 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Dec 28 11:15:54 UTC 2018
src/drmmode_display.c | 225 ++++++++++++++++++++++++++++++++-----------------
src/drmmode_display.h | 18 +++
src/radeon.h | 1
src/radeon_bo_helper.c | 2
src/radeon_dri2.c | 4
src/radeon_drm_queue.c | 110 +++++++++++++----------
src/radeon_drm_queue.h | 3
src/radeon_glamor.c | 7 +
src/radeon_kms.c | 147 +++++++++++++++++++++++---------
src/radeon_present.c | 3
10 files changed, 352 insertions(+), 168 deletions(-)
New commits:
commit 803f872f7d4b2d80be434bb42ce64dfd295b122c
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 18:04:21 2018 +0100
Use two HW cursor buffers per CRTC
Switch to the other buffer when xf86_config->cursor changes. Avoids
these issues possible when re-using the same buffer:
* The HW may intermittently display a mix of the old and new cursor
images.
* If the hotspot changes, the HW may intermittently display the new
cursor image at the location corresponding to the old image's hotspot.
Bugzilla: https://bugs.freedesktop.org/108832
(Ported from amdgpu commit 0d60233d26ec70d4e1faa343b438e33829c6d5e4)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index bec309e5..d433e061 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1122,13 +1122,18 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
ScrnInfoPtr pScrn = crtc->scrn;
RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ unsigned id = drmmode_crtc->cursor_id;
Bool premultiplied = TRUE;
Bool apply_gamma = TRUE;
uint32_t argb;
uint32_t *ptr;
+ if (drmmode_crtc->cursor &&
+ XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor)
+ id ^= 1;
+
/* cursor should be mapped already */
- ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
+ ptr = (uint32_t *)(drmmode_crtc->cursor_bo[id]->ptr);
if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
apply_gamma = FALSE;
@@ -1170,6 +1175,11 @@ retry:
ptr[i] = cpu_to_le32(argb);
}
}
+
+ if (id != drmmode_crtc->cursor_id) {
+ drmmode_crtc->cursor_id = id;
+ crtc->funcs->show_cursor(crtc);
+ }
}
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
@@ -1195,7 +1205,7 @@ drmmode_hide_cursor (xf86CrtcPtr crtc)
drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
info->cursor_w, info->cursor_h);
-
+ drmmode_crtc->cursor = NULL;
}
static void
@@ -1212,9 +1222,11 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
static Bool use_set_cursor2 = TRUE;
struct drm_mode_cursor2 arg;
+ drmmode_crtc->cursor = xf86_config->cursor;
+
memset(&arg, 0, sizeof(arg));
- arg.handle = drmmode_crtc->cursor_bo->handle;
+ arg.handle = drmmode_crtc->cursor_bo[drmmode_crtc->cursor_id]->handle;
arg.flags = DRM_MODE_CURSOR_BO;
arg.crtc_id = drmmode_crtc->mode_crtc->crtc_id;
arg.width = info->cursor_w;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 49893ab0..2c2c3d57 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -88,11 +88,14 @@ typedef struct {
drmModeCrtcPtr mode_crtc;
int hw_id;
+ CursorPtr cursor;
int cursor_x;
int cursor_y;
int cursor_xhot;
int cursor_yhot;
- struct radeon_bo *cursor_bo;
+ unsigned cursor_id;
+ struct radeon_bo *cursor_bo[2];
+
struct drmmode_scanout rotate;
struct drmmode_scanout scanout[2];
DamagePtr scanout_damage;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 27a02109..bb6885fb 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -2755,27 +2755,29 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
{
int cursor_size;
- int c;
+ int c, i;
cursor_size = info->cursor_w * info->cursor_h * 4;
cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE);
for (c = 0; c < xf86_config->num_crtc; c++) {
drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
- if (!drmmode_crtc->cursor_bo) {
- drmmode_crtc->cursor_bo = radeon_bo_open(info->bufmgr, 0,
- cursor_size, 0,
- RADEON_GEM_DOMAIN_VRAM, 0);
- if (!(drmmode_crtc->cursor_bo)) {
- ErrorF("Failed to allocate cursor buffer memory\n");
- return FALSE;
- }
-
- if (radeon_bo_map(drmmode_crtc->cursor_bo, 1)) {
- ErrorF("Failed to map cursor buffer memory\n");
- }
- }
- }
+ for (i = 0; i < 2; i++) {
+ if (!drmmode_crtc->cursor_bo[i]) {
+ drmmode_crtc->cursor_bo[i] =
+ radeon_bo_open(info->bufmgr, 0, cursor_size, 0,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+
+ if (!(drmmode_crtc->cursor_bo[i])) {
+ ErrorF("Failed to allocate cursor buffer memory\n");
+ return FALSE;
+ }
+
+ if (radeon_bo_map(drmmode_crtc->cursor_bo[i], 1))
+ ErrorF("Failed to map cursor buffer memory\n");
+ }
+ }
+ }
}
if (!info->front_buffer) {
@@ -2841,7 +2843,7 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size)
for (c = 0; c < xf86_config->num_crtc; c++) {
drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
- if (drmmode_crtc->cursor_bo)
+ if (drmmode_crtc->cursor_bo[0])
new_fb_size += (64 * 4 * 64);
}
commit 91e557f78ad261e76a1829f54722c2c0781742d2
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 18:00:09 2018 +0100
Update cursor position in drmmode_show_cursor if hotspot changed
The cursor position is updated to be consistent with the new hotspot in
the same ioctl call.
(Ported from amdgpu commit b04697de5270e8e45744a7025c24df1f454a4cf0)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c2a59da7..bec309e5 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1017,6 +1017,9 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
}
#endif
+ drmmode_crtc->cursor_x = x;
+ drmmode_crtc->cursor_y = y;
+
drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
}
@@ -1202,6 +1205,10 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ CursorPtr cursor = xf86_config->cursor;
+ int xhot = cursor->bits->xhot;
+ int yhot = cursor->bits->yhot;
static Bool use_set_cursor2 = TRUE;
struct drm_mode_cursor2 arg;
@@ -1213,41 +1220,45 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
arg.width = info->cursor_w;
arg.height = info->cursor_h;
+ if (crtc->rotation != RR_Rotate_0 &&
+ crtc->rotation != (RR_Rotate_180 | RR_Reflect_X |
+ RR_Reflect_Y)) {
+ int t;
+
+ /* Reflect & rotate hotspot position */
+ if (crtc->rotation & RR_Reflect_X)
+ xhot = info->cursor_w - xhot - 1;
+ if (crtc->rotation & RR_Reflect_Y)
+ yhot = info->cursor_h - yhot - 1;
+
+ switch (crtc->rotation & 0xf) {
+ case RR_Rotate_90:
+ t = xhot;
+ xhot = yhot;
+ yhot = info->cursor_w - t - 1;
+ break;
+ case RR_Rotate_180:
+ xhot = info->cursor_w - xhot - 1;
+ yhot = info->cursor_h - yhot - 1;
+ break;
+ case RR_Rotate_270:
+ t = xhot;
+ xhot = info->cursor_h - yhot - 1;
+ yhot = t;
+ }
+ }
+
+ if (xhot != drmmode_crtc->cursor_xhot || yhot != drmmode_crtc->cursor_yhot) {
+ arg.flags |= DRM_MODE_CURSOR_MOVE;
+ arg.x = drmmode_crtc->cursor_x += drmmode_crtc->cursor_xhot - xhot;
+ arg.y = drmmode_crtc->cursor_y += drmmode_crtc->cursor_yhot - yhot;
+ drmmode_crtc->cursor_xhot = xhot;
+ drmmode_crtc->cursor_yhot = yhot;
+ }
+
if (use_set_cursor2) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
- CursorPtr cursor = xf86_config->cursor;
- int xhot = cursor->bits->xhot;
- int yhot = cursor->bits->yhot;
int ret;
- if (crtc->rotation != RR_Rotate_0 &&
- crtc->rotation != (RR_Rotate_180 | RR_Reflect_X |
- RR_Reflect_Y)) {
- int t;
-
- /* Reflect & rotate hotspot position */
- if (crtc->rotation & RR_Reflect_X)
- xhot = info->cursor_w - xhot - 1;
- if (crtc->rotation & RR_Reflect_Y)
- yhot = info->cursor_h - yhot - 1;
-
- switch (crtc->rotation & 0xf) {
- case RR_Rotate_90:
- t = xhot;
- xhot = yhot;
- yhot = info->cursor_w - t - 1;
- break;
- case RR_Rotate_180:
- xhot = info->cursor_w - xhot - 1;
- yhot = info->cursor_h - yhot - 1;
- break;
- case RR_Rotate_270:
- t = xhot;
- xhot = info->cursor_h - yhot - 1;
- yhot = t;
- }
- }
-
arg.hot_x = xhot;
arg.hot_y = yhot;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index d7ab9d7e..49893ab0 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -87,6 +87,11 @@ typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
int hw_id;
+
+ int cursor_x;
+ int cursor_y;
+ int cursor_xhot;
+ int cursor_yhot;
struct radeon_bo *cursor_bo;
struct drmmode_scanout rotate;
struct drmmode_scanout scanout[2];
commit 92df709786830d4e30a106dd49d8e0355c50c8f0
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 17:54:36 2018 +0100
Use drmIoctl in drmmode_show_cursor
This should be functionally equivalent to what drmModeSetCursor(2) do
behind the scenes, but allows for new tricks in following changes.
(Ported from amdgpu commit b344e1559e936046ef02c777fc4f6bcefa3830bc)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index ef235bd2..c2a59da7 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1202,8 +1202,16 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
- uint32_t handle = drmmode_crtc->cursor_bo->handle;
static Bool use_set_cursor2 = TRUE;
+ struct drm_mode_cursor2 arg;
+
+ memset(&arg, 0, sizeof(arg));
+
+ arg.handle = drmmode_crtc->cursor_bo->handle;
+ arg.flags = DRM_MODE_CURSOR_BO;
+ arg.crtc_id = drmmode_crtc->mode_crtc->crtc_id;
+ arg.width = info->cursor_w;
+ arg.height = info->cursor_h;
if (use_set_cursor2) {
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
@@ -1240,18 +1248,17 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
}
}
- ret =
- drmModeSetCursor2(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
- handle, info->cursor_w, info->cursor_h,
- xhot, yhot);
+ arg.hot_x = xhot;
+ arg.hot_y = yhot;
+
+ ret = drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR2, &arg);
if (ret == -EINVAL)
use_set_cursor2 = FALSE;
else
return;
}
- drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
- info->cursor_w, info->cursor_h);
+ drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR, &arg);
}
/* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and
commit e14c3d2f86c7be2b5c3d06a47bf0abe954207d0b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 17:38:51 2018 +0100
Drop RADEONInfoRec::cursor_bo array
Not needed or even useful for anything.
(Ported from amdgpu commit e95044e45350870fa7e237860e89ade91ac03550)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 34c88c8e..ef235bd2 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2967,15 +2967,6 @@ miPointerSpriteFuncRec drmmode_sprite_funcs = {
};
-void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
-{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- xf86CrtcPtr crtc = xf86_config->crtc[id];
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-
- drmmode_crtc->cursor_bo = bo;
-}
-
void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index f5659664..d7ab9d7e 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -213,7 +213,6 @@ extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
extern void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr);
-extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo);
void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y);
extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
Bool set_hw);
diff --git a/src/radeon.h b/src/radeon.h
index cde922c6..74454c30 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -572,7 +572,6 @@ typedef struct {
struct radeon_cs_manager *csm;
struct radeon_cs *cs;
- struct radeon_bo *cursor_bo[32];
uint64_t vram_size;
uint64_t gart_size;
drmmode_rec drmmode;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index dd9955da..27a02109 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -2760,21 +2760,20 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
cursor_size = info->cursor_w * info->cursor_h * 4;
cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE);
for (c = 0; c < xf86_config->num_crtc; c++) {
- /* cursor objects */
- if (!info->cursor_bo[c]) {
- info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0,
- cursor_size, 0,
- RADEON_GEM_DOMAIN_VRAM, 0);
- if (!info->cursor_bo[c]) {
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
+
+ if (!drmmode_crtc->cursor_bo) {
+ drmmode_crtc->cursor_bo = radeon_bo_open(info->bufmgr, 0,
+ cursor_size, 0,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+ if (!(drmmode_crtc->cursor_bo)) {
ErrorF("Failed to allocate cursor buffer memory\n");
return FALSE;
}
- if (radeon_bo_map(info->cursor_bo[c], 1)) {
+ if (radeon_bo_map(drmmode_crtc->cursor_bo, 1)) {
ErrorF("Failed to map cursor buffer memory\n");
}
-
- drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]);
}
}
}
@@ -2840,7 +2839,9 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size)
int c;
for (c = 0; c < xf86_config->num_crtc; c++) {
- if (info->cursor_bo[c])
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
+
+ if (drmmode_crtc->cursor_bo)
new_fb_size += (64 * 4 * 64);
}
commit f66254c171f5a3b052a2a9e0339f17dfb5a60dc2
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 12:49:27 2018 +0100
Automatically try re-enabling TearFree after a flip failed
Specifically, after both the page flip and vblank ioctls failed, but
then the vblank ioctl started working again. This can happen
intermittently e.g. when hotplugging a DP display. Previously, TearFree
would stay disabled in that case until a modeset was triggered somehow.
Bugzilla: https://bugs.freedesktop.org/103791
(Ported from amdgpu commit bcfa6c258fdf41a9928f8a3c78fc528d0fafee25)
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index bfc13010..f5659664 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -71,6 +71,12 @@ struct drmmode_fb {
uint32_t handle;
};
+enum drmmode_scanout_status {
+ DRMMODE_SCANOUT_OK,
+ DRMMODE_SCANOUT_FLIP_FAILED = 1u << 0,
+ DRMMODE_SCANOUT_VBLANK_FAILED = 1u << 1,
+};
+
struct drmmode_scanout {
struct radeon_buffer *bo;
PixmapPtr pixmap;
@@ -90,6 +96,7 @@ typedef struct {
unsigned scanout_id;
uintptr_t scanout_update_pending;
Bool tear_free;
+ enum drmmode_scanout_status scanout_status;
PixmapPtr prime_scanout_pixmap;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 796dac5f..dd9955da 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -783,15 +783,32 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
1, drm_queue_seq, NULL, NULL)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "drmmode_wait_vblank failed for PRIME update: %s\n",
- strerror(errno));
+ if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "drmmode_wait_vblank failed for PRIME update: %s\n",
+ strerror(errno));
+ drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
+ }
+
drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd,
0, 0, 0,
(void*)drm_queue_seq);
drmmode_crtc->wait_flip_nesting_level++;
radeon_drm_queue_handle_deferred(xf86_crtc);
+ return;
+ }
+
+ if (drmmode_crtc->scanout_status ==
+ (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
+ /* The page flip and vblank ioctls failed before, but the vblank
+ * ioctl is working again, so we can try re-enabling TearFree
+ */
+ xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
+ xf86_crtc->rotation,
+ xf86_crtc->x, xf86_crtc->y);
}
+
+ drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
}
static void
@@ -842,12 +859,22 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
drmmode_crtc->flip_pending->handle,
0, drm_queue_seq, 0) != 0) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
- __func__, strerror(errno));
+ if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "flip queue failed in %s: %s, TearFree inactive\n",
+ __func__, strerror(errno));
+ drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
+ }
+
radeon_drm_abort_entry(drm_queue_seq);
return;
}
+ if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
+ drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
+ }
+
drmmode_crtc->scanout_id = scanout_id;
drmmode_crtc->scanout_update_pending = drm_queue_seq;
}
@@ -1072,15 +1099,32 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
1, drm_queue_seq, NULL, NULL)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "drmmode_wait_vblank failed for scanout update: %s\n",
- strerror(errno));
+ if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "drmmode_wait_vblank failed for scanout update: %s\n",
+ strerror(errno));
+ drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
+ }
+
drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd,
0, 0, 0,
(void*)drm_queue_seq);
drmmode_crtc->wait_flip_nesting_level++;
radeon_drm_queue_handle_deferred(xf86_crtc);
+ return;
+ }
+
+ if (drmmode_crtc->scanout_status ==
+ (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
+ /* The page flip and vblank ioctls failed before, but the vblank
+ * ioctl is working again, so we can try re-enabling TearFree
+ */
+ xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
+ xf86_crtc->rotation,
+ xf86_crtc->x, xf86_crtc->y);
}
+
+ drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
}
static void
@@ -1132,9 +1176,13 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
drmmode_crtc->flip_pending->handle,
0, drm_queue_seq, 0) != 0) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, "
- "TearFree inactive until next modeset\n",
- __func__, strerror(errno));
+ if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "flip queue failed in %s: %s, TearFree inactive\n",
+ __func__, strerror(errno));
+ drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
+ }
+
radeon_drm_abort_entry(drm_queue_seq);
RegionCopy(DamageRegion(drmmode_crtc->scanout_damage),
&drmmode_crtc->scanout_last_region);
@@ -1146,6 +1194,11 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
return;
}
+ if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
+ drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
+ }
+
drmmode_crtc->scanout_id = scanout_id;
drmmode_crtc->scanout_update_pending = drm_queue_seq;
}
commit ce7db51020d32f17e442338bfd305220feb51630
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 12:47:18 2018 +0100
Cancel pending scanout update in drmmode_crtc_scanout_update
drmmode_crtc_scanout_update does the equivalent of a scanout update,
so no need to do it again. This might also avoid issues if there's a
pending scanout update at this point.
(Ported from amdgpu commit 4e7a24ac5a64e402146953ec5850d13c05742116)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 134b0f72..34c88c8e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -781,11 +781,17 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
*fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
*x = *y = 0;
- radeon_scanout_do_update(crtc, scanout_id,
- screen->GetWindowPixmap(screen->root),
- extents);
- RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage));
- radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo);
+ if (radeon_scanout_do_update(crtc, scanout_id,
+ screen->GetWindowPixmap(screen->root),
+ extents)) {
+ RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage));
+ radeon_glamor_finish(scrn);
+
+ if (!drmmode_crtc->flip_pending) {
+ radeon_drm_abort_entry(drmmode_crtc->
+ scanout_update_pending);
+ }
+ }
}
}
commit 21d65e5b78c8889e363aee8596cd0b0f942fee46
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Dec 21 12:38:04 2018 +0100
Perform scanout buffer update immediately if drmmode_wait_vblank fails
Otherwise the damaged screen contents may never be displayed in that
case.
(Ported from amdgpu commit 500fadb16285146e91f62fce3a0ce1360ca684ba)
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index a7aade70..796dac5f 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -752,6 +752,7 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
{
ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty);
drmmode_crtc_private_ptr drmmode_crtc;
uintptr_t drm_queue_seq;
@@ -774,19 +775,23 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"radeon_drm_queue_alloc failed for PRIME update\n");
+ radeon_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL);
return;
}
+ drmmode_crtc->scanout_update_pending = drm_queue_seq;
+
if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
1, drm_queue_seq, NULL, NULL)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"drmmode_wait_vblank failed for PRIME update: %s\n",
strerror(errno));
- radeon_drm_abort_entry(drm_queue_seq);
- return;
+ drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd,
+ 0, 0, 0,
+ (void*)drm_queue_seq);
+ drmmode_crtc->wait_flip_nesting_level++;
+ radeon_drm_queue_handle_deferred(xf86_crtc);
}
-
- drmmode_crtc->scanout_update_pending = drm_queue_seq;
}
static void
@@ -1022,8 +1027,9 @@ static void
radeon_scanout_update(xf86CrtcPtr xf86_crtc)
{
drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ ScrnInfoPtr scrn = xf86_crtc->scrn;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
uintptr_t drm_queue_seq;
- ScrnInfoPtr scrn;
DamagePtr pDamage;
RegionPtr pRegion;
BoxRec extents;
@@ -1048,7 +1054,6 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
return;
}
- scrn = xf86_crtc->scrn;
drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
RADEON_DRM_QUEUE_CLIENT_DEFAULT,
RADEON_DRM_QUEUE_ID_DEFAULT,
@@ -1059,19 +1064,23 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"radeon_drm_queue_alloc failed for scanout update\n");
+ radeon_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc);
return;
}
+ drmmode_crtc->scanout_update_pending = drm_queue_seq;
+
if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
1, drm_queue_seq, NULL, NULL)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"drmmode_wait_vblank failed for scanout update: %s\n",
strerror(errno));
- radeon_drm_abort_entry(drm_queue_seq);
- return;
+ drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd,
+ 0, 0, 0,
+ (void*)drm_queue_seq);
+ drmmode_crtc->wait_flip_nesting_level++;
+ radeon_drm_queue_handle_deferred(xf86_crtc);
}
-
- drmmode_crtc->scanout_update_pending = drm_queue_seq;
}
static void
commit 64942d2c49f9fa1afcc42c07943d076a40963e51
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Dec 20 19:00:08 2018 +0100
Move deferred vblank events to separate drm_vblank_deferred list
It was still possible for nested xorg_list_for_each_entry_safe loops
to occur over the drm_vblank_signalled list, which could mess up that
list. Moving deferred events to a separate list allows processing the
drm_vblank_signalled list without xorg_list_for_each_entry_safe.
Bugzilla: https://bugs.freedesktop.org/108600
(Ported from amdgpu commit 51ba6dddee40c3688d4c7b12eabeab516ed153b7)
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index acfea3da..d8a8243c 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -56,6 +56,7 @@ static int radeon_drm_queue_refcnt;
static struct xorg_list radeon_drm_queue;
static struct xorg_list radeon_drm_flip_signalled;
static struct xorg_list radeon_drm_vblank_signalled;
+static struct xorg_list radeon_drm_vblank_deferred;
static uintptr_t radeon_drm_queue_seq;
@@ -112,6 +113,31 @@ radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
}
/*
+ * Handle signalled vblank events. If we're waiting for a flip event,
+ * put events for that CRTC in the vblank_deferred list.
+ */
+static void
+radeon_drm_handle_vblank_signalled(void)
+{
+ drmmode_crtc_private_ptr drmmode_crtc;
+ struct radeon_drm_queue_entry *e;
+
+ while (!xorg_list_is_empty(&radeon_drm_vblank_signalled)) {
+ e = xorg_list_first_entry(&radeon_drm_vblank_signalled,
+ struct radeon_drm_queue_entry, list);
+ drmmode_crtc = e->crtc->driver_private;
+
+ if (drmmode_crtc->wait_flip_nesting_level == 0) {
+ radeon_drm_queue_handle_one(e);
+ continue;
+ }
+
+ xorg_list_del(&e->list);
+ xorg_list_append(&e->list, &radeon_drm_vblank_deferred);
+ }
+}
+
+/*
* Handle deferred DRM vblank events
*
* This function must be called after radeon_drm_wait_pending_flip, once
@@ -127,12 +153,18 @@ radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc)
--drmmode_crtc->wait_flip_nesting_level > 0)
return;
- xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
- drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
+ /* Put previously deferred vblank events for this CRTC back in the
+ * signalled queue
+ */
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) {
+ if (e->crtc != crtc)
+ continue;
- if (drmmode_crtc->wait_flip_nesting_level == 0)
- radeon_drm_queue_handle_one(e);
+ xorg_list_del(&e->list);
+ xorg_list_append(&e->list, &radeon_drm_vblank_signalled);
}
+
+ radeon_drm_handle_vblank_signalled();
}
/*
@@ -205,6 +237,13 @@ radeon_drm_abort_entry(uintptr_t seq)
}
}
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) {
+ if (e->seq == seq) {
+ radeon_drm_abort_one(e);
+ return;
+ }
+ }
+
xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
if (e->seq == seq) {
radeon_drm_abort_one(e);
@@ -235,7 +274,7 @@ radeon_drm_abort_id(uint64_t id)
int
radeon_drm_handle_event(int fd, drmEventContext *event_context)
{
- struct radeon_drm_queue_entry *e, *tmp;
+ struct radeon_drm_queue_entry *e;
int r;
r = drmHandleEvent(fd, event_context);
@@ -246,12 +285,7 @@ radeon_drm_handle_event(int fd, drmEventContext *event_context)
radeon_drm_queue_handle_one(e);
}
- xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
- drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
-
- if (drmmode_crtc->wait_flip_nesting_level == 0)
- radeon_drm_queue_handle_one(e);
- }
+ radeon_drm_handle_vblank_signalled();
return r;
}
@@ -298,6 +332,7 @@ radeon_drm_queue_init(ScrnInfoPtr scrn)
xorg_list_init(&radeon_drm_queue);
xorg_list_init(&radeon_drm_flip_signalled);
xorg_list_init(&radeon_drm_vblank_signalled);
+ xorg_list_init(&radeon_drm_vblank_deferred);
}
/*
commit f450632077843a95a6ef269febbfb64a605045ed
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Dec 20 18:48:19 2018 +0100
Explicitly keep track of whether a DRM event is for a flip or not
When an async flip is performed, and TearFree is enabled on the CRTC
used for timing, we schedule a vblank event for completing the page
flip. The DRM event queuing code treated this event like a vblank event,
but it needs to be treated like a page flip event.
(Ported from amdgpu commit e2c7369cae65069aa93eed1c0b678f975ce5c274)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 831394d4..134b0f72 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -3397,7 +3397,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id,
flipdata,
drmmode_flip_handler,
- drmmode_flip_abort);
+ drmmode_flip_abort,
+ TRUE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue event entry failed.\n");
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 4d12fc09..922ed4fb 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -1076,7 +1076,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT,
wait_info, radeon_dri2_frame_event_handler,
- radeon_dri2_frame_event_abort);
+ radeon_dri2_frame_event_abort, FALSE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue event entry failed.\n");
@@ -1215,7 +1215,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT,
swap_info, radeon_dri2_frame_event_handler,
- radeon_dri2_frame_event_abort);
+ radeon_dri2_frame_event_abort, FALSE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue entry failed.\n");
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index ebc6a5b6..acfea3da 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -48,6 +48,7 @@ struct radeon_drm_queue_entry {
xf86CrtcPtr crtc;
radeon_drm_handler_proc handler;
radeon_drm_abort_proc abort;
+ Bool is_flip;
unsigned int frame;
};
@@ -86,8 +87,8 @@ radeon_drm_abort_one(struct radeon_drm_queue_entry *e)
}
static void
-radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
- unsigned int sec, unsigned int usec, void *user_ptr)
+radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *user_ptr)
{
uintptr_t seq = (uintptr_t)user_ptr;
struct radeon_drm_queue_entry *e, *tmp;
@@ -102,35 +103,15 @@ radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
xorg_list_del(&e->list);
e->usec = (uint64_t)sec * 1000000 + usec;
e->frame = frame;
- xorg_list_append(&e->list, signalled);
+ xorg_list_append(&e->list, e->is_flip ?
+ &radeon_drm_flip_signalled :
+ &radeon_drm_vblank_signalled);
break;
}
}
}
/*
- * Signal a DRM page flip event
- */
-static void
-radeon_drm_page_flip_handler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *user_ptr)
-{
- radeon_drm_queue_handler(&radeon_drm_flip_signalled, frame, sec, usec,
- user_ptr);
-}
-
-/*
- * Signal a DRM vblank event
- */
-static void
-radeon_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *user_ptr)
-{
- radeon_drm_queue_handler(&radeon_drm_vblank_signalled, frame, sec, usec,
- user_ptr);
-}
-
-/*
* Handle deferred DRM vblank events
*
* This function must be called after radeon_drm_wait_pending_flip, once
@@ -162,7 +143,8 @@ uintptr_t
radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
uint64_t id, void *data,
radeon_drm_handler_proc handler,
- radeon_drm_abort_proc abort)
+ radeon_drm_abort_proc abort,
+ Bool is_flip)
{
struct radeon_drm_queue_entry *e;
@@ -180,6 +162,7 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
e->data = data;
e->handler = handler;
e->abort = abort;
+ e->is_flip = is_flip;
xorg_list_append(&e->list, &radeon_drm_queue);
@@ -306,8 +289,8 @@ radeon_drm_queue_init(ScrnInfoPtr scrn)
drmmode_ptr drmmode = &info->drmmode;
drmmode->event_context.version = 2;
- drmmode->event_context.vblank_handler = radeon_drm_vblank_handler;
- drmmode->event_context.page_flip_handler = radeon_drm_page_flip_handler;
+ drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
+ drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
if (radeon_drm_queue_refcnt++)
return;
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
index 334c4ca6..19d42e93 100644
--- a/src/radeon_drm_queue.h
+++ b/src/radeon_drm_queue.h
@@ -44,7 +44,8 @@ void radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc);
uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
uint64_t id, void *data,
radeon_drm_handler_proc handler,
- radeon_drm_abort_proc abort);
+ radeon_drm_abort_proc abort,
+ Bool is_flip);
void radeon_drm_abort_client(ClientPtr client);
void radeon_drm_abort_entry(uintptr_t seq);
void radeon_drm_abort_id(uint64_t id);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index cd5efd53..a7aade70 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -769,7 +769,8 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
RADEON_DRM_QUEUE_CLIENT_DEFAULT,
RADEON_DRM_QUEUE_ID_DEFAULT, NULL,
radeon_prime_scanout_update_handler,
- radeon_prime_scanout_update_abort);
+ radeon_prime_scanout_update_abort,
+ FALSE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"radeon_drm_queue_alloc failed for PRIME update\n");
@@ -817,7 +818,7 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
RADEON_DRM_QUEUE_ID_DEFAULT,
NULL,
radeon_scanout_flip_handler,
- radeon_scanout_flip_abort);
+ radeon_scanout_flip_abort, TRUE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM event queue entry failed for PRIME flip.\n");
@@ -1053,7 +1054,8 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
RADEON_DRM_QUEUE_ID_DEFAULT,
drmmode_crtc,
radeon_scanout_update_handler,
- radeon_scanout_update_abort);
+ radeon_scanout_update_abort,
+ FALSE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"radeon_drm_queue_alloc failed for scanout update\n");
@@ -1102,7 +1104,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
RADEON_DRM_QUEUE_ID_DEFAULT,
NULL,
radeon_scanout_flip_handler,
- radeon_scanout_flip_abort);
+ radeon_scanout_flip_abort, TRUE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM event queue entry failed.\n");
diff --git a/src/radeon_present.c b/src/radeon_present.c
index d0a0c68c..0b55117e 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -157,7 +157,8 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
RADEON_DRM_QUEUE_CLIENT_DEFAULT,
event_id, event,
radeon_present_vblank_handler,
- radeon_present_vblank_abort);
+ radeon_present_vblank_abort,
+ FALSE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
free(event);
return BadAlloc;
commit 189b6facb3988c00c96d970f8c13ed8d58fa3998
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Dec 20 18:44:24 2018 +0100
Use drm_abort_one in drm_queue_handler
At this point, we've already established that e->handler is NULL, no
need to check again in drm_queue_handle_one. This also makes it clearer
what's happening.
(Ported from amdgpu commit eda571222f5a6be47f8897e82d85199bb9d95251)
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index ea78e8e2..ebc6a5b6 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -72,6 +72,19 @@ radeon_drm_queue_handle_one(struct radeon_drm_queue_entry *e)
free(e);
}
+/*
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+radeon_drm_abort_one(struct radeon_drm_queue_entry *e)
+{
+ xorg_list_del(&e->list);
+ e->abort(e->crtc, e->data);
+ free(e);
+}
+
static void
radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
unsigned int sec, unsigned int usec, void *user_ptr)
@@ -82,7 +95,7 @@ radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
if (e->seq == seq) {
if (!e->handler) {
- radeon_drm_queue_handle_one(e);
+ radeon_drm_abort_one(e);
break;
}
@@ -174,19 +187,6 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
}
/*
- * Abort one queued DRM entry, removing it
- * from the list, calling the abort function and
- * freeing the memory
- */
-static void
-radeon_drm_abort_one(struct radeon_drm_queue_entry *e)
-{
- xorg_list_del(&e->list);
- e->abort(e->crtc, e->data);
- free(e);
-}
-
-/*
* Abort drm queue entries for a client
*
* NOTE: This keeps the entries in the list until the DRM event arrives,
commit 06957e3067b9eb38d30b32d98a07895399f4cb36
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Dec 20 18:40:19 2018 +0100
glamor: Can work at depth >= 15 with current xserver Git master
(Ported from amdgpu commit 0734cdf544ffd3f2ac8749ad0e4bf43f8a5cea50)
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index da5a484f..8b3e5797 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -39,6 +39,8 @@ radeon_get_gbm_format(int depth, int bitsPerPixel)
case 8:
return GBM_FORMAT_R8;
#endif
+ case 15:
+ return GBM_FORMAT_ARGB1555;
case 16:
return GBM_FORMAT_RGB565;
case 32:
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index bffc89ec..f1098381 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -109,9 +109,14 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn)
"glamor may not work (well) with GPUs < RV515.\n");
}
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,99,0,0)
if (scrn->depth < 24) {
+#else
+ if (scrn->depth < 15) {
+#endif
xf86DrvMsg(scrn->scrnIndex, s ? X_ERROR : X_WARNING,
- "glamor requires depth >= 24, disabling.\n");
+ "Depth %d not supported with glamor, disabling\n",
+ scrn->depth);
return FALSE;
}
commit 99ac121770da53196124d80375a5c8edbcf827fa
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Dec 20 18:38:33 2018 +0100
Skip gamma correction of cursor data if premultiplied R/G/B > alpha
The un-premultiplied R/G/B values would overflow the gamma LUT, so just
pass through the data unchanged, and leave it up to the HW how to
interpret such weird premultiplied alpha pixels.
Bugzilla: https://bugs.freedesktop.org/108355
(Ported from amdgpu commit 13c94a373b4858a2d2aa14c22b5f98d53c84c0d9)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9a9e092a..831394d4 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1050,8 +1050,8 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height,
#endif
static Bool
-drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
- Bool apply_gamma)
+drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied,
+ Bool *apply_gamma)
{
uint32_t alpha = *argb >> 24;
uint32_t rgb[3];
@@ -1059,13 +1059,23 @@ drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
if (premultiplied) {
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0)
- if (alpha == 0 && (*argb & 0xffffff) != 0)
+ if (alpha == 0 && (*argb & 0xffffff) != 0) {
/* Doesn't look like premultiplied alpha */
+ *premultiplied = FALSE;
return FALSE;
+ }
#endif
- if (!apply_gamma)
+ if (!(*apply_gamma))
return TRUE;
+
+ if (*argb > (alpha | alpha << 8 | alpha << 16 | alpha << 24)) {
+ /* Un-premultiplied R/G/B would overflow gamma LUT,
+ * don't apply gamma correction
+ */
+ *apply_gamma = FALSE;
+ return FALSE;
+ }
}
if (!alpha) {
@@ -1083,7 +1093,7 @@ drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
rgb[i] = rgb[i] * 0xff / alpha;
}
- if (apply_gamma) {
+ if (*apply_gamma) {
rgb[0] = crtc->gamma_blue[rgb[0]] >> 8;
rgb[1] = crtc->gamma_green[rgb[1]] >> 8;
rgb[2] = crtc->gamma_red[rgb[2]] >> 8;
@@ -1128,11 +1138,10 @@ retry_transform:
cursor_h,
dstx, dsty);
argb = image[srcoffset];
- if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
- apply_gamma)) {
- premultiplied = FALSE;
+ if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied,
+ &apply_gamma))
goto retry_transform;
- }
+
ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb);
}
}
@@ -1145,11 +1154,10 @@ retry_transform:
retry:
for (i = 0; i < cursor_size; i++) {
argb = image[i];
- if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
- apply_gamma)) {
- premultiplied = FALSE;
+ if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied,
+ &apply_gamma))
goto retry;
- }
+
ptr[i] = cpu_to_le32(argb);
}
}
commit 0c40a76d1c050d018e6d59bebb5efc9c62be308c
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Dec 20 18:25:21 2018 +0100
Detect and fix up non-premultiplied cursor data
X server >= 1.18 already has code for this, but handle it with older X
servers as well.
(Ported from amdgpu commits ad6dfb0124860cf67730bde85867f81d9258c84d &
426f9a49655f01863cf4d898f525e5f95984e0c4)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 00d94449..9a9e092a 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1049,29 +1049,52 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height,
#endif
-static uint32_t
-drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb)
+static Bool
+drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
+ Bool apply_gamma)
{
- uint32_t alpha = argb >> 24;
+ uint32_t alpha = *argb >> 24;
uint32_t rgb[3];
int i;
- if (!alpha)
- return 0;
+ if (premultiplied) {
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0)
+ if (alpha == 0 && (*argb & 0xffffff) != 0)
+ /* Doesn't look like premultiplied alpha */
+ return FALSE;
+#endif
- if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
- return argb;
+ if (!apply_gamma)
+ return TRUE;
+ }
- /* Un-premultiply alpha */
+ if (!alpha) {
+ *argb = 0;
+ return TRUE;
+ }
+
+ /* Extract RGB */
for (i = 0; i < 3; i++)
- rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha;
+ rgb[i] = (*argb >> (i * 8)) & 0xff;
+
+ if (premultiplied) {
+ /* Un-premultiply alpha */
+ for (i = 0; i < 3; i++)
+ rgb[i] = rgb[i] * 0xff / alpha;
+ }
+
+ if (apply_gamma) {
+ rgb[0] = crtc->gamma_blue[rgb[0]] >> 8;
+ rgb[1] = crtc->gamma_green[rgb[1]] >> 8;
+ rgb[2] = crtc->gamma_red[rgb[2]] >> 8;
+ }
- /* Apply gamma correction and pre-multiply alpha */
- rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff;
- rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff;
- rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff;
+ /* Premultiply alpha */
+ for (i = 0; i < 3; i++)
+ rgb[i] = rgb[i] * alpha / 0xff;
- return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+ *argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+ return TRUE;
}
static void
@@ -1080,27 +1103,37 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
ScrnInfoPtr pScrn = crtc->scrn;
RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ Bool premultiplied = TRUE;
+ Bool apply_gamma = TRUE;
+ uint32_t argb;
uint32_t *ptr;
/* cursor should be mapped already */
ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
+ if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
+ apply_gamma = FALSE;
+
#if XF86_CRTC_VERSION < 7
if (crtc->driverIsPerformingTransform) {
uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h;
int dstx, dsty;
int srcoffset;
+retry_transform:
for (dsty = 0; dsty < cursor_h; dsty++) {
for (dstx = 0; dstx < cursor_w; dstx++) {
srcoffset = drmmode_cursor_src_offset(crtc->rotation,
cursor_w,
cursor_h,
dstx, dsty);
-
- ptr[dsty * info->cursor_w + dstx] =
- cpu_to_le32(drmmode_cursor_gamma(crtc,
- image[srcoffset]));
+ argb = image[srcoffset];
+ if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
+ apply_gamma)) {
+ premultiplied = FALSE;
+ goto retry_transform;
+ }
+ ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb);
}
}
} else
@@ -1109,8 +1142,16 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
uint32_t cursor_size = info->cursor_w * info->cursor_h;
int i;
- for (i = 0; i < cursor_size; i++)
- ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i]));
+retry:
+ for (i = 0; i < cursor_size; i++) {
+ argb = image[i];
+ if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
+ apply_gamma)) {
+ premultiplied = FALSE;
+ goto retry;
+ }
+ ptr[i] = cpu_to_le32(argb);
+ }
}
}
More information about the xorg-commit
mailing list