On Tue, Mar 05, 2019 at 10:24:10PM +0100, Matthieu Herrb wrote:
> On Mon, Mar 04, 2019 at 09:14:45AM +0100, Matthieu Herrb wrote:
> > On Sat, Mar 02, 2019 at 10:24:22PM +0200, Mihai Popescu wrote:
> > > Hello,
> > > 
> > > I am able to generate a segmentation fault on X with chromium help.
> > > This is happening each time I visit the web page at [1]. Basically,
> > > there is a picture of a product and whenever I hover the mouse over
> > > it, X gets a segmentation fault and exits at xenodm login prompt.
> > > Sometimes, if I repeat this procedure over and over, I get an offset
> > > for the image on my display, making things hard to see.
> > > 
> > > [1] 
> > > https://computers.woot.com/offers/lenovo-thinkcentre-m78-amd-a4-sff-desktop-1
> > > 
> > > I have inspected the web page in question with firefox, and I can tell
> > > the page loads a special image cursor when I hover on the picture in
> > > question. No segmentation fault for X this time.
> > > 
> > 
> > Hi,
> > 
> > Thanks for the bug report. Can you try the attached patch (from
> > upstream) ?
> 
> The patch below is in the most recent snapshots and Mihai reported that it
> fixes the issue for him. So if you're using the ati/radeon driver
> please test (and pay attention to possible cursor corruption...)
> 
> The relevant upstream commits are:
> https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati/commit/0c40a76d1c050d018e6d59bebb5efc9c62be308c
> 
> Detect and fix up non-premultiplied cursor data
> 
> and
> https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati/commit/99ac121770da53196124d80375a5c8edbcf827fa
> 
> Skip gamma correction of cursor data if premultiplied R/G/B > alpha
> 
> ok ?

As xf86-video-ati 19.0.0 recently released
https://lists.x.org/archives/xorg-announce/2019-March/002967.html

I'd prefer if we just went to that which includes the commits.

Index: ChangeLog
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/ChangeLog,v
retrieving revision 1.16
diff -u -p -r1.16 ChangeLog
--- ChangeLog   13 Jan 2019 07:16:48 -0000      1.16
+++ ChangeLog   7 Mar 2019 22:45:56 -0000
@@ -1,3 +1,440 @@
+commit 0d132d99e0b750896a78f47d73a8639680495d8c
+Author: Michel D??nzer <[email protected]>
+Date:   Wed Mar 6 17:48:03 2019 +0100
+
+    Bump version for 19.0.0 release
+
+commit c301b8af25d2c2cd49035a4395ebe6c3612df366
+Author: Michel D??nzer <[email protected]>
+Date:   Fri Mar 1 18:28:11 2019 +0100
+
+    dri2: Call drm_queue_handle_deferred in dri2_deferred_event
+    
+    drm_queue_handler just puts the event on the signalled list; without
+    calling drm_queue_handle_deferred, actual processing of the event may be
+    delayed indefinitely, e.g. until another event arrives from the kernel.
+    
+    This could result in DRI2 clients hanging during DPMS off.
+    
+    Fixes: ba83a866af5a "Add radeon_drm_handle_event wrapper for
+                         drmHandleEvent"
+    (Ported from amdgpu commit 09be74a3d1dd9604336d9a27f98d132b262dcbaf)
+    Reviewed-by: Alex Deucher <[email protected]>
+
+commit 705020b6247eaa062edc9c88e6ad52f8c5468051
+Author: Michel D??nzer <[email protected]>
+Date:   Fri Mar 1 18:23:30 2019 +0100
+
+    present: Check that flip and screen pixmap pitches match
+    
+    If they don't, flipping will result in corrupted display.
+    
+    Test case:
+    
+    * Run Xorg at 1920x1080 with no window manager
+    * glxgears -geometry 2048x1080
+    
+    The Present extension code in xserver 1.21 will check for this.
+    
+    (Ported from amdgpu commit a636f42b496b0604ca00a144690ece61d1a88a27)
+    Reviewed-by: Alex Deucher <[email protected]>
+
+commit 15697ee242c30b9ea6775624e8282e0171a113a7
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:27:10 2019 +0100
+
+    Keep waiting for a pending flip if drm_handle_event returns 0
+    
+    drm_wait_pending_flip stopped waiting if drm_handle_event returned 0,
+    but that might have processed only some unrelated DRM events. As long as
+    the flip is pending, we have to keep waiting for its completion event.
+    
+    Noticed while working on the previous fix.
+    
+    (Ported from amdgpu commit 9045fb310f88780e250e60b80431ca153330e61b)
+
+commit 227123de3d862e691131708b7f55260bee17f2b7
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:24:41 2019 +0100
+
+    Call drmHandleEvent again if it was interrupted by a signal
+    
+    drmHandleEvent can be interrupted by a signal in read(), in which case
+    it doesn't process any events but returns -1, which
+    drm_handle_event propagated to its callers. This could cause the
+    following failure cascade:
+    
+    1. drm_wait_pending_flip stopped waiting for a pending flip.
+    2. Its caller cleared drmmode_crtc->flip_pending before the flip
+       completed.
+    3. Another flip was attempted but got an unexpected EBUSY error because
+       the previous flip was still pending.
+    4. TearFree was disabled due to the error.
+    
+    The solution is to call drmHandleEvent if it was interrupted by a
+    signal. We can do that in drm_handle_event, because when that is called,
+    either it is known that there are events ready to be processed, or the
+    caller has to wait for events to arrive anyway.
+    
+    Bugzilla: https://bugs.freedesktop.org/109364
+    (Ported from amdgpu commit 3ff2cc225f6bc08364ee007fa54e9d0150adaf11)
+
+commit 1bfdccf7639ee2f655dc659cafa63830ba28be85
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:11:10 2019 +0100
+
+    Only update drmmode_crtc->flip_pending after actually submitting a flip
+    
+    And only clear it if it matches the framebuffer of the completed flip
+    being processed.
+    
+    Fixes
+    
+     (WW) RADEON(0): flip queue failed: Device or resource busy
+     (WW) RADEON(0): Page flip failed: Device or resource busy
+     (EE) RADEON(0): present flip failed
+    
+    due to clobbering drmmode_crtc->flip_pending.
+    
+    Reproducer: Enable TearFree, run warzone2100 fullscreen, toggle
+    Vertical sync on/off under Video Options. Discovered while investigating
+    https://bugs.freedesktop.org/109364 .
+    
+    (Ported from amdgpu commit e72a02ba1d35743fefd939458b9d8cddce86e7f5)
+
+commit dcd3527299c1f6d6faa401c565fa884f4d8f3287
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:08:35 2019 +0100
+
+    Don't allow TearFree scanout flips to complete in the same vblank period
+    
+    We were using a relative target of 0, meaning "complete the flip ASAP".
+    This could result in the flip sometimes, but not always completing in
+    the same vertical blank period where the corresponding drawing occurred,
+    potentially causing judder artifacts with applications updating their
+    window contents synchronized to the display refresh. A good way to test
+    this is the vsynctester.com site in a windowed browser, where the judder
+    results in the large "VSYNC" text intermittently appearing red or cyan
+    instead of the expected gray.
+    
+    To avoid this, use a relative target MSC of 1, meaning that if a
+    vertical blank period is in progress, the flip will only complete in the
+    next one.
+    
+    Reported by Julian Tempel and Brandon Wright in
+    https://bugs.freedesktop.org/106175 .
+    
+    (Ported from amdgpu commit a1b479c7d0066c481af920f297d6af9009dda11e)
+
+commit 274703087f80342f51fa69c935bb9a1cb0c4ae47
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:06:50 2019 +0100
+
+    glamor: Avoid glamor_create_pixmap for pixmaps backing windows
+    
+    If the compositing manager uses direct rendering (as is usually the case
+    these days), the storage of a pixmap allocated by glamor_create_pixmap
+    needs to be reallocated for sharing it with the compositing manager.
+    Instead, allocate pixmap storage which can be shared directly.
+    
+    (Ported from amdgpu commit bf326f2ea19daa6c8da23d6788ff301ae70b8e69)
+
+commit 6d1dfe2523e900517bd1e8743c87d6990a82c800
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:04:41 2019 +0100
+
+    dri2: Flush in dri2_create_buffer2 after calling glamor_set_pixmap_bo
+    
+    To make sure the client can't use the shared pixmap storage for direct
+    rendering first, which could produce garbage.
+    
+    Bugzilla: https://bugs.freedesktop.org/109235
+    (Ported from amdgpu commit ebd32b1c07208f8dbe853e089f5e4b7c6a7a658a)
+
+commit 77d7abf46446522e686c6b6f1e4857458589ef37
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Jan 28 18:00:20 2019 +0100
+
+    dri3: Flush if necessary in dri3_fd_from_pixmap
+    
+    To make sure the client can't use the shared pixmap storage for direct
+    rendering first, which could produce garbage.
+    
+    Bugzilla: https://bugs.freedesktop.org/109235
+    (Ported from amdgpu commit d168532ee739f7e33a2798051e64ba445dd3859f)
+
+commit b1c01698f577577e4a88bad0ae08fb5d998e7ebb
+Author: Michel D??nzer <[email protected]>
+Date:   Wed Jan 9 11:26:14 2019 +0100
+
+    Only call drmmode_validate_leases if RandR is enabled
+    
+    It would crash if RandR is disabled, e.g. because Xinerama is enabled.
+    
+    Bugzilla: https://bugs.freedesktop.org/109230
+    Reviewed-by: Alex Deucher <[email protected]>
+
+commit 38db1bbcfc019c92884c7819a6630c70e543f6b2
+Author: Michel D??nzer <[email protected]>
+Date:   Wed Jan 9 11:33:18 2019 +0100
+
+    Only call drmmode_uevent_init if RandR is enabled
+    
+    There's no point in listening for hotplug events if RandR is disabled,
+    as there's no other mechanism for them to be propagated. We were already
+    mostly ignoring them in that case.
+    
+    Inspired by
+    
https://gitlab.freedesktop.org/xorg/driver/xf86-video-intel/commit/1a489142c8e6a4828348cc9afbd0f430d3b1e2d8
+    (via https://bugs.freedesktop.org/109230#c11).
+    Reviewed-by: Alex Deucher <[email protected]>
+
+commit 803f872f7d4b2d80be434bb42ce64dfd295b122c
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 91e557f78ad261e76a1829f54722c2c0781742d2
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 92df709786830d4e30a106dd49d8e0355c50c8f0
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit e14c3d2f86c7be2b5c3d06a47bf0abe954207d0b
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit f66254c171f5a3b052a2a9e0339f17dfb5a60dc2
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit ce7db51020d32f17e442338bfd305220feb51630
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 21d65e5b78c8889e363aee8596cd0b0f942fee46
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 64942d2c49f9fa1afcc42c07943d076a40963e51
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit f450632077843a95a6ef269febbfb64a605045ed
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 189b6facb3988c00c96d970f8c13ed8d58fa3998
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 06957e3067b9eb38d30b32d98a07895399f4cb36
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 99ac121770da53196124d80375a5c8edbcf827fa
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 0c40a76d1c050d018e6d59bebb5efc9c62be308c
+Author: Michel D??nzer <[email protected]>
+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)
+
+commit 0058fd2ebf4c900b12f129984e98886a7ac84b2f
+Author: Mario Kleiner <[email protected]>
+Date:   Tue Dec 18 11:40:35 2018 +0100
+
+    Fix crash when page flipping in multi-X-Screen/Zaphod mode
+    
+    radeon_do_pageflip() indexed the flipdata->fb[] array
+    indexing over config->num_crtc, but the flip completion
+    routines, e.g., drmmode_flip_handler(), index that array
+    via the crtc hw id from drmmode_get_crtc_id(crtc).
+    
+    This is mismatched and causes indexing into the wrong
+    array slot at flip completion -> Server crash.
+    
+    Always use drmmode_get_crtc_id(crtc) for indexing into
+    the array to fix this.
+    
+    Tested on a dual-X-Screen setup with one video output
+    assigned to each X-Screen, page-flipping an OpenGL app
+    on either of both X-Screens. This used to crash when
+    flipping on X-Screen 1, now it doesn't anymore.
+    
+    Fixes: 740f0850f1e4 "Store FB for each CRTC in drmmode_flipdata_rec"
+    Reviewed-by: Michel D??nzer <[email protected]>
+    Signed-off-by: Mario Kleiner <[email protected]>
+
+commit b559fd83b2b026b50fe39a2b69bdc0901fd3330c
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Nov 19 11:38:22 2018 +0100
+
+    Post-release version bump
+
+commit 33cbd449b5305b8e8c0319af8becc1ab1832c101
+Author: Alan Coopersmith <[email protected]>
+Date:   Sun Nov 18 12:22:16 2018 -0800
+
+    Update README for gitlab migration
+    
+    Signed-off-by: Alan Coopersmith <[email protected]>
+
+commit 5e6fa5c17a810127f0049816f20db6b871ca77e0
+Author: Michel D??nzer <[email protected]>
+Date:   Wed Oct 24 18:22:05 2018 +0200
+
+    Allow up to six instances in Zaphod mode
+    
+    Corresponding to up to six CRTCs being available in the hardware.
+    
+    (Ported from amdgpu commit c9d43c1deb9a9cfc41a8d6439caf46d12d220853)
+
+commit c480fd066fe129fa6561fca8c09f037613b753e8
+Author: Michel D??nzer <[email protected]>
+Date:   Wed Oct 24 18:19:42 2018 +0200
+
+    Make wait_pending_flip / handle_deferred symmetric in set_mode_major
+    
+    We were always calling the latter, but not always the former, which
+    could result in handling deferred DRM events prematurely.
+    
+    (Ported from amdgpu commit 955373a3e69baa241a1f267e96d04ddb902f689f)
+
+commit 86fe8d27b9a3f043e5288ce50eaf1f5fffd24516
+Author: Michel D??nzer <[email protected]>
+Date:   Wed Oct 24 18:14:02 2018 +0200
+
+    Handle pending scanout update in drmmode_crtc_scanout_free
+    
+    We have to wait for a pending scanout flip or abort a pending scanout
+    update, otherwise the corresponding event handler will likely crash
+    after drmmode_crtc_scanout_free cleaned up the data structures.
+    
+    Fixes crash after VT switch while dedicated scanout pixmaps are enabled
+    for any CRTC.
+    
+    (Ported from amdgpu commit 0cd2c337d2c02b8ec2bd994d6124b4aaaad10741)
+
+commit f892d3791219d1041e0cbb1b866e15774004aa18
+Author: Michel D??nzer <[email protected]>
+Date:   Mon Oct 15 17:14:41 2018 +0200
+
+    dri3: Handle radeon_get_pixmap_bo returning NULL
+    
+    We were trying to already, but testing the wrong pointer.
+    
+    Fixes: b85b7b11f5b5 "Add struct radeon_buffer"
+    Bug: https://bugs.debian.org/910846
+    Reviewed-by: Alex Deucher <[email protected]>
+
 commit 80514b7b1b88f46f3965ff023035dea83b57e652
 Author: Michel D??nzer <[email protected]>
 Date:   Fri Sep 14 17:48:49 2018 +0200
Index: Makefile.am
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/Makefile.am,v
retrieving revision 1.7
diff -u -p -r1.7 Makefile.am
--- Makefile.am 20 Feb 2018 04:49:19 -0000      1.7
+++ Makefile.am 7 Mar 2019 22:45:56 -0000
@@ -31,4 +31,4 @@ INSTALL:
 ChangeLog:
        $(CHANGELOG_CMD)
 
-EXTRA_DIST = ChangeLog INSTALL
+EXTRA_DIST = ChangeLog INSTALL README.md
Index: Makefile.in
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/Makefile.in,v
retrieving revision 1.12
diff -u -p -r1.12 Makefile.in
--- Makefile.in 13 Jan 2019 07:16:48 -0000      1.12
+++ Makefile.in 7 Mar 2019 22:48:21 -0000
@@ -70,7 +70,7 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 subdir = .
-DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/config.h.in \
        $(top_srcdir)/configure COPYING ChangeLog INSTALL compile \
        config.guess config.sub depcomp install-sh ltmain.sh missing
@@ -327,7 +327,7 @@ top_srcdir = @top_srcdir@
 SUBDIRS = src man conf
 MAINTAINERCLEANFILES = ChangeLog INSTALL
 ACLOCAL_AMFLAGS = -I m4
-EXTRA_DIST = ChangeLog INSTALL
+EXTRA_DIST = ChangeLog INSTALL README.md
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
Index: README
===================================================================
RCS file: README
diff -N README
--- README      20 Feb 2018 04:49:19 -0000      1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,25 +0,0 @@
-xf86-video-ati - ATI/AMD Radeon video driver for the Xorg X server
-
-Patches and questions regarding this software should be directed at the
-amd-gfx mailing list:
-
-        https://lists.freedesktop.org/mailman/listinfo/amd-gfx
-
-Please submit bug reports to the Xorg bugzilla:
-
-        
https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon
-
-The master development code repository can be found at:
-
-        git://anongit.freedesktop.org/git/xorg/driver/xf86-video-ati
-
-        https://cgit.freedesktop.org/xorg/driver/xf86-video-ati
-
-For patch submission instructions, see:
-
-        https://www.x.org/wiki/Development/Documentation/SubmittingPatches
-
-For more information on the git code manager, see:
-
-        https://wiki.x.org/wiki/GitPage
-
Index: README.md
===================================================================
RCS file: README.md
diff -N README.md
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ README.md   7 Mar 2019 22:45:56 -0000
@@ -0,0 +1,19 @@
+xf86-video-ati - ATI/AMD Radeon video driver for the Xorg X server
+------------------------------------------------------------------
+
+Patches and questions regarding this software should be directed at the
+amd-gfx mailing list:
+
+  https://lists.freedesktop.org/mailman/listinfo/amd-gfx
+
+Please submit bug reports to the Xorg bugzilla:
+
+  
https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon
+
+The master development code repository can be found at:
+
+  https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati
+
+For patch submission instructions, see:
+
+  https://www.x.org/wiki/Development/Documentation/SubmittingPatches
Index: aclocal.m4
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/aclocal.m4,v
retrieving revision 1.21
diff -u -p -r1.21 aclocal.m4
--- aclocal.m4  13 Jan 2019 07:16:48 -0000      1.21
+++ aclocal.m4  7 Mar 2019 22:48:18 -0000
@@ -19,32 +19,63 @@ You have another version of autoconf.  I
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically 
'autoreconf'.])])
 
-# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
-# serial 1 (pkg-config-0.24)
-# 
-# Copyright ?? 2004 Scott James Remnant <[email protected]>.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# PKG_PROG_PKG_CONFIG([MIN-VERSION])
-# ----------------------------------
+dnl pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
+dnl serial 11 (pkg-config-0.29.1)
+dnl
+dnl Copyright ?? 2004 Scott James Remnant <[email protected]>.
+dnl Copyright ?? 2012-2015 Dan Nicholson <[email protected]>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl     [m4_fatal([must install pkg-config 0.29 or later before running 
autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.1])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+    [m4_fatal([pkg.m4 version $1 or higher is required but 
]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
 AC_DEFUN([PKG_PROG_PKG_CONFIG],
 [m4_pattern_forbid([^_?PKG_[A-Z_]+$])
 
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
@@ -66,18 +97,19 @@ if test -n "$PKG_CONFIG"; then
                PKG_CONFIG=""
        fi
 fi[]dnl
-])# PKG_PROG_PKG_CONFIG
+])dnl PKG_PROG_PKG_CONFIG
 
-# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-#
-# Check to see whether a particular set of modules exists.  Similar
-# to PKG_CHECK_MODULES(), but does not set variables or print errors.
-#
-# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-# only at the first occurence in configure.ac, so if the first place
-# it's called might be skipped (such as if it is within an "if", you
-# have to call PKG_CHECK_EXISTS manually
-# --------------------------------------------------------------
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
 AC_DEFUN([PKG_CHECK_EXISTS],
 [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
 if test -n "$PKG_CONFIG" && \
@@ -87,8 +119,10 @@ m4_ifvaln([$3], [else
   $3])dnl
 fi])
 
-# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
-# ---------------------------------------------
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
 m4_define([_PKG_CONFIG],
 [if test -n "$$1"; then
     pkg_cv_[]$1="$$1"
@@ -100,10 +134,11 @@ m4_define([_PKG_CONFIG],
  else
     pkg_failed=untried
 fi[]dnl
-])# _PKG_CONFIG
+])dnl _PKG_CONFIG
 
-# _PKG_SHORT_ERRORS_SUPPORTED
-# -----------------------------
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
 AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
 [AC_REQUIRE([PKG_PROG_PKG_CONFIG])
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -111,19 +146,17 @@ if $PKG_CONFIG --atleast-pkgconfig-versi
 else
         _pkg_short_errors_supported=no
 fi[]dnl
-])# _PKG_SHORT_ERRORS_SUPPORTED
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
 
 
-# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-#
-#
-# Note that if there is a possibility the first call to
-# PKG_CHECK_MODULES might not happen, you should be sure to include an
-# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
-#
-#
-# --------------------------------------------------------------
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
 AC_DEFUN([PKG_CHECK_MODULES],
 [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
 AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
@@ -177,16 +210,40 @@ else
         AC_MSG_RESULT([yes])
        $3
 fi[]dnl
-])# PKG_CHECK_MODULES
+])dnl PKG_CHECK_MODULES
 
 
-# PKG_INSTALLDIR(DIRECTORY)
-# -------------------------
-# Substitutes the variable pkgconfigdir as the location where a module
-# should install pkg-config .pc files. By default the directory is
-# $libdir/pkgconfig, but the default can be changed by passing
-# DIRECTORY. The user can override through the --with-pkgconfigdir
-# parameter.
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
 AC_DEFUN([PKG_INSTALLDIR],
 [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
 m4_pushdef([pkg_description],
@@ -197,16 +254,18 @@ AC_ARG_WITH([pkgconfigdir],
 AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
 m4_popdef([pkg_default])
 m4_popdef([pkg_description])
-]) dnl PKG_INSTALLDIR
+])dnl PKG_INSTALLDIR
 
 
-# PKG_NOARCH_INSTALLDIR(DIRECTORY)
-# -------------------------
-# Substitutes the variable noarch_pkgconfigdir as the location where a
-# module should install arch-independent pkg-config .pc files. By
-# default the directory is $datadir/pkgconfig, but the default can be
-# changed by passing DIRECTORY. The user can override through the
-# --with-noarch-pkgconfigdir parameter.
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
 AC_DEFUN([PKG_NOARCH_INSTALLDIR],
 [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
 m4_pushdef([pkg_description],
@@ -217,7 +276,7 @@ AC_ARG_WITH([noarch-pkgconfigdir],
 AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
 m4_popdef([pkg_default])
 m4_popdef([pkg_description])
-]) dnl PKG_NOARCH_INSTALLDIR
+])dnl PKG_NOARCH_INSTALLDIR
 
 
 dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
Index: configure
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/configure,v
retrieving revision 1.25
diff -u -p -r1.25 configure
--- configure   13 Jan 2019 07:16:48 -0000      1.25
+++ configure   7 Mar 2019 22:48:19 -0000
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for xf86-video-ati 18.1.0.
+# Generated by GNU Autoconf 2.69 for xf86-video-ati 19.0.0.
 #
 # Report bugs to 
<https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon>.
 #
@@ -591,8 +591,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='xf86-video-ati'
 PACKAGE_TARNAME='xf86-video-ati'
-PACKAGE_VERSION='18.1.0'
-PACKAGE_STRING='xf86-video-ati 18.1.0'
+PACKAGE_VERSION='19.0.0'
+PACKAGE_STRING='xf86-video-ati 19.0.0'
 
PACKAGE_BUGREPORT='https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon'
 PACKAGE_URL=''
 
@@ -1398,7 +1398,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures xf86-video-ati 18.1.0 to adapt to many kinds of 
systems.
+\`configure' configures xf86-video-ati 19.0.0 to adapt to many kinds of 
systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1468,7 +1468,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of xf86-video-ati 18.1.0:";;
+     short | recursive ) echo "Configuration of xf86-video-ati 19.0.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1629,7 +1629,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-xf86-video-ati configure 18.1.0
+xf86-video-ati configure 19.0.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2044,7 +2044,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by xf86-video-ati $as_me 18.1.0, which was
+It was created by xf86-video-ati $as_me 19.0.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2876,7 +2876,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='xf86-video-ati'
- VERSION='18.1.0'
+ VERSION='19.0.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -20122,7 +20122,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by xf86-video-ati $as_me 18.1.0, which was
+This file was extended by xf86-video-ati $as_me 19.0.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -20188,7 +20188,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-xf86-video-ati config.status 18.1.0
+xf86-video-ati config.status 19.0.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
Index: configure.ac
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/configure.ac,v
retrieving revision 1.18
diff -u -p -r1.18 configure.ac
--- configure.ac        13 Jan 2019 07:16:48 -0000      1.18
+++ configure.ac        7 Mar 2019 22:45:56 -0000
@@ -23,7 +23,7 @@
 # Initialize Autoconf
 AC_PREREQ([2.60])
 AC_INIT([xf86-video-ati],
-        [18.1.0],
+        [19.0.0],
         
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon],
         [xf86-video-ati])
 
Index: src/drmmode_display.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/drmmode_display.c,v
retrieving revision 1.18
diff -u -p -r1.18 drmmode_display.c
--- src/drmmode_display.c       13 Jan 2019 07:16:48 -0000      1.18
+++ src/drmmode_display.c       7 Mar 2019 22:45:56 -0000
@@ -508,8 +508,17 @@ drmmode_crtc_scanout_destroy(drmmode_ptr
 }
 
 void
-drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
+drmmode_crtc_scanout_free(xf86CrtcPtr crtc)
 {
+       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+       if (drmmode_crtc->scanout_update_pending) {
+               radeon_drm_wait_pending_flip(crtc);
+               radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
+               drmmode_crtc->scanout_update_pending = 0;
+               radeon_drm_queue_handle_deferred(crtc);
+       }
+
        drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
                                     &drmmode_crtc->scanout[0]);
        drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
@@ -772,11 +781,17 @@ drmmode_crtc_scanout_update(xf86CrtcPtr 
                *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);
+                       }
+               }
        }
 }
 
@@ -848,6 +863,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc,
        RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+       Bool handle_deferred = FALSE;
        unsigned scanout_id = 0;
        drmmode_ptr drmmode = drmmode_crtc->drmmode;
        int saved_x, saved_y;
@@ -915,6 +931,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc,
                }
 
                radeon_drm_wait_pending_flip(crtc);
+               handle_deferred = TRUE;
 
                if (!drmmode_set_mode(crtc, fb, mode, x, y))
                        goto done;
@@ -967,16 +984,16 @@ done:
                if (drmmode_crtc->scanout[scanout_id].pixmap &&
                    fb != radeon_pixmap_get_fb(drmmode_crtc->
                                               scanout[scanout_id].pixmap)) {
-                       
radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
-                       drmmode_crtc->scanout_update_pending = 0;
-                       drmmode_crtc_scanout_free(drmmode_crtc);
+                       drmmode_crtc_scanout_free(crtc);
                } else if (!drmmode_crtc->tear_free) {
                        drmmode_crtc_scanout_destroy(drmmode,
                                                     &drmmode_crtc->scanout[1]);
                }
        }
 
-       radeon_drm_queue_handle_deferred(crtc);
+       if (handle_deferred)
+               radeon_drm_queue_handle_deferred(crtc);
+
        return ret;
 }
 
@@ -1000,6 +1017,9 @@ drmmode_set_cursor_position (xf86CrtcPtr
        }
 #endif
 
+       drmmode_crtc->cursor_x = x;
+       drmmode_crtc->cursor_y = y;
+
        drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, 
y);
 }
 
@@ -1038,29 +1058,62 @@ drmmode_cursor_src_offset(Rotation rotat
 
 #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 */
+                       *premultiplied = FALSE;
+                       return FALSE;
+               }
+#endif
 
-       if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
-               return argb;
+               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;
+               }
+       }
 
-       /* 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;
 
-       /* 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;
+       if (premultiplied) {
+               /* Un-premultiply alpha */
+               for (i = 0; i < 3; i++)
+                       rgb[i] = rgb[i] * 0xff / alpha;
+       }
 
-       return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+       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;
+       }
+
+       /* Premultiply alpha */
+       for (i = 0; i < 3; i++)
+               rgb[i] = rgb[i] * alpha / 0xff;
+
+       *argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+       return TRUE;
 }
 
 static void
@@ -1069,10 +1122,21 @@ drmmode_load_cursor_argb (xf86CrtcPtr cr
        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;
 
 #if XF86_CRTC_VERSION < 7
        if (crtc->driverIsPerformingTransform) {
@@ -1080,16 +1144,19 @@ drmmode_load_cursor_argb (xf86CrtcPtr cr
                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);
+                               argb = image[srcoffset];
+                               if (!drmmode_cursor_pixel(crtc, &argb, 
&premultiplied,
+                                                         &apply_gamma))
+                                       goto retry_transform;
 
-                               ptr[dsty * info->cursor_w + dstx] =
-                                       cpu_to_le32(drmmode_cursor_gamma(crtc,
-                                                                        
image[srcoffset]));
+                               ptr[dsty * info->cursor_w + dstx] = 
cpu_to_le32(argb);
                        }
                }
        } else
@@ -1098,8 +1165,20 @@ drmmode_load_cursor_argb (xf86CrtcPtr cr
                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))
+                               goto retry;
+
+                       ptr[i] = cpu_to_le32(argb);
+               }
+       }
+
+       if (id != drmmode_crtc->cursor_id) {
+               drmmode_crtc->cursor_id = id;
+               crtc->funcs->show_cursor(crtc);
        }
 }
 
@@ -1126,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
@@ -1136,56 +1215,73 @@ 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;
+       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;
+
+       drmmode_crtc->cursor = xf86_config->cursor;
+
+       memset(&arg, 0, sizeof(arg));
+
+       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;
+       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;
 
-           ret =
-               drmModeSetCursor2(pRADEONEnt->fd, 
drmmode_crtc->mode_crtc->crtc_id,
-                                 handle, info->cursor_w, info->cursor_h,
-                                 xhot, 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
@@ -1265,7 +1361,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr c
                }
        }
 
-       drmmode_crtc_scanout_free(drmmode_crtc);
+       drmmode_crtc_scanout_free(crtc);
        drmmode_crtc->prime_scanout_pixmap = NULL;
 
        if (!ppix)
@@ -1280,7 +1376,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr c
            !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
                                         ppix->drawable.width,
                                         ppix->drawable.height)) {
-               drmmode_crtc_scanout_free(drmmode_crtc);
+               drmmode_crtc_scanout_free(crtc);
                return FALSE;
        }
 
@@ -2049,9 +2145,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, d
                        if (!RADEONZaphodStringMatches(pScrn, s, name))
                                goto out_free_encoders;
                } else {
-                       if (!info->IsSecondary && (num != 0))
-                               goto out_free_encoders;
-                       else if (info->IsSecondary && (num != 1))
+                       if (info->instance_id != num)
                                goto out_free_encoders;
                }
        }
@@ -2557,12 +2651,14 @@ drmmode_flip_handler(xf86CrtcPtr crtc, u
                flipdata->fe_usec = usec;
        }
 
-       if (drmmode_crtc->flip_pending == *fb) {
-               drmmode_fb_reference(pRADEONEnt->fd,
-                                    &drmmode_crtc->flip_pending, NULL);
+       if (*fb) {
+               if (drmmode_crtc->flip_pending == *fb) {
+                       drmmode_fb_reference(pRADEONEnt->fd,
+                                            &drmmode_crtc->flip_pending, NULL);
+               }
+               drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb);
+               drmmode_fb_reference(pRADEONEnt->fd, fb, NULL);
        }
-       drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb);
-       drmmode_fb_reference(pRADEONEnt->fd, fb, NULL);
 
        if (--flipdata->flip_count == 0) {
                /* Deliver MSC & UST from reference/current CRTC to flip event
@@ -2669,6 +2765,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn,
        int i, num_dvi = 0, num_hdmi = 0;
        drmModeResPtr mode_res;
        unsigned int crtcs_needed = 0;
+       unsigned int crtcs_got = 0;
        char *bus_id_string, *provider_name;
 
        xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
@@ -2707,16 +2804,26 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn,
        drmmode->count_crtcs = mode_res->count_crtcs;
        xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, 
mode_res->max_height);
 
-       for (i = 0; i < mode_res->count_crtcs; i++)
+       for (i = 0; i < mode_res->count_crtcs; i++) {
                if (!xf86IsEntityShared(pScrn->entityList[0]) ||
-                   (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
-                       crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, 
mode_res, i);
+                   (crtcs_got < crtcs_needed &&
+                    !(pRADEONEnt->assigned_crtcs & (1 << i))))
+                       crtcs_got += drmmode_crtc_init(pScrn, drmmode, 
mode_res, i);
+       }
 
        /* All ZaphodHeads outputs provided with matching crtcs? */
-       if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
+       if (crtcs_got < crtcs_needed) {
+               if (crtcs_got == 0) {
+                       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                                  "No ZaphodHeads CRTC available, needed %u\n",
+                                  crtcs_needed);
+                       return FALSE;
+               }
+
                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
                           "%d ZaphodHeads crtcs unavailable. Some outputs will 
stay off.\n",
                           crtcs_needed);
+       }
 
        /* workout clones */
        drmmode_clones_init(pScrn, drmmode, mode_res);
@@ -2770,6 +2877,9 @@ void drmmode_fini(ScrnInfoPtr pScrn, drm
        if (info->dri2.pKernelDRMVersion->version_minor < 4 || 
!info->drmmode_inited)
                return;
 
+       for (c = 0; c < config->num_crtc; c++)
+               drmmode_crtc_scanout_free(config->crtc[c]);
+
        if (pRADEONEnt->fd_wakeup_registered == serverGeneration &&
            !--pRADEONEnt->fd_wakeup_ref) {
 #if HAVE_NOTIFY_FD
@@ -2780,9 +2890,6 @@ void drmmode_fini(ScrnInfoPtr pScrn, drm
                                drm_wakeup_handler, pScrn);
 #endif
        }
-
-       for (c = 0; c < config->num_crtc; c++)
-               drmmode_crtc_scanout_free(config->crtc[c]->driver_private);
 }
 
 
@@ -2892,15 +2999,6 @@ miPointerSpriteFuncRec drmmode_sprite_fu
 };
 
        
-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);
@@ -3004,7 +3102,8 @@ Bool drmmode_set_desired_modes(ScrnInfoP
        }
 
        /* Validate leases on VT re-entry */
-       drmmode_validate_leases(pScrn);
+       if (dixPrivateKeyRegistered(rrPrivKey))
+           drmmode_validate_leases(pScrn);
 
        return TRUE;
 }
@@ -3159,13 +3258,14 @@ restart_destroy:
 
        /* find new output ids we don't have outputs for */
        for (i = 0; i < mode_res->count_connectors; i++) {
-               if (drmmode_find_output(pRADEONEnt->primary_scrn,
-                                       mode_res->connectors[i],
-                                       &num_dvi, &num_hdmi) ||
-                   (pRADEONEnt->secondary_scrn &&
-                    drmmode_find_output(pRADEONEnt->secondary_scrn,
-                                        mode_res->connectors[i],
-                                        &num_dvi, &num_hdmi)))
+               for (j = 0; j < pRADEONEnt->num_scrns; j++) {
+                       if (drmmode_find_output(pRADEONEnt->scrn[j],
+                                               mode_res->connectors[i],
+                                               &num_dvi, &num_hdmi))
+                               break;
+               }
+
+               if (j < pRADEONEnt->num_scrns)
                        continue;
 
                if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi,
@@ -3176,7 +3276,7 @@ restart_destroy:
        /* Check to see if a lessee has disappeared */
        drmmode_validate_leases(scrn);
 
-       if (changed && dixPrivateKeyRegistered(rrPrivKey)) {
+       if (changed) {
 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
                RRSetChanged(xf86ScrnToScreen(scrn));
 #else
@@ -3276,6 +3376,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
        xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
        xf86CrtcPtr crtc = NULL;
        drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
+       int crtc_id;
        uint32_t flip_flags = flip_sync == FLIP_ASYNC ? 
DRM_MODE_PAGE_FLIP_ASYNC : 0;
        drmmode_flipdata_ptr flipdata;
        Bool handle_deferred = FALSE;
@@ -3283,7 +3384,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
        struct drmmode_fb *fb;
        int i = 0;
 
-       flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc *
+       flipdata = calloc(1, sizeof(*flipdata) + 
drmmode_crtc->drmmode->count_crtcs *
                          sizeof(flipdata->fb[0]));
         if (!flipdata) {
              xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -3315,6 +3416,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
        for (i = 0; i < config->num_crtc; i++) {
                crtc = config->crtc[i];
                drmmode_crtc = crtc->driver_private;
+               crtc_id = drmmode_get_crtc_id(crtc);
 
                if (!drmmode_crtc_can_flip(crtc) ||
                    (drmmode_crtc->tear_free && crtc != ref_crtc))
@@ -3325,7 +3427,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
                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");
@@ -3348,9 +3451,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
                                goto next;
                        }
 
-                       drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i],
+                       drmmode_fb_reference(pRADEONEnt->fd, 
&flipdata->fb[crtc_id],
                                             
radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
-                       if (!flipdata->fb[i]) {
+                       if (!flipdata->fb[crtc_id]) {
                                ErrorF("Failed to get FB for TearFree flip\n");
                                goto error;
                        }
@@ -3366,13 +3469,13 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
                                drmmode_crtc->scanout_update_pending = 0;
                        }
                } else {
-                       drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], 
fb);
+                       drmmode_fb_reference(pRADEONEnt->fd, 
&flipdata->fb[crtc_id], fb);
                }
 
                if (crtc == ref_crtc) {
                        if (drmmode_page_flip_target_absolute(pRADEONEnt,
                                                              drmmode_crtc,
-                                                             
flipdata->fb[i]->handle,
+                                                             
flipdata->fb[crtc_id]->handle,
                                                              flip_flags,
                                                              drm_queue_seq,
                                                              target_msc) != 0)
@@ -3380,7 +3483,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
                } else {
                        if (drmmode_page_flip_target_relative(pRADEONEnt,
                                                              drmmode_crtc,
-                                                             
flipdata->fb[i]->handle,
+                                                             
flipdata->fb[crtc_id]->handle,
                                                              flip_flags,
                                                              drm_queue_seq, 0) 
!= 0)
                                goto flip_error;
@@ -3391,9 +3494,10 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn
                        drmmode_crtc->ignore_damage = TRUE;
                }
 
-       next:
                drmmode_fb_reference(pRADEONEnt->fd, 
&drmmode_crtc->flip_pending,
-                                    flipdata->fb[i]);
+                                    flipdata->fb[crtc_id]);
+
+       next:
                drm_queue_seq = 0;
        }
 
Index: src/drmmode_display.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/drmmode_display.h,v
retrieving revision 1.12
diff -u -p -r1.12 drmmode_display.h
--- src/drmmode_display.h       13 Jan 2019 07:16:48 -0000      1.12
+++ src/drmmode_display.h       7 Mar 2019 22:45:56 -0000
@@ -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;
@@ -81,7 +87,15 @@ typedef struct {
     drmmode_ptr drmmode;
     drmModeCrtcPtr mode_crtc;
     int hw_id;
-    struct radeon_bo *cursor_bo;
+
+    CursorPtr cursor;
+    int cursor_x;
+    int cursor_y;
+    int cursor_xhot;
+    int cursor_yhot;
+    unsigned cursor_id;
+    struct radeon_bo *cursor_bo[2];
+
     struct drmmode_scanout rotate;
     struct drmmode_scanout scanout[2];
     DamagePtr scanout_damage;
@@ -90,6 +104,7 @@ typedef struct {
     unsigned scanout_id;
     uintptr_t scanout_update_pending;
     Bool tear_free;
+    enum drmmode_scanout_status scanout_status;
 
     PixmapPtr prime_scanout_pixmap;
 
@@ -206,7 +221,6 @@ extern Bool drmmode_pre_init(ScrnInfoPtr
 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);
@@ -215,7 +229,7 @@ extern Bool drmmode_setup_colormap(Scree
 
 extern void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
                                         struct drmmode_scanout *scanout);
-void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc);
+void drmmode_crtc_scanout_free(xf86CrtcPtr crtc);
 PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc,
                                      struct drmmode_scanout *scanout,
                                      int width, int height);
Index: src/radeon.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon.h,v
retrieving revision 1.20
diff -u -p -r1.20 radeon.h
--- src/radeon.h        13 Jan 2019 07:16:48 -0000      1.20
+++ src/radeon.h        7 Mar 2019 22:45:56 -0000
@@ -560,7 +560,7 @@ typedef struct {
     /* Number of SW cursors currently visible on this screen */
     int sprites_visible;
 
-    Bool              IsSecondary;
+    int instance_id;
 
     Bool              r600_shadow_fb;
     void *fb_shadow;
@@ -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;
Index: src/radeon_bo_helper.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_bo_helper.c,v
retrieving revision 1.6
diff -u -p -r1.6 radeon_bo_helper.c
--- src/radeon_bo_helper.c      13 Jan 2019 07:16:48 -0000      1.6
+++ src/radeon_bo_helper.c      7 Mar 2019 22:45:56 -0000
@@ -39,6 +39,8 @@ radeon_get_gbm_format(int depth, int bit
     case 8:
        return GBM_FORMAT_R8;
 #endif
+    case 15:
+       return GBM_FORMAT_ARGB1555;
     case 16:
        return GBM_FORMAT_RGB565;
     case 32:
Index: src/radeon_dri2.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_dri2.c,v
retrieving revision 1.13
diff -u -p -r1.13 radeon_dri2.c
--- src/radeon_dri2.c   13 Jan 2019 07:16:48 -0000      1.13
+++ src/radeon_dri2.c   7 Mar 2019 22:45:56 -0000
@@ -252,6 +252,12 @@ radeon_dri2_create_buffer2(ScreenPtr pSc
     } else if (is_glamor_pixmap) {
        pixmap = radeon_glamor_set_pixmap_bo(drawable, pixmap);
        pixmap->refcnt++;
+
+       /* The copy operation from radeon_glamor_set_pixmap_bo needs to
+        * be flushed to the kernel driver before the client starts
+        * using the pixmap storage for direct rendering.
+        */
+       radeon_cs_flush_indirect(pScrn);
     }
 
     if (!radeon_get_flink_name(pRADEONEnt, pixmap, &buffers->name))
@@ -973,12 +979,18 @@ CARD32 radeon_dri2_deferred_event(OsTime
     if (ret) {
        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
                   "%s cannot get current time\n", __func__);
-       if (event_info->drm_queue_seq)
+
+       if (event_info->drm_queue_seq) {
            drmmode_crtc->drmmode->event_context.
                vblank_handler(pRADEONEnt->fd, 0, 0, 0,
                               (void*)event_info->drm_queue_seq);
-       else
+           drmmode_crtc->wait_flip_nesting_level++;
+           radeon_drm_queue_handle_deferred(crtc);
+
+       } else {
            radeon_dri2_frame_event_handler(crtc, 0, 0, data);
+       }
+
        return 0;
     }
     /*
@@ -989,13 +1001,18 @@ CARD32 radeon_dri2_deferred_event(OsTime
     delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
     delta_seq /= 1000000;
     frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq;
-    if (event_info->drm_queue_seq)
+
+    if (event_info->drm_queue_seq) {
        drmmode_crtc->drmmode->event_context.
            vblank_handler(pRADEONEnt->fd, frame, drm_now / 1000000,
                           drm_now % 1000000,
                           (void*)event_info->drm_queue_seq);
-    else
+       drmmode_crtc->wait_flip_nesting_level++;
+       radeon_drm_queue_handle_deferred(crtc);
+    } else {
        radeon_dri2_frame_event_handler(crtc, frame, drm_now, data);
+    }
+
     return 0;
 }
 
@@ -1076,7 +1093,7 @@ static int radeon_dri2_schedule_wait_msc
 
     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 +1232,7 @@ static int radeon_dri2_schedule_swap(Cli
 
     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");
Index: src/radeon_dri3.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_dri3.c,v
retrieving revision 1.4
diff -u -p -r1.4 radeon_dri3.c
--- src/radeon_dri3.c   13 Jan 2019 07:16:48 -0000      1.4
+++ src/radeon_dri3.c   7 Mar 2019 22:45:56 -0000
@@ -37,6 +37,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <gbm.h>
 #include <errno.h>
 #include <libgen.h>
 
@@ -212,20 +213,46 @@ static int radeon_dri3_fd_from_pixmap(Sc
                                      CARD16 *stride,
                                      CARD32 *size)
 {
-       struct radeon_bo *bo;
+       struct radeon_buffer *bo;
        int fd;
 #ifdef USE_GLAMOR
        ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
        RADEONInfoPtr info = RADEONPTR(scrn);
 
-       if (info->use_glamor)
-               return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+       if (info->use_glamor) {
+               Bool need_flush = TRUE;
+               int ret = -1;
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,19,99,904,0)
+               struct gbm_bo *gbm_bo = glamor_gbm_bo_from_pixmap(screen, 
pixmap);
+
+               if (gbm_bo) {
+                       ret = gbm_bo_get_fd(gbm_bo);
+                       gbm_bo_destroy(gbm_bo);
+
+                       if (ret >= 0)
+                               need_flush = FALSE;
+               }
+#endif
+
+               if (ret < 0)
+                       ret = glamor_fd_from_pixmap(screen, pixmap, stride, 
size);
+
+               /* glamor might have needed to reallocate the pixmap storage and
+                * copy the pixmap contents to the new storage. The copy
+                * operation needs to be flushed to the kernel driver before the
+                * client starts using the pixmap storage for direct rendering.
+                */
+               if (ret >= 0 && need_flush)
+                       radeon_cs_flush_indirect(scrn);
+
+               return ret;
+       }
 #endif
 
-       bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
+       bo = radeon_get_pixmap_bo(pixmap);
        if (!bo) {
                exaMoveInPixmap(pixmap);
-               bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
+               bo = radeon_get_pixmap_bo(pixmap);
                if (!bo)
                        return -1;
        }
@@ -233,11 +260,11 @@ static int radeon_dri3_fd_from_pixmap(Sc
        if (pixmap->devKind > UINT16_MAX)
                return -1;
 
-       if (radeon_gem_prime_share_bo(bo, &fd) < 0)
+       if (radeon_gem_prime_share_bo(bo->bo.radeon, &fd) < 0)
                return -1;
 
        *stride = pixmap->devKind;
-       *size = bo->size;
+       *size = bo->bo.radeon->size;
        return fd;
 }
 
Index: src/radeon_drm_queue.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_drm_queue.c,v
retrieving revision 1.4
diff -u -p -r1.4 radeon_drm_queue.c
--- src/radeon_drm_queue.c      13 Jan 2019 07:16:48 -0000      1.4
+++ src/radeon_drm_queue.c      7 Mar 2019 22:45:56 -0000
@@ -30,6 +30,8 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
+
 #include <xorg-server.h>
 #include <X11/Xdefs.h>
 #include <list.h>
@@ -48,6 +50,7 @@ struct radeon_drm_queue_entry {
     xf86CrtcPtr crtc;
     radeon_drm_handler_proc handler;
     radeon_drm_abort_proc abort;
+    Bool is_flip;
     unsigned int frame;
 };
 
@@ -55,6 +58,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;
 
 
@@ -72,9 +76,22 @@ radeon_drm_queue_handle_one(struct radeo
     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)
+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;
@@ -82,39 +99,44 @@ radeon_drm_queue_handler(struct xorg_lis
     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;
            }
 
            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
+ * 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_page_flip_handler(int fd, unsigned int frame, unsigned int sec,
-                            unsigned int usec, void *user_ptr)
+radeon_drm_handle_vblank_signalled(void)
 {
-    radeon_drm_queue_handler(&radeon_drm_flip_signalled, frame, sec, usec,
-                            user_ptr);
-}
+    drmmode_crtc_private_ptr drmmode_crtc;
+    struct radeon_drm_queue_entry *e;
 
-/*
- * 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);
+    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);
+    }
 }
 
 /*
@@ -133,12 +155,18 @@ radeon_drm_queue_handle_deferred(xf86Crt
        --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();
 }
 
 /*
@@ -149,7 +177,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;
 
@@ -167,6 +196,7 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc,
     e->data = data;
     e->handler = handler;
     e->abort = abort;
+    e->is_flip = is_flip;
 
     xorg_list_append(&e->list, &radeon_drm_queue);
 
@@ -174,19 +204,6 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc,
 }
 
 /*
- * 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,
@@ -222,6 +239,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);
@@ -252,10 +276,23 @@ 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);
+    /* Retry drmHandleEvent if it was interrupted by a signal in read() */
+    do {
+       r = drmHandleEvent(fd, event_context);
+    } while (r < 0 && (errno == EINTR || errno == EAGAIN));
+
+    if (r < 0) {
+       static Bool printed;
+
+       if (!printed) {
+           ErrorF("%s: drmHandleEvent returned %d, errno=%d (%s)\n",
+                  __func__, r, errno, strerror(errno));
+           printed = TRUE;
+       }
+    }
 
     while (!xorg_list_is_empty(&radeon_drm_flip_signalled)) {
        e = xorg_list_first_entry(&radeon_drm_flip_signalled,
@@ -263,12 +300,7 @@ radeon_drm_handle_event(int fd, drmEvent
        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;
 }
@@ -293,7 +325,7 @@ void radeon_drm_wait_pending_flip(xf86Cr
 
     while (drmmode_crtc->flip_pending
           && radeon_drm_handle_event(pRADEONEnt->fd,
-                                         
&drmmode_crtc->drmmode->event_context) > 0);
+                                     &drmmode_crtc->drmmode->event_context) >= 
0);
 }
 
 /*
@@ -306,8 +338,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;
@@ -315,6 +347,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);
 }
 
 /*
Index: src/radeon_drm_queue.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_drm_queue.h,v
retrieving revision 1.4
diff -u -p -r1.4 radeon_drm_queue.h
--- src/radeon_drm_queue.h      13 Jan 2019 07:16:48 -0000      1.4
+++ src/radeon_drm_queue.h      7 Mar 2019 22:45:56 -0000
@@ -44,7 +44,8 @@ void radeon_drm_queue_handle_deferred(xf
 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);
Index: src/radeon_glamor.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_glamor.c,v
retrieving revision 1.9
diff -u -p -r1.9 radeon_glamor.c
--- src/radeon_glamor.c 13 Jan 2019 07:16:48 -0000      1.9
+++ src/radeon_glamor.c 7 Mar 2019 22:45:56 -0000
@@ -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;
        }
 
@@ -233,7 +238,7 @@ radeon_glamor_create_pixmap(ScreenPtr sc
                if (info->shadow_primary) {
                        if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
                                return fbCreatePixmap(screen, w, h, depth, 
usage);
-               } else {
+               } else if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) {
                        pixmap = glamor_create_pixmap(screen, w, h, depth, 
usage);
                        if (pixmap)
                            return pixmap;
Index: src/radeon_kms.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_kms.c,v
retrieving revision 1.18
diff -u -p -r1.18 radeon_kms.c
--- src/radeon_kms.c    13 Jan 2019 07:16:48 -0000      1.18
+++ src/radeon_kms.c    7 Mar 2019 22:45:56 -0000
@@ -202,6 +202,10 @@ static void RADEONFreeRec(ScrnInfoPtr pS
     if (!pScrn)
        return;
 
+    pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
+    pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex);
+    pRADEONEnt = pPriv->ptr;
+
     info = RADEONPTR(pScrn);
     if (info) {
        if (info->fbcon_pixmap)
@@ -217,15 +221,12 @@ static void RADEONFreeRec(ScrnInfoPtr pS
            gbm_device_destroy(info->gbm);
 #endif
 
-       pEnt = info->pEnt;
+       pRADEONEnt->scrn[info->instance_id] = NULL;
+       pRADEONEnt->num_scrns--;
        free(pScrn->driverPrivate);
        pScrn->driverPrivate = NULL;
-    } else {
-       pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
     }
 
-    pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex);
-    pRADEONEnt = pPriv->ptr;
     if (pRADEONEnt->fd > 0) {
         DevUnion *pPriv;
         RADEONEntPtr pRADEONEnt;
@@ -348,13 +349,13 @@ static Bool RADEONCreateScreenResources_
            RROutputChanged(rrScrPriv->primaryOutput, FALSE);
            rrScrPriv->layoutChanged = TRUE;
        }
+
+       drmmode_uevent_init(pScrn, &info->drmmode);
     }
 
     if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU))
        return FALSE;
 
-    drmmode_uevent_init(pScrn, &info->drmmode);
-
     if (info->r600_shadow_fb) {
        pixmap = pScreen->GetScreenPixmap(pScreen);
 
@@ -525,10 +526,14 @@ radeon_scanout_flip_abort(xf86CrtcPtr cr
 {
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    struct drmmode_fb *fb = event_data;
 
     drmmode_crtc->scanout_update_pending = 0;
-    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
-                        NULL);
+
+    if (drmmode_crtc->flip_pending == fb) {
+       drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
+                            NULL);
+    }
 }
 
 static void
@@ -537,9 +542,9 @@ radeon_scanout_flip_handler(xf86CrtcPtr 
 {
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    struct drmmode_fb *fb = event_data;
 
-    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
-                        drmmode_crtc->flip_pending);
+    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb);
     radeon_scanout_flip_abort(crtc, event_data);
 }
 
@@ -751,6 +756,7 @@ radeon_prime_scanout_update(PixmapDirtyU
 {
     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;
@@ -768,23 +774,45 @@ radeon_prime_scanout_update(PixmapDirtyU
                                           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");
+       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);
+       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;
     }
 
-    drmmode_crtc->scanout_update_pending = drm_queue_seq;
+    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
@@ -797,52 +825,61 @@ radeon_prime_scanout_flip(PixmapDirtyUpd
     drmmode_crtc_private_ptr drmmode_crtc;
     uintptr_t drm_queue_seq;
     unsigned scanout_id;
+    struct drmmode_fb *fb;
 
     if (!crtc || !crtc->enabled)
        return;
 
     drmmode_crtc = crtc->driver_private;
+    scanout_id = drmmode_crtc->scanout_id ^ 1;
     if (drmmode_crtc->scanout_update_pending ||
-       !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
+       !drmmode_crtc->scanout[scanout_id].pixmap ||
        drmmode_crtc->dpms_mode != DPMSModeOn)
        return;
 
-    scanout_id = drmmode_crtc->scanout_id ^ 1;
     if (!radeon_prime_scanout_do_update(crtc, scanout_id))
        return;
 
+    fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
+    if (!fb) {
+       xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                  "Failed to get FB for PRIME flip.\n");
+       return;
+    }
+       
     drm_queue_seq = radeon_drm_queue_alloc(crtc,
                                           RADEON_DRM_QUEUE_CLIENT_DEFAULT,
-                                          RADEON_DRM_QUEUE_ID_DEFAULT,
-                                          NULL,
+                                          RADEON_DRM_QUEUE_ID_DEFAULT, fb,
                                           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");
        return;
     }
 
-    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
-                         
radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
-    if (!drmmode_crtc->flip_pending) {
-       xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-                  "Failed to get FB for PRIME flip.\n");
+    if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
+                                         fb->handle, 0, drm_queue_seq, 1)
+       != 0) {
+       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_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));
-       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;
+    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb);
 }
 
 static void
@@ -1020,8 +1057,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;
@@ -1046,29 +1084,50 @@ radeon_scanout_update(xf86CrtcPtr xf86_c
        return;
     }
 
-    scrn = xf86_crtc->scrn;
     drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
                                           RADEON_DRM_QUEUE_CLIENT_DEFAULT,
                                           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");
+       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);
+       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;
     }
 
-    drmmode_crtc->scanout_update_pending = drm_queue_seq;
+    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
@@ -1081,6 +1140,7 @@ radeon_scanout_flip(ScreenPtr pScreen, R
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
     uintptr_t drm_queue_seq;
     unsigned scanout_id;
+    struct drmmode_fb *fb;
 
     if (drmmode_crtc->scanout_update_pending ||
        drmmode_crtc->flip_pending ||
@@ -1096,33 +1156,34 @@ radeon_scanout_flip(ScreenPtr pScreen, R
     radeon_cs_flush_indirect(scrn);
     RegionEmpty(region);
 
+    fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
+    if (!fb) {
+       xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+              "Failed to get FB for scanout flip.\n");
+       return;
+    }
+
     drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
                                           RADEON_DRM_QUEUE_CLIENT_DEFAULT,
-                                          RADEON_DRM_QUEUE_ID_DEFAULT,
-                                          NULL,
+                                          RADEON_DRM_QUEUE_ID_DEFAULT, fb,
                                           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");
        return;
     }
 
-    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
-                         
radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
-    if (!drmmode_crtc->flip_pending) {
-       xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-                  "Failed to get FB for scanout flip.\n");
-       radeon_drm_abort_entry(drm_queue_seq);
-       return;
-    }
-
     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));
+                                         fb->handle, 0, drm_queue_seq, 1)
+       != 0) {
+       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);
@@ -1134,8 +1195,14 @@ radeon_scanout_flip(ScreenPtr pScreen, R
        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;
+    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb);
 }
 
 static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
@@ -1689,7 +1756,6 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
     RADEONInfoPtr     info;
     RADEONEntPtr pRADEONEnt;
     MessageType from;
-    DevUnion* pPriv;
     Gamma  zeros = { 0.0, 0.0, 0.0 };
     uint32_t tiling = 0;
     int cpp;
@@ -1700,10 +1766,23 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
                   "RADEONPreInit_KMS\n");
     if (pScrn->numEntities != 1) return FALSE;
+
+    pRADEONEnt = xf86GetEntityPrivate(pScrn->entityList[0],
+                                     getRADEONEntityIndex())->ptr;
+    if (pRADEONEnt->num_scrns == ARRAY_SIZE(pRADEONEnt->scrn)) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                  "Only up to %u Zaphod instances supported\n",
+                  (unsigned)ARRAY_SIZE(pRADEONEnt->scrn));
+       return FALSE;
+    }
+    
     if (!RADEONGetRec(pScrn)) return FALSE;
 
     info               = RADEONPTR(pScrn);
-    info->IsSecondary  = FALSE;
+
+    info->instance_id = pRADEONEnt->num_scrns++;
+    pRADEONEnt->scrn[info->instance_id] = pScrn;
+
     info->pEnt         = 
xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
     if (info->pEnt->location.type != BUS_PCI
 #ifdef XSERVER_PLATFORM_BUS
@@ -1712,27 +1791,11 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
         )
         return FALSE;
 
-    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
-                                getRADEONEntityIndex());
-    pRADEONEnt = pPriv->ptr;
-
-    if(xf86IsEntityShared(pScrn->entityList[0]))
-    {
-        if(xf86IsPrimInitDone(pScrn->entityList[0]))
-        {
-            info->IsSecondary = TRUE;
-        }
-        else
-        {
-            xf86SetPrimInitDone(pScrn->entityList[0]);
-        }
+    if (xf86IsEntityShared(pScrn->entityList[0]) &&
+       info->instance_id == 0) {
+       xf86SetPrimInitDone(pScrn->entityList[0]);
     }
 
-    if (info->IsSecondary)
-       pRADEONEnt->secondary_scrn = pScrn;
-    else
-       pRADEONEnt->primary_scrn = pScrn;
-
     info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
     pScrn->monitor     = pScrn->confScreen->monitor;
 
@@ -2614,7 +2677,7 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn
                                pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
                                                None, pRADEONEnt);
                        } else {
-                           drmmode_crtc_scanout_free(drmmode_crtc);
+                           drmmode_crtc_scanout_free(crtc);
                        }
                    }
                }
@@ -2694,28 +2757,29 @@ static Bool radeon_setup_kernel_mem(Scre
 
     {
        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++) {
-           /* 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]) {
-                    ErrorF("Failed to allocate cursor buffer memory\n");
-                    return FALSE;
-                }
-
-                if (radeon_bo_map(info->cursor_bo[c], 1)) {
-                    ErrorF("Failed to map cursor buffer memory\n");
-                }
+           drmmode_crtc_private_ptr drmmode_crtc = 
xf86_config->crtc[c]->driver_private;
 
-                drmmode_set_cursor(pScrn, &info->drmmode, c, 
info->cursor_bo[c]);
-            }
-        }
+           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) {
@@ -2779,7 +2843,9 @@ void radeon_kms_update_vram_limit(ScrnIn
     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[0])
            new_fb_size += (64 * 4 * 64);
     }
 
Index: src/radeon_present.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_present.c,v
retrieving revision 1.5
diff -u -p -r1.5 radeon_present.c
--- src/radeon_present.c        13 Jan 2019 07:16:48 -0000      1.5
+++ src/radeon_present.c        7 Mar 2019 22:45:56 -0000
@@ -157,7 +157,8 @@ radeon_present_queue_vblank(RRCrtcPtr cr
                                           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;
@@ -255,7 +256,7 @@ radeon_present_check_flip(RRCrtcPtr crtc
     ScrnInfoPtr scrn = xf86_crtc->scrn;
     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
     RADEONInfoPtr info = RADEONPTR(scrn);
-    PixmapPtr screen_pixmap;
+    PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
     int num_crtcs_on;
     int i;
 
@@ -271,10 +272,14 @@ radeon_present_check_flip(RRCrtcPtr crtc
     if (info->drmmode.dri2_flipping)
        return FALSE;
 
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(1, 20, 99, 1, 0)
+    if (pixmap->devKind != screen_pixmap->devKind)
+       return FALSE;
+#endif
+
     /* The kernel driver doesn't handle flipping between BOs with different
      * tiling parameters correctly yet
      */
-    screen_pixmap = screen->GetScreenPixmap(screen);
     if (radeon_present_get_pixmap_tiling_flags(info, pixmap) !=
        radeon_present_get_pixmap_tiling_flags(info, screen_pixmap))
        return FALSE;
Index: src/radeon_probe.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-ati/src/radeon_probe.h,v
retrieving revision 1.15
diff -u -p -r1.15 radeon_probe.h
--- src/radeon_probe.h  20 Feb 2018 04:49:20 -0000      1.15
+++ src/radeon_probe.h  7 Mar 2019 22:45:56 -0000
@@ -140,8 +140,8 @@ typedef struct
     unsigned long     fd_wakeup_registered; /* server generation for which fd 
has been registered for wakeup handling */
     int fd_wakeup_ref;
     unsigned int assigned_crtcs;
-    ScrnInfoPtr primary_scrn;
-    ScrnInfoPtr secondary_scrn;
+    unsigned int num_scrns;
+    ScrnInfoPtr scrn[6];
 #ifdef XSERVER_PLATFORM_BUS
     struct xf86_platform_device *platform_dev;
 #endif

Reply via email to