From c4f0a5e3d3fc40d0a80cc31ee710e05fa0cce5c5 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Fri, 8 Mar 2019 21:59:58 +0000 Subject: update to xf86-video-ati 19.0.0 fixes Xorg segfault reported by Mihai Popescu ok matthieu@ --- driver/xf86-video-ati/ChangeLog | 437 +++++++++++++++++++++++++++ driver/xf86-video-ati/Makefile.am | 2 +- driver/xf86-video-ati/Makefile.in | 4 +- driver/xf86-video-ati/README | 25 -- driver/xf86-video-ati/README.md | 19 ++ driver/xf86-video-ati/aclocal.m4 | 199 +++++++----- driver/xf86-video-ati/configure | 20 +- driver/xf86-video-ati/configure.ac | 2 +- driver/xf86-video-ati/src/drmmode_display.c | 330 +++++++++++++------- driver/xf86-video-ati/src/drmmode_display.h | 20 +- driver/xf86-video-ati/src/radeon.h | 3 +- driver/xf86-video-ati/src/radeon_bo_helper.c | 2 + driver/xf86-video-ati/src/radeon_dri2.c | 29 +- driver/xf86-video-ati/src/radeon_dri3.c | 41 ++- driver/xf86-video-ati/src/radeon_drm_queue.c | 129 +++++--- driver/xf86-video-ati/src/radeon_drm_queue.h | 3 +- driver/xf86-video-ati/src/radeon_glamor.c | 9 +- driver/xf86-video-ati/src/radeon_kms.c | 266 ++++++++++------ driver/xf86-video-ati/src/radeon_present.c | 11 +- driver/xf86-video-ati/src/radeon_probe.h | 4 +- 20 files changed, 1159 insertions(+), 396 deletions(-) delete mode 100644 driver/xf86-video-ati/README create mode 100644 driver/xf86-video-ati/README.md (limited to 'driver') diff --git a/driver/xf86-video-ati/ChangeLog b/driver/xf86-video-ati/ChangeLog index cd2393adb..5cb3fa7d1 100644 --- a/driver/xf86-video-ati/ChangeLog +++ b/driver/xf86-video-ati/ChangeLog @@ -1,3 +1,440 @@ +commit 0d132d99e0b750896a78f47d73a8639680495d8c +Author: Michel Dänzer +Date: Wed Mar 6 17:48:03 2019 +0100 + + Bump version for 19.0.0 release + +commit c301b8af25d2c2cd49035a4395ebe6c3612df366 +Author: Michel Dänzer +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 + +commit 705020b6247eaa062edc9c88e6ad52f8c5468051 +Author: Michel Dänzer +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 + +commit 15697ee242c30b9ea6775624e8282e0171a113a7 +Author: Michel Dänzer +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 +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 +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 +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 +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 +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 +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 +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 + +commit 38db1bbcfc019c92884c7819a6630c70e543f6b2 +Author: Michel Dänzer +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 + +commit 803f872f7d4b2d80be434bb42ce64dfd295b122c +Author: Michel Dänzer +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 + Signed-off-by: Mario Kleiner + +commit b559fd83b2b026b50fe39a2b69bdc0901fd3330c +Author: Michel Dänzer +Date: Mon Nov 19 11:38:22 2018 +0100 + + Post-release version bump + +commit 33cbd449b5305b8e8c0319af8becc1ab1832c101 +Author: Alan Coopersmith +Date: Sun Nov 18 12:22:16 2018 -0800 + + Update README for gitlab migration + + Signed-off-by: Alan Coopersmith + +commit 5e6fa5c17a810127f0049816f20db6b871ca77e0 +Author: Michel Dänzer +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 +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 +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 +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 + commit 80514b7b1b88f46f3965ff023035dea83b57e652 Author: Michel Dänzer Date: Fri Sep 14 17:48:49 2018 +0200 diff --git a/driver/xf86-video-ati/Makefile.am b/driver/xf86-video-ati/Makefile.am index b8d99f323..d14ed8f93 100644 --- a/driver/xf86-video-ati/Makefile.am +++ b/driver/xf86-video-ati/Makefile.am @@ -31,4 +31,4 @@ INSTALL: ChangeLog: $(CHANGELOG_CMD) -EXTRA_DIST = ChangeLog INSTALL +EXTRA_DIST = ChangeLog INSTALL README.md diff --git a/driver/xf86-video-ati/Makefile.in b/driver/xf86-video-ati/Makefile.in index 68b62d938..70eb763cf 100644 --- a/driver/xf86-video-ati/Makefile.in +++ b/driver/xf86-video-ati/Makefile.in @@ -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 diff --git a/driver/xf86-video-ati/README b/driver/xf86-video-ati/README deleted file mode 100644 index bf7c64071..000000000 --- a/driver/xf86-video-ati/README +++ /dev/null @@ -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 - diff --git a/driver/xf86-video-ati/README.md b/driver/xf86-video-ati/README.md new file mode 100644 index 000000000..7c9925c71 --- /dev/null +++ b/driver/xf86-video-ati/README.md @@ -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 diff --git a/driver/xf86-video-ati/aclocal.m4 b/driver/xf86-video-ati/aclocal.m4 index b28e34d58..f7e8099bb 100644 --- a/driver/xf86-video-ati/aclocal.m4 +++ b/driver/xf86-video-ati/aclocal.m4 @@ -19,32 +19,63 @@ You have another version of autoconf. It may work, but is not guaranteed to. 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 . -# -# 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 . +dnl Copyright © 2012-2015 Dan Nicholson +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-version 0.20; then 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, diff --git a/driver/xf86-video-ati/configure b/driver/xf86-video-ati/configure index fdf25f217..c6741fd6a 100644 --- a/driver/xf86-video-ati/configure +++ b/driver/xf86-video-ati/configure @@ -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 . # @@ -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_write_fail=1 # 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\\" diff --git a/driver/xf86-video-ati/configure.ac b/driver/xf86-video-ati/configure.ac index 5edb188cf..0763a8ed2 100644 --- a/driver/xf86-video-ati/configure.ac +++ b/driver/xf86-video-ati/configure.ac @@ -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]) diff --git a/driver/xf86-video-ati/src/drmmode_display.c b/driver/xf86-video-ati/src/drmmode_display.c index 8445ef2a7..c5fccd2aa 100644 --- a/driver/xf86-video-ati/src/drmmode_display.c +++ b/driver/xf86-video-ati/src/drmmode_display.c @@ -508,8 +508,17 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, } 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 crtc, DisplayModePtr mode, *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); *x = *y = 0; - radeon_scanout_do_update(crtc, scanout_id, - screen->GetWindowPixmap(screen->root), - extents); - RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage)); - radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo); + if (radeon_scanout_do_update(crtc, scanout_id, + screen->GetWindowPixmap(screen->root), + extents)) { + RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage)); + radeon_glamor_finish(scrn); + + if (!drmmode_crtc->flip_pending) { + radeon_drm_abort_entry(drmmode_crtc-> + scanout_update_pending); + } + } } } @@ -848,6 +863,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 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, DisplayModePtr mode, } 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 crtc, int x, int y) } #endif + drmmode_crtc->cursor_x = x; + drmmode_crtc->cursor_y = y; + drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); } @@ -1038,29 +1058,62 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height, #endif -static uint32_t -drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb) +static Bool +drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied, + Bool *apply_gamma) { - uint32_t alpha = argb >> 24; + uint32_t alpha = *argb >> 24; uint32_t rgb[3]; int i; - if (!alpha) - return 0; + if (premultiplied) { +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0) + if (alpha == 0 && (*argb & 0xffffff) != 0) { + /* Doesn't look like premultiplied alpha */ + *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; + } + } + + if (!alpha) { + *argb = 0; + return TRUE; + } - /* Un-premultiply alpha */ + /* 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; + } + + 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; + } - return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; + /* 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 crtc, CARD32 *image) ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + unsigned id = drmmode_crtc->cursor_id; + Bool premultiplied = TRUE; + Bool apply_gamma = TRUE; + uint32_t argb; uint32_t *ptr; + if (drmmode_crtc->cursor && + XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor) + id ^= 1; + /* cursor should be mapped already */ - ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); + ptr = (uint32_t *)(drmmode_crtc->cursor_bo[id]->ptr); + + if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) + apply_gamma = FALSE; #if XF86_CRTC_VERSION < 7 if (crtc->driverIsPerformingTransform) { @@ -1080,16 +1144,19 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 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 crtc, CARD32 *image) uint32_t cursor_size = info->cursor_w * info->cursor_h; int i; - for (i = 0; i < cursor_size; i++) - ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i])); +retry: + for (i = 0; i < cursor_size; i++) { + argb = image[i]; + if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, + &apply_gamma)) + 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 crtc, PixmapPtr ppix) } } - 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 crtc, PixmapPtr ppix) !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, drmmode_ptr drmmode, drmModeResPtr mode_r 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, uint32_t frame, uint64_t usec, void *even 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, drmmode_ptr drmmode, int cpp) 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_ptr drmmode, int cpp) 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, drmmode_ptr drmmode) 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, drmmode_ptr drmmode) 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_funcs = { }; -void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = xf86_config->crtc[id]; - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - - drmmode_crtc->cursor_bo = bo; -} - void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -3004,7 +3102,8 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, } /* 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, ClientPtr client, 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, ClientPtr client, 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, ClientPtr client, 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, ClientPtr client, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, flipdata, drmmode_flip_handler, - drmmode_flip_abort); + drmmode_flip_abort, + TRUE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue event entry failed.\n"); @@ -3348,9 +3451,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, 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, ClientPtr client, 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, ClientPtr client, } 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, ClientPtr client, 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; } diff --git a/driver/xf86-video-ati/src/drmmode_display.h b/driver/xf86-video-ati/src/drmmode_display.h index bc66eda65..2c2c3d57f 100644 --- a/driver/xf86-video-ati/src/drmmode_display.h +++ b/driver/xf86-video-ati/src/drmmode_display.h @@ -71,6 +71,12 @@ struct drmmode_fb { uint32_t handle; }; +enum drmmode_scanout_status { + DRMMODE_SCANOUT_OK, + DRMMODE_SCANOUT_FLIP_FAILED = 1u << 0, + DRMMODE_SCANOUT_VBLANK_FAILED = 1u << 1, +}; + struct drmmode_scanout { struct radeon_buffer *bo; PixmapPtr pixmap; @@ -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 pScrn, drmmode_ptr drmmode, int cpp); extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr); -extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo); void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y); extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw); @@ -215,7 +229,7 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn); 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); diff --git a/driver/xf86-video-ati/src/radeon.h b/driver/xf86-video-ati/src/radeon.h index b1d5f5af4..74454c307 100644 --- a/driver/xf86-video-ati/src/radeon.h +++ b/driver/xf86-video-ati/src/radeon.h @@ -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; diff --git a/driver/xf86-video-ati/src/radeon_bo_helper.c b/driver/xf86-video-ati/src/radeon_bo_helper.c index da5a484f2..8b3e57974 100644 --- a/driver/xf86-video-ati/src/radeon_bo_helper.c +++ b/driver/xf86-video-ati/src/radeon_bo_helper.c @@ -39,6 +39,8 @@ radeon_get_gbm_format(int depth, int bitsPerPixel) case 8: return GBM_FORMAT_R8; #endif + case 15: + return GBM_FORMAT_ARGB1555; case 16: return GBM_FORMAT_RGB565; case 32: diff --git a/driver/xf86-video-ati/src/radeon_dri2.c b/driver/xf86-video-ati/src/radeon_dri2.c index 4d12fc09a..a9f14e8d8 100644 --- a/driver/xf86-video-ati/src/radeon_dri2.c +++ b/driver/xf86-video-ati/src/radeon_dri2.c @@ -252,6 +252,12 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, } 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(OsTimerPtr timer, CARD32 now, pointer data) 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(OsTimerPtr timer, CARD32 now, pointer data) 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(ClientPtr client, DrawablePtr draw, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, wait_info, radeon_dri2_frame_event_handler, - radeon_dri2_frame_event_abort); + radeon_dri2_frame_event_abort, FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue event entry failed.\n"); @@ -1215,7 +1232,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, swap_info, radeon_dri2_frame_event_handler, - radeon_dri2_frame_event_abort); + radeon_dri2_frame_event_abort, FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue entry failed.\n"); diff --git a/driver/xf86-video-ati/src/radeon_dri3.c b/driver/xf86-video-ati/src/radeon_dri3.c index 7e89a2f0b..73353bf51 100644 --- a/driver/xf86-video-ati/src/radeon_dri3.c +++ b/driver/xf86-video-ati/src/radeon_dri3.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -212,20 +213,46 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen, 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(ScreenPtr screen, 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; } diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.c b/driver/xf86-video-ati/src/radeon_drm_queue.c index ea78e8e2b..fc0436058 100644 --- a/driver/xf86-video-ati/src/radeon_drm_queue.c +++ b/driver/xf86-video-ati/src/radeon_drm_queue.c @@ -30,6 +30,8 @@ #include "config.h" #endif +#include + #include #include #include @@ -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 radeon_drm_queue_entry *e) free(e); } +/* + * Abort one queued DRM entry, removing it + * from the list, calling the abort function and + * freeing the memory + */ static void -radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame, - unsigned int sec, unsigned int usec, void *user_ptr) +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(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_list *signalled, unsigned int frame, xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) { if (e->seq == seq) { if (!e->handler) { - radeon_drm_queue_handle_one(e); + radeon_drm_abort_one(e); break; } 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(xf86CrtcPtr crtc) --drmmode_crtc->wait_flip_nesting_level > 0) return; - xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) { - drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private; + /* Put previously deferred vblank events for this CRTC back in the + * signalled queue + */ + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) { + if (e->crtc != crtc) + continue; - if (drmmode_crtc->wait_flip_nesting_level == 0) - radeon_drm_queue_handle_one(e); + xorg_list_del(&e->list); + xorg_list_append(&e->list, &radeon_drm_vblank_signalled); } + + radeon_drm_handle_vblank_signalled(); } /* @@ -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,25 +196,13 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, e->data = data; e->handler = handler; e->abort = abort; + e->is_flip = is_flip; xorg_list_append(&e->list, &radeon_drm_queue); return e->seq; } -/* - * 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 * @@ -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, drmEventContext *event_context) radeon_drm_queue_handle_one(e); } - xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) { - drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private; - - if (drmmode_crtc->wait_flip_nesting_level == 0) - radeon_drm_queue_handle_one(e); - } + radeon_drm_handle_vblank_signalled(); return r; } @@ -293,7 +325,7 @@ void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc) 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); } /* diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.h b/driver/xf86-video-ati/src/radeon_drm_queue.h index 334c4ca63..19d42e930 100644 --- a/driver/xf86-video-ati/src/radeon_drm_queue.h +++ b/driver/xf86-video-ati/src/radeon_drm_queue.h @@ -44,7 +44,8 @@ void radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc); uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, uint64_t id, void *data, radeon_drm_handler_proc handler, - radeon_drm_abort_proc abort); + radeon_drm_abort_proc abort, + Bool is_flip); void radeon_drm_abort_client(ClientPtr client); void radeon_drm_abort_entry(uintptr_t seq); void radeon_drm_abort_id(uint64_t id); diff --git a/driver/xf86-video-ati/src/radeon_glamor.c b/driver/xf86-video-ati/src/radeon_glamor.c index b0da8537f..eae351fbf 100644 --- a/driver/xf86-video-ati/src/radeon_glamor.c +++ b/driver/xf86-video-ati/src/radeon_glamor.c @@ -109,9 +109,14 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn) "glamor may not work (well) with GPUs < RV515.\n"); } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,99,0,0) if (scrn->depth < 24) { +#else + if (scrn->depth < 15) { +#endif xf86DrvMsg(scrn->scrnIndex, s ? X_ERROR : X_WARNING, - "glamor requires depth >= 24, disabling.\n"); + "Depth %d not supported with glamor, disabling\n", + scrn->depth); return FALSE; } @@ -233,7 +238,7 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, 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; diff --git a/driver/xf86-video-ati/src/radeon_kms.c b/driver/xf86-video-ati/src/radeon_kms.c index ae69f3353..ff4f8dcf6 100644 --- a/driver/xf86-video-ati/src/radeon_kms.c +++ b/driver/xf86-video-ati/src/radeon_kms.c @@ -202,6 +202,10 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn) 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 pScrn) 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_KMS(ScreenPtr pScreen) 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 crtc, void *event_data) { 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 crtc, uint32_t msc, uint64_t usec, { 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(PixmapDirtyUpdatePtr dirty) { ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty); drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; @@ -768,23 +774,45 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, NULL, radeon_prime_scanout_update_handler, - radeon_prime_scanout_update_abort); + radeon_prime_scanout_update_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "radeon_drm_queue_alloc failed for PRIME update\n"); + 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(PixmapDirtyUpdatePtr ent) 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_crtc) return; } - scrn = xf86_crtc->scrn; drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, 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, RADEONInfoPtr info, 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, RADEONInfoPtr info, 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, RADEONInfoPtr info, return; } + if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; + } + drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = drm_queue_seq; + 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, int flags) 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, int flags) 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, int flags) ) 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(ScreenPtr pScreen) { int cursor_size; - int c; + int c, i; cursor_size = info->cursor_w * info->cursor_h * 4; cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE); for (c = 0; c < xf86_config->num_crtc; c++) { - /* 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_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]); - } - } + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; + + 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(ScrnInfoPtr pScrn, uint32_t new_fb_size) int c; for (c = 0; c < xf86_config->num_crtc; c++) { - if (info->cursor_bo[c]) + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; + + if (drmmode_crtc->cursor_bo[0]) new_fb_size += (64 * 4 * 64); } diff --git a/driver/xf86-video-ati/src/radeon_present.c b/driver/xf86-video-ati/src/radeon_present.c index d0a0c68ca..38a9a6b79 100644 --- a/driver/xf86-video-ati/src/radeon_present.c +++ b/driver/xf86-video-ati/src/radeon_present.c @@ -157,7 +157,8 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) RADEON_DRM_QUEUE_CLIENT_DEFAULT, event_id, event, radeon_present_vblank_handler, - radeon_present_vblank_abort); + radeon_present_vblank_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { free(event); return BadAlloc; @@ -255,7 +256,7 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, 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, WindowPtr window, PixmapPtr pixmap, 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; diff --git a/driver/xf86-video-ati/src/radeon_probe.h b/driver/xf86-video-ati/src/radeon_probe.h index be82f9aea..7cb29b916 100644 --- a/driver/xf86-video-ati/src/radeon_probe.h +++ b/driver/xf86-video-ati/src/radeon_probe.h @@ -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 -- cgit v1.2.3