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
