summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2016-04-02 07:37:35 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2016-04-02 07:37:35 +0000
commit8aa706cc566b1bdd1b34eda99aa39f03408ecc77 (patch)
tree64683856877270d249605ad5e6e726c07c887670
parent4590cb8710f56e7c1b2c5b91a079d5765dda0ece (diff)
Update to xf86-video-ati 7.6.1. ok jsg@
-rw-r--r--driver/xf86-video-ati/ChangeLog1327
-rw-r--r--driver/xf86-video-ati/config.h.in18
-rw-r--r--driver/xf86-video-ati/configure123
-rw-r--r--driver/xf86-video-ati/configure.ac53
-rw-r--r--driver/xf86-video-ati/man/radeon.man28
-rw-r--r--driver/xf86-video-ati/src/Makefile.am10
-rw-r--r--driver/xf86-video-ati/src/Makefile.in33
-rw-r--r--driver/xf86-video-ati/src/ati_pciids_gen.h2
-rw-r--r--driver/xf86-video-ati/src/drmmode_display.c1023
-rw-r--r--driver/xf86-video-ati/src/drmmode_display.h46
-rw-r--r--driver/xf86-video-ati/src/evergreen_accel.c2
-rw-r--r--driver/xf86-video-ati/src/pcidb/ati_pciids.csv2
-rw-r--r--driver/xf86-video-ati/src/radeon.h107
-rw-r--r--driver/xf86-video-ati/src/radeon_accel.c1
-rw-r--r--driver/xf86-video-ati/src/radeon_bo_helper.c135
-rw-r--r--driver/xf86-video-ati/src/radeon_bo_helper.h6
-rw-r--r--driver/xf86-video-ati/src/radeon_chipinfo_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_chipset_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_dri2.c709
-rw-r--r--driver/xf86-video-ati/src/radeon_dri2.h37
-rw-r--r--driver/xf86-video-ati/src/radeon_dri3.c215
-rw-r--r--driver/xf86-video-ati/src/radeon_drm_queue.c181
-rw-r--r--driver/xf86-video-ati/src/radeon_drm_queue.h56
-rw-r--r--driver/xf86-video-ati/src/radeon_exa.c1
-rw-r--r--driver/xf86-video-ati/src/radeon_glamor.c121
-rw-r--r--driver/xf86-video-ati/src/radeon_glamor.h71
-rw-r--r--driver/xf86-video-ati/src/radeon_glamor_wrappers.c994
-rw-r--r--driver/xf86-video-ati/src/radeon_kms.c396
-rw-r--r--driver/xf86-video-ati/src/radeon_list.h39
-rw-r--r--driver/xf86-video-ati/src/radeon_pci_chipset_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_pci_device_match_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_present.c465
-rw-r--r--driver/xf86-video-ati/src/radeon_probe.c11
-rw-r--r--driver/xf86-video-ati/src/radeon_probe.h5
-rw-r--r--driver/xf86-video-ati/src/radeon_sync.c145
-rw-r--r--driver/xf86-video-ati/src/radeon_video.c63
-rw-r--r--driver/xf86-video-ati/src/radeon_video.h1
37 files changed, 5489 insertions, 945 deletions
diff --git a/driver/xf86-video-ati/ChangeLog b/driver/xf86-video-ati/ChangeLog
index a45a8d809..3aa14d6e1 100644
--- a/driver/xf86-video-ati/ChangeLog
+++ b/driver/xf86-video-ati/ChangeLog
@@ -1,3 +1,1330 @@
+commit 99cb8c3faf1a4ce368b7500f17a2a7868c15e8e8
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Nov 12 13:38:14 2015 +0900
+
+ Set version for 7.6.1 release
+
+commit 4a2114a717ec8d78cacd8fe158e132d62013faac
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Nov 12 13:32:25 2015 +0900
+
+ Remove duplicate free(output_ids) call
+
+ Fixes double-free regression introduced by commit 875ad48e ("Simplify
+ drmmode_set_mode_major() and avoid leaking memory.").
+
+commit 960a9f37096b53ec9603a99c7b1f3679f915e03f
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Nov 12 13:20:18 2015 +0900
+
+ Post 7.6.0 release version bump
+
+commit 9aae4b71fb402841439e3267fcb7f410d8429c3a
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Nov 12 11:56:48 2015 +0900
+
+ Bump version for 7.6.0 release
+
+commit 98291869ac4a542a0b478920586407ff9d2c8ef0
+Author: Tom St Denis <tom.stdenis@amd.com>
+Date: Wed Nov 11 16:01:41 2015 +0900
+
+ Clean up radeon_dri2_create_buffer2()
+
+ Remove the depth_pixmap variable from the function and clear
+ out any dead/odd behaviour that results.
+
+ Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
+ (ported from amdgpu commit 6000aef4e2f0a121b94023484406fb6f04688f74)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit c6fc7e309a8a922f94a1f5f3e8bfb9058cff7ad1
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Nov 11 15:59:06 2015 +0900
+
+ Properly handle drmModeAddFB failure in drmmode_crtc_scanout_allocate
+
+ We were printing an error message, but not propagating the failure. That
+ would probably lead to trouble down the road.
+
+ (ported from amdgpu commit 21e72fb2418b5cc7fc849a9cf951186e209036b0)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 4e4f4d53da0539ef9feb8766230a6e9927ae005b
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Nov 11 15:57:21 2015 +0900
+
+ Eliminate redundant data parameter from drmmode_crtc_scanout_create
+
+ drmmode_crtc_scanout_create just needs to call
+ drmmode_crtc_scanout_allocate when scanout->bo is NULL.
+
+ This makes it clearer to the reader / compiler that
+ drmmode_crtc_scanout_create doesn't dereference scanout->bo when it's
+ NULL.
+
+ (ported from amdgpu commit 8da1d0c870e1081d77925807d6e3bbc61a23f54f)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 421a7e797bdd58d83e81af7a6512cc715a3df514
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Nov 11 15:51:58 2015 +0900
+
+ Don't advertise rotation support without hardware acceleration v2
+
+ Rotation currently doesn't work without acceleration (doesn't actually
+ rotate with Option "NoAccel", crashes with Option "AccelMethod" "none"
+ or when glamor fails to initialize) and would probably be too slow
+ anyway.
+
+ v2: Also remove now dead code checking for ShadowFB from
+ drmmode_crtc_scanout_allocate().
+
+ (ported from amdgpu commit dc40582d5ff94d812cbc08f95cf14b80cd0f410d)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 875ad48e7b5cdb7beefbf18dddcbee3ed22b5446
+Author: Tom St Denis <tom.stdenis@amd.com>
+Date: Wed Nov 11 15:51:19 2015 +0900
+
+ Simplify drmmode_set_mode_major() and avoid leaking memory.
+
+ The function would leak the memory allocated for output_ids. This
+ patch addresses that as well as simplifies the logic somewhat.
+
+ Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
+ (ported from amdgpu commit 460560502a1bdf26d06f3c30df46fa9f28ffb9e5)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 789d7d6a04cca6b36fb088a074027807ccb8dd61
+Author: Tom St Denis <tom.stdenis@amd.com>
+Date: Wed Nov 11 15:48:51 2015 +0900
+
+ Clean up allocation in RADEONInitVideo()
+
+ The allocation of the adapters should use the correct sizeof (even if
+ allocating an array of pointers).
+
+ Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
+ (ported from amdgpu commit db3bb2061b9ac16b0922d9afae99874820356a04)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit d88fa0dd5d37604de8efb05853738cfaca6a3166
+Author: Tom St Denis <tom.stdenis@amd.com>
+Date: Wed Nov 11 15:46:50 2015 +0900
+
+ Simplify pick best crtc to fold two loops into one
+
+ This patch folds the two for loops from radeon_pick_best_crtc() into
+ one to reduce the LOC and make the routine easier to read.
+
+ Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
+ (ported from amdgpu commit 3055724aef76a624718f26d5f0f9e9d567ffbcfb)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit dbbcd75b3c80aba77673904d46bca97779fd8a8d
+Author: Tom St Denis <tom.stdenis@amd.com>
+Date: Wed Nov 11 12:54:54 2015 +0900
+
+ dri2: Avoid calculation with undefined msc value
+
+ If the get_msc() call fails for any reason we should avoid updating the
+ vblank counter delta with undefined data.
+
+ Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
+ Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> (minor fixups)
+ (ported from amdgpu commit 8823c3d4c6db70cff7699b31088f2d92db8faaf4)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 7186a8713ba004de4991f21c1a9fc4abc62aeff4
+Author: Stephen Chandler Paul <cpaul@redhat.com>
+Date: Fri Oct 23 09:59:36 2015 -0400
+
+ Handle failures in setting a CRTC to a DRM mode properly
+
+ This fixes a bug where running the card out of PPLL's when hotplugging
+ another monitor would result in all of the displays going blank and
+ failing to work properly until X was restarted or the user switched to
+ another VT.
+
+ [Michel Dänzer: Pass errno instead of -ret to strerror()]
+
+ Signed-off-by: Stephen Chandler Paul <cpaul@redhat.com>
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+commit 548e97b3b7d1e94075a54ca2bb4eb683025098a7
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri Oct 16 16:26:58 2015 +0900
+
+ Call xf86CrtcRotate from initial drmmode_set_desired_modes call
+
+ Fixes various problems when rotation is specified in xorg.conf.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92475
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit ce9914af8d8d5243977023ec7b09c605f9cca8b4
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri Oct 2 18:07:18 2015 +0900
+
+ Only align screen / scanout pixmap height where necessary
+
+ When using glamor acceleration, the pixmap's header has to have a height
+ that matches exactly what the actual height is minus the GPU memory
+ alignment. Otherwise CRTCs scanning out from the main scanout buffer
+ (e.g. every CRTC that isn't rotated or transformed in some way) won't
+ always work. This results in a bug where rotating one monitor in a
+ multi-monitor setup won't always work properly. Easiest way to reproduce
+ this:
+
+ - Have two monitors (I've gotten this working with a 1920x1080 and
+ 1280x1024, along with two 1920x1080s)
+ - Rotate one of them from 0° to 90°, then rotate the same monitor from
+ 90° to 180°. The monitor that hasn't been rotated won't properly
+ update, and will stay on a blank screen
+
+ This doesn't seem to make any difference when using EXA for
+ acceleration.
+
+ Compared to Stephen Chandler's patch, this drops the height alignment
+ in most places and only keeps it where it's really necessary.
+
+ Reported-and-Tested-by: Stephen Chandler Paul <cpaul@redhat.com>
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 0288a4b87b65ba54f37fbeeea3cb32238deee92e
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Aug 19 16:54:14 2015 +0900
+
+ DRI2: Keep MSC monotonic when moving window between CRTCs
+
+ This mirrors the DRI3 implementation in xserver. Fixes VDPAU video
+ playback hanging when moving the window between CRTCs.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66384
+
+ (Ported from amdgpu commit 63948ea091a9b324327ade7ec4fc5d67ca7e6f6f)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 1d886b526dc49f32dc6744b7a882894bdac4e846
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Aug 19 18:11:45 2015 +0900
+
+ DRI2: Don't ignore rotated CRTCs in amdgpu_dri2_drawable_crtc
+
+ Waiting for vblank interrupts works fine with rotated CRTCs. The only
+ case we can't handle with rotation is page flipping, which is handled
+ in can_exchange().
+
+ This fixes gnome-shell hanging on rotation, probably because
+ amdgpu_dri2_get_msc returned MSC/UST 0 for rotated CRTCs.
+
+ (Ported from amdgpu commit 7b3212e33cd36fb6f122774df27b56ec4e1a22b8)
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 270da55340766074cabff8af4258e29fe2f0fc81
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date: Mon Aug 10 15:32:34 2015 -0400
+
+ add new OLAND pci id
+
+ Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit f123096877f0a0044f3d0315285441f2b5790c29
+Author: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Mon Aug 10 23:34:39 2015 +0200
+
+ Make selection between DRI2 and DRI3 consistent with other drivers. (v2)
+
+ Add Option "DRI" to allow selection of maximum DRI level.
+
+ This allows the user to select the maximum level of DRI
+ implementation to use, DRI2 or DRI3. It replaces the old
+ option "DRI3" which had exactly the same purpose, but
+ differs from the method used in both intel ddx and nouveau ddx.
+ Make this consistent before a new stable driver is released.
+
+ v2: Retain handling of old Option "DRI3" for backwards
+ compatibility, but Option "DRI" will take precedence
+ over "DRI3" if both are provided.
+
+ Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+commit 3791fceabf2cb037467dc41c15364e9f9ec1e47e
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Aug 6 16:27:01 2015 +0900
+
+ Wait for scanout BO initialization to finish before setting mode
+
+ This should avoid intermittent artifacts which could sometimes be visible
+ when setting a new scanout pixmap, e.g. on server startup or when
+ changing resolutions.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 4e3dfa69e4630df2e0ec0f5b81d61159757c4664
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Aug 6 16:16:38 2015 +0900
+
+ Only call drmmode_copy_fb (at most) once on server startup
+
+ It doesn't make sense to copy the screen contents from console when VT
+ switching back to Xorg or when Xorg resets.
+
+ Fixes intermittent artifacts when VT switching back from console to the
+ gdm login screen.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 09c7cdb923965f9a1ea11d2f449bc02114408938
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Jul 30 15:58:54 2015 +0900
+
+ glamor: Move declaration of struct radeon_pixmap out of #if/#else blocks
+
+ Reviewed-by: Dave Airlie <airlied@redhat.com>
+
+commit 936582fde0db461c5c3d78ce4f5f4c93a88a489d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Jul 30 15:56:36 2015 +0900
+
+ Remove unused local variable pRADEONEnt
+
+ ../../src/radeon_probe.c: In function 'radeon_get_scrninfo':
+ ../../src/radeon_probe.c:157:22: warning: variable 'pRADEONEnt' set but not used [-Wunused-but-set-variable]
+ RADEONEntPtr pRADEONEnt;
+ ^
+
+ Reviewed-by: Dave Airlie <airlied@redhat.com>
+
+commit 5510cd6027d2387efdf33575e3bfc424cb11bfd8
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Jul 27 09:22:57 2015 +1000
+
+ radeon: move radeon_pixmap forward declaration into other block
+
+ There is already a radeon_pixmap forward decl here, the #else
+ block is missing one.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit b32a0a3de84a44b9af4f1ca8be19f10d7fa31b12
+Author: Dave Airlie <airlied@redhat.com>
+Date: Wed Jul 22 13:35:07 2015 +1000
+
+ radeon: cleanup the entity rec
+
+ Some of these were set, some of them were
+ always opposites, so clean things up.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit fcb32231a38f9461d12720cbf72f63502197a711
+Author: Emil Velikov <emil.l.velikov@gmail.com>
+Date: Tue Jul 21 23:55:20 2015 +0100
+
+ Do not link radeon_drv.so against libpciaccess
+
+ It's only used/needed by ati_drv.so
+
+ Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+commit b6d871bf299c7d0f106c07ee4d8bd3b2337f53cc
+Author: Dave Airlie <airlied@gmail.com>
+Date: Thu Jul 9 19:25:36 2015 +1000
+
+ radeon: adopt for new X server dirty tracking APIs.
+
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit 95f5d09e3667ded027ae648c97eb4737d8bf67c5
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu May 28 11:24:42 2015 +0900
+
+ present: Handle DPMS off in radeon_present_get_ust_msc
+
+ The DRM_IOCTL_WAIT_VBLANK ioctl may return an error during DPMS off,
+ which would trigger an error message in drmmode_crtc_get_ust_msc.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 211862b777d0be251a4662f5dd24f2d400544c09
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri May 1 18:20:01 2015 +0900
+
+ present: Look at all CRTCs to determine if we can flip
+
+ Inspired by modesetting driver change by Kenneth Graunke.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 802d33e474a82262d9cdf11b03568b0c4929cd0d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri May 1 18:54:16 2015 +0900
+
+ present: Fall back to modeset for unflip operation
+
+ It's not always possible to use the page flip ioctl for this, e.g.
+ during DPMS off. We were previously just skipping the unflip in that
+ case, which could result in hangs when setting DPMS off while a
+ fullscreen Present app is running, e.g. at the GNOME3 lock screen.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit a8ed62010d5012dfb27773595c446b217f3c00c5
+Author: Piotr Redlewski <predlewski@gmail.com>
+Date: Mon Jul 6 19:57:07 2015 +0200
+
+ Do not try to enable already enabled CRTCs in DPMS hook
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91227
+
+ Signed-off-by: Piotr Redlewski <predlewski@gmail.com>
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+commit fc07c370dac4649511eb7322d05a61605a539f39
+Author: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Sun Jun 28 02:45:58 2015 +0200
+
+ Fix inconsistent default eg_tile_split in evergreen_accel.c
+
+ eg_tile_split() maps the default: switch-case to tile split
+ flag 6, like for a tile split size of 4096 Bytes. All other
+ instances of tile split mappings or reverse mappings in both
+ the ddx and in Mesa's radeon gallium drivers assign the default:
+ case to tile split flag 4, consistent with a default of 1024
+ Bytes.
+
+ Make this one outlier consistent with other instances of
+ mappings in the code to avoid surprises.
+
+ Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit ddaba449e8d6fe9fc0d97085e4045843fd8d7af9
+Author: Piotr Redlewski <predlewski@gmail.com>
+Date: Wed Jun 24 18:44:39 2015 +0200
+
+ Disable CRTCs when disabling the outputs
+
+ When turning the outputs off (DPMSModeOff), CRTCs stayed enabled. This led
+ to higher gpu temperatures than with fglrx driver.
+
+ v2: when entering DPMS also disable active CRTCs
+ v3: use drmmode_set_mode_major() for enabling CRTCs when leaving DPMS
+
+ Signed-off-by: Piotr Redlewski <predlewski@gmail.com>
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+commit acc11877423ecd81a6e0a7f38466f80e43efee20
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Jun 16 17:34:57 2015 +0900
+
+ Skip disabled CRTCs in radeon_scanout_(do_)update
+
+ The vblank / page flip ioctls don't work as expected for a disabled CRTC.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit fc9fadaebbc8aead6e030d93a9ccd84561f8f59e
+Author: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Mon Jun 22 00:09:17 2015 +0200
+
+ Don't set TILE_SPLIT flags if surface.tile_split == 0.
+
+ On pre-Evergreen hw, libdrm's r6_surface_best() helper
+ for the surface managers radeon_surface_best() routine
+ is a no-op and therefore doesn't assign any tile_split
+ settings to created surfaces, so it leaves
+ surface.tile_split on its "undefined" value of 0.
+
+ Mesa's DRI3/Present backend creates DRI3 Pixmaps via
+ the DRIImage extension and the radeon gallium driver
+ implementation of that extension uses the libdrm
+ surface manager for backing bo creation and treats
+ an undefined surface.tile_split==0, as returned by
+ the surface manager for pre-evergreen, as a signal
+ to not assign any tile_split flags to the DRI3 Pixmaps
+ bo.
+
+ The ddx also uses libdrm surface manager to create the
+ x-screen pixmap, but so far treated the returned undefined
+ surface.tile_split==0 by mapping it to eg_tile_split()'s
+ default tile_split flags, which are different from Mesa's
+ tiling flags for DRI3 pixmaps. Under DRI3/Present this
+ causes a mismatch of src pixmap and destination root
+ pixmaps tiling flags and thereby prevents page flipping
+ for pixmap presents.
+
+ Change the ddx code to treat surface.tile_split==0 the
+ same way as the radeon gallium driver to avoid mismatched
+ tiling flags and thereby allow DRI3/Present page-flip to
+ work on pre-Evergreen hw.
+
+ Tested on RV730 and Evergreen "Juniper".
+
+ Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit 49f5b0bc301414df049e00d226034e3d6e56421b
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri May 1 19:02:36 2015 +0900
+
+ Don't attempt a DRI2/Present page flip while the other one is flipping
+
+ Fixes corrupted display and hangs when switching between DRI2 and DRI3
+ fullscreen apps, e.g. a compositor using DRI3 and a fullscreen app using
+ DRI2 or vice versa.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit afab7839fc15722dbaa7203d00fe7f6ce5336b9d
+Author: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Wed Jun 10 20:55:08 2015 +0200
+
+ Allow/Fix use of multiple ZaphodHead outputs per x-screen. (v2)
+
+ Defining multiple ZaphodHead outputs per x-screen in a
+ multiple x-screen's per gpu configuration caused all
+ outputs except one per x-screen to go dark, because
+ there was a fixed mapping x-screen number -> crtc number,
+ limiting the number of crtc's per x-screen to one.
+
+ On a ZaphodHead's setup, be more clever and assign
+ as many crtc's to a given x-screen as there are
+ ZaphodHeads defined for that screen, assuming
+ there are enough unused crtc's available.
+
+ Tested on a triple display setup with different combos
+ of one, two or three ZaphodHeads per one, two or three
+ x-screens.
+
+ This is a port of similar code from xf86-video-nouveau.
+
+ v2: Implement suggestions by Michel Dänzer: Less verbose
+ debug output, more clear warning message on crtc allocation
+ failure. Move clearing of per gpu assigned_crtc mask to
+ CloseScreen, indeed testing shows no need for the more
+ complex new server generation check from v1.
+
+ Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+ (v1) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+commit d7c82731a8bf3d381bc571b94d80d9bb2dd6e40d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu May 21 16:01:16 2015 +0900
+
+ DRI2: Fix handling of drmmode_crtc_get_ust_msc return code
+
+ Fixes regression introduced in commit
+ 76c2923ac5c7230a8b2f9f8329c308d28b44d9c0 ("DRI2: Split out helper for
+ getting UST and MSC of a specific CRTC").
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit e58fc380ccf2a581d28f041fd74b963626ca5404
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu May 28 10:59:22 2015 +0900
+
+ glamor: Only wait for GPU writes in radeon_glamor_prepare_access_cpu_ro
+
+ We don't need to wait for GPU reads to finish before reading with the
+ CPU.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 5f82a720374c9c1caebb42bfbeea1f0cf8847d28
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu May 21 15:46:32 2015 +0900
+
+ present: Remove get_drmmode_crtc helper
+
+ It was getting the drmmode_crtc_private_ptr in a roundabout way.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit d64a13ebe0ecd241ee3260dbffd8f4a01e254183
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed May 20 09:58:38 2015 +0900
+
+ Replace SyncFence typedef with declaration of struct _SyncFence
+
+ Fixes build failure in some environments:
+
+ CC radeon_sync.lo
+ In file included from radeon_sync.c:28:
+ /home/tinderbox/xorg-build/include/xorg/misync.h:31: error: redefinition of typedef 'SyncFence'
+ radeon.h:93: note: previous declaration of 'SyncFence' was here
+ make[2]: *** [radeon_sync.lo] Error 1
+
+ Reported-Tested-and-Acked-by: David Airlie <airlied@redhat.com>
+
+commit 818c180c8932233b214a35ba0647af82f7bcec3d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue May 12 17:43:57 2015 +0900
+
+ glamor: Deal with glamor_glyphs_init being removed from xserver
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 7c4b78ab10b82c6dba9f72034ff7583859cca63d
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue May 12 13:21:24 2015 -0400
+
+ add new bonaire pci id
+
+ Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+ Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 80eede245d1eda27eaba108b0761a24bfd69aff6
+Author: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Sat May 9 07:24:36 2015 +0200
+
+ present: Fix present notify timestamps and counts.
+
+ Invalid (msc,ust)=(0,0) were returned to the server
+ because a wrong crtc_id was used to specify which
+ crtc should deliver pageflip completion data. Fix
+ it in accordance with the dri2 implementation.
+
+ Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit e3be8b0a8cf484ff16597413a6172788178e80c8
+Author: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Sat May 9 07:24:35 2015 +0200
+
+ present: Move check for async flips
+
+ Check for and reject currently unsupported async_flip
+ inside radeon_present_check_flip() instead of inside
+ radeon_present_flip().
+
+ This way the server can detect early that async flips
+ aren't supported by the ddx and can deal with this
+ correctly by using its non-vsync'ed CopyRegion fallback.
+
+ Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit 1584dc545c78e0bce8d4b4b9f26b568e2c211453
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Apr 28 17:14:11 2015 +0900
+
+ Skip disabled CRTCs in drmmode_set_desired_modes() even if set_hw == FALSE
+
+ Not skipping a disabled CRTC results in a crash.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90187
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 340baf3804b7d9de8082badfc715a9bee7856e8f
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Mon Apr 27 15:07:06 2015 +0900
+
+ Don't call radeon_get_pixmap_private() when using EXA
+
+ It only works when using glamor.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90169
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 80f3d727f93cb6efedd2b39338d2301035965fe2
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Apr 22 13:33:15 2015 +0900
+
+ On screen resize, clear the new buffer before displaying it
+
+ Fixes garbage being intermittently visible during a screen resize.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=27757#c7
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 3999bf88cdb192fe2f30b03bd2ed6f6a3f9f9057
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Apr 2 18:29:38 2015 +0900
+
+ Make drmmode_copy_fb() work with glamor as well
+
+ Needed for Xorg -background none.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit a4a8cdbcc10c1c5f07485a2af9e9e81e490c3e1d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Apr 2 17:46:34 2015 +0900
+
+ Update scanout pixmap contents before setting a mode with it
+
+ This ensures the scanout pixmaps used for Option "TearFree" and Option
+ "ShadowPrimary" have been initialized when their initial mode is set.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 673e1c7637687c74fc9bdeeeffb7ace0d04b734f
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Apr 2 17:54:33 2015 +0900
+
+ Defer initial modeset until the first BlockHandler invocation
+
+ This ensures that the screen pixmap contents have been initialized when
+ the initial modes are set.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=27757
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 37874a4eeace5df04b02c8fc28f67b824e3f0f5f
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Apr 21 17:19:15 2015 +0900
+
+ Defer initial drmmode_copy_fb call until root window creation
+
+ That's late enough for acceleration to be fully initialized, but still
+ early enough to set pScreen->canDoBGNoneRoot.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 39c497f3efca5ca08343b884f44c93215dcdef31
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Apr 2 18:10:42 2015 +0900
+
+ Only copy fbcon BO contents if bgNoneRoot is TRUE
+
+ Otherwise, the X server will initialize the screen pixmap contents
+ anyway.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 1af044d7eee211fd4b248c236280274a68334da5
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Apr 22 18:43:02 2015 +0900
+
+ DRI2: Clear old->devPrivate.ptr in fixup_glamor
+
+ It doesn't point to the memory of the newly allocated BO. Fixes crash
+ running piglit with Option "ShadowPrimary" enabled.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 43159ef400c3b18b9f4d3e6fa1c4aef2d60d38fe
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Mon Apr 20 18:44:36 2015 +0900
+
+ Add Option "TearFree" v4
+
+ Avoids tearing by flipping between two scanout BOs per (non-rotated) CRTC
+
+ v2:
+ * Fix condition for TearFree log message (Richard Wilbur)
+ * Log warning message about DRI page flipping being enabled because of
+ TearFree (or ShadowPrimary) also when building without glamor support
+
+ v3:
+ * Only override fb_id/x/y if all scanout pixmaps have been successfully
+ allocated
+
+ v4:
+ * Make log warning clearer if drmModePageFlip returns an error
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1)
+
+commit ed401f5b4f07375db17ff05e294907ec95fc946d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri Apr 3 12:11:00 2015 +0900
+
+ glamor: Remove the stride member of struct radeon_pixmap
+
+ Its value was always the same as that of the PixmapRec devKind member.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit ae92d1765fa370a8d94c2856ad6c45d273ec3c69
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 16:23:24 2015 +0900
+
+ glamor: Add Option "ShadowPrimary" v2
+
+ When this option is enabled, most pixmaps (including the screen pixmap)
+ are allocated in system RAM and mostly accessed by the CPU. Changed areas
+ of the screen pixmap are copied to dedicated per-CRTC scanout pixmaps
+ regularly, triggered by the vblank interrupt.
+
+ v2:
+ * Set region data pointer to NULL for keeping only the extents
+ * Move pRegion and pBox local variable declarations closer to their uses
+ in drmmode_set_mode_major()
+
+commit eea79472a84672ee4dc7adc4487cec6a4037048a
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Apr 1 15:51:52 2015 +0900
+
+ glamor: Add wrappers for the X server rendering hooks
+
+ They can choose between using the GPU or CPU for the operation.
+
+commit 051d46382656ffc3e6cac1aab3aee7efdf5b623a
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 19 17:34:27 2015 +0900
+
+ glamor: Add radeon_pixmap parameter to radeon_glamor_create_textured_pixmap
+
+commit 2fa021f77372ca93375a3d13a0c43a9089674899
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 19 17:38:47 2015 +0900
+
+ glamor: Remove unused function radeon_glamor_pixmap_is_offscreen
+
+commit e96349ba6281fd18b8bf9c76629128276b065e6c
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Apr 1 16:04:13 2015 +0900
+
+ Add RADEON_CREATE_PIXMAP_SCANOUT flag
+
+ It means that the pixmap is used for scanout exclusively.
+
+commit 9be7dd382e86d2b804de81d4e2af7431b2e16843
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Apr 1 12:40:16 2015 +0900
+
+ Split out struct drmmode_scanout for rotation shadow buffer information
+
+ Will be used for other kinds of dedicated scanout buffers as well.
+
+commit c32b0530302739f6512755bccf281c2300617376
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 19 17:46:48 2015 +0900
+
+ Rename scanout_pixmap_x field to prime_pixmap_x
+
+ To avoid confusion with upcoming changes.
+
+commit 5921ba4ca705a0d919515626088f3948cc4848c1
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 31 15:14:52 2015 +0900
+
+ present: Don't flip between BOs with different tiling parameters
+
+ The kernel driver doesn't handle that correctly yet.
+
+ Fixes or at least avoids issues with OpenGL fullscreen apps with DRI3
+ enabled and using PRIME or with (2D) tiling disabled.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89720
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 428e416e7cb04a1e0527da39cfebf70218879a77
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Apr 2 10:34:03 2015 +0900
+
+ Add radeon_get_pixmap_tiling_flags helper
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 98fb4199e63fedd4607cddee64bf602d6398df81
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 31 12:25:18 2015 +0900
+
+ Only enable SYNC extension fences and the Present extension along with DRI3
+
+ This avoids some trouble with the Gallium nine state tracker, which uses
+ the Present extension even when DRI3 is disabled.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89772
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit f8b0f23e9f4af9f9097ee5e72d53b45173163c41
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri Mar 27 12:34:55 2015 +0900
+
+ DRI2: Use radeon_get_pixmap_handle
+
+ Now we can share pixmaps with no struct radeon_bo via DRI2.
+
+ Fixes VDPAU video playback freezing when using an OpenGL compositor with
+ DRI3 enabled.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89755
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Tested-by: Nick Sarnie <commendsarnex@gmail.com>
+
+commit ccbda955ebae1d457d35293833f12791e0f9fb0b
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri Mar 27 12:16:44 2015 +0900
+
+ Move get_pixmap_handle helper to radeon_bo_helper.c
+
+ No functional change.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Tested-by: Nick Sarnie <commendsarnex@gmail.com>
+
+commit de5ddd09db82141b263338dcf0c28e01f58268ee
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 26 16:33:02 2015 +0900
+
+ Move radeon_drm_handler/abort_proc fields to drmmode_flipdata_rec
+
+ Their values are the same for all DRM flip ioctl calls within a single
+ radeon_do_pageflip() call.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit e8c0f6319fbf4c3ea11e22ab1a68837031bdec8c
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 26 16:27:35 2015 +0900
+
+ Simplify radeon_do_pageflip() error handling slightly more
+
+ We don't need the local variable old_fb_id.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 8fc22360d5520469c82092ccb0fcf2af330c573f
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 26 15:58:01 2015 +0900
+
+ Increase robustness against DRM page flip ioctl failures v3
+
+ Centralize cleanup, only clean up things that have been allocated for
+ the failed ioctl call.
+
+ Fixes double-free after a flip ioctl failure.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89681
+
+ v2: Only call drmModeRmFB for flipdata->old_fb_id on receipt of last DRM
+ page flip event. Fixes Black screen on making glxgears fullscreen with
+ DRI3 enabled.
+ v3: Avoid double-free of flipdata in the unlikely case that calloc fails
+ for flipcarrier, but only for the second or later CRTC.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v2)
+
+commit b16609b453bb1a181198cf27778f205dc23fb642
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 26 17:15:21 2015 +0900
+
+ glamor: Handle GLAMOR_* flags removed from xserver
+
+ The behaviour is the same as when the removed flags were passed in.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 391900a670addec39515f924265bfa9f8bfa9ec0
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 12:56:07 2015 +0900
+
+ glamor: Avoid generating GEM flink names for BOs shared via DRI3 v2
+
+ We can't create our own struct radeon_bo representation in this case
+ because destroying that would make the GEM handle inaccessible to glamor
+ as well. So just get the handle directly via dma-buf.
+
+ v2: Close dma-buf file descriptor, pointed out by Axel Davy.
+
+ Reviewed-by: Axel Davy <axel.davy@ens.fr>
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit dfad91fffb5bd013785223b42d78886df839eacf
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 19 12:37:01 2015 +0900
+
+ Present: Add radeon_present_get_pixmap_handle helper
+
+ Reviewed-by: Axel Davy <axel.davy@ens.fr>
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 7b4fc4a677d252d01c2bf80d162bc35814059eaa
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 19 12:15:52 2015 +0900
+
+ Make radeon_do_pageflip take a BO handle directly
+
+ Reviewed-by: Axel Davy <axel.davy@ens.fr>
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit af6076241c0d322b295a4e898407ae2472bd8eb4
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 24 13:37:01 2015 +0900
+
+ Adapt radeon_sync.c for misyncshm.h vs misync.h as well
+
+ This should have been part of the previous commit. Without this, SYNC
+ extension fences (and by extension DRI3) were disabled because it checked
+ for HAVE_MISYNC_H, but configure now only defines HAVE_MISYNCSHM_H.
+
+commit aa7825eb29cdf6ac9d7b28ad18186807ff384687
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Mon Mar 23 10:12:17 2015 +0900
+
+ configure.ac: Check for misyncshm.h again
+
+ We need this header, which was added after the other misync*.h headers,
+ along with DRI3 support.
+
+commit 6291baaed261e36a63dc001307427fe00ba82259
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 19 00:12:06 2015 +0900
+
+ EXA: Return NULL from radeon_get_pixmap_bo if there is no driver private
+
+ This mirrors what the glamor part of the function does. Fixes a crash
+ running glxgears_pixmap with DRI3 enabled, reported by "marvin24" on IRC.
+
+commit f68d9b5ba0c91a725b5eec9386c61bea8824c299
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 18:29:27 2015 +0900
+
+ dri3: Use screen->CreatePixmap instead of fbCreatePixmap directly
+
+ Fixes crash with EXA reported by "marvin24" on IRC.
+
+commit 4b0997e56dec0053cb2cb793e0f4ae35055ff7e6
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 12:30:09 2015 +0900
+
+ glamor: Add glamor_fd_from_pixmap define for standalone glamor tree
+
+commit af1862a37570fa512a525ab47d72b30400d2e2d6
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 11:05:40 2015 +0900
+
+ Always include misync.h before other misync headers
+
+ Older versions of xserver didn't include misync.h from other misync
+ headers as needed.
+
+commit fcd37f65f485291084c174666bd605e215bf1398
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 10:39:03 2015 +0900
+
+ DRI3: Use open hook instead of open_client
+
+ We don't need the client pointer, and this allows it to work with older
+ versions of xserver as well.
+
+commit f940fd741b15f03393037c5bb904cd74f012de9d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 18 10:06:47 2015 +0900
+
+ Initialize boolean variable before calling xf86GetOptValBool
+
+ We were just lucky that it contained 0 in most cases.
+
+commit 4a98f60117c387a228d5cbaadb6e298fb4e865df
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 17 16:47:11 2015 +0900
+
+ Add xorg_list_for_each_entry_safe fallback in radeon_list.h
+
+ Fixes another build failure against older versions of xserver reported
+ by "Pali" on IRC.
+
+commit 694e04720b886060fe3eefdce59741f218c8269f
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 17 16:32:09 2015 +0900
+
+ Simplify includes in radeon_{dri3,present}.c
+
+ Just include radeon.h first. Fixes build failures against older versions
+ of xserver because compat-api.h wasn't getting picked up. Reported by
+ "Pali" on IRC.
+
+commit 64e1e4dbdd3caee6f5d8f6b6c094b4533fa94953
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 10 16:53:11 2015 +0900
+
+ Add DRI3 support v2
+
+ Must be enabled with
+
+ Option "DRI3"
+
+ in xorg.conf.
+
+ v2: Adapt to v2 of patches 11/12.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 69ae0194778fe4276895839db92383f63f0b5de4
+Author: David Heidelberger <david.heidelberger@ixit.cz>
+Date: Fri Mar 6 17:57:22 2015 +0900
+
+ Handle tiling in radeon_set_shared_pixmap_backing
+
+ [ Michel Dänzer: Fixups for glamor ]
+ Signed-off-by: David Heidelberger <david.heidelberger@ixit.cz>
+ Signed-off-by: Axel Davy <axel.davy@ens.fr>
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 3c65fb849e1ba9fb6454bcaa55b696548902f3fc
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 10 16:52:54 2015 +0900
+
+ Add support for the Present extension v2
+
+ v2: Fix up for struct radeon_drm_queue -> radeon_drm_queue_entry.
+ Swapped order of patches 11 & 12 because the Present extension uses
+ SYNC fences.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 8fc9a241ab59ffbcdc178d6415332c88a54e85fe
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 5 18:18:56 2015 +0900
+
+ Add support for SYNC extension fences v2
+
+ v2: Swapped order of patches 11 & 12 because the Present extension uses
+ SYNC fences.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 4a35e2f33d9cdfb608423046391311109f96fb6b
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 5 18:34:07 2015 +0900
+
+ Fold radeon_glamor_flush into radeon_cs_flush_indirect
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 4b8adebb80158bcf81ada83bb88517febe931b12
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 5 18:40:23 2015 +0900
+
+ Move #include "radeon_glamor.h" from radeon.h to where it's needed
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 76c2923ac5c7230a8b2f9f8329c308d28b44d9c0
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 4 10:30:19 2015 +0900
+
+ DRI2: Split out helper for getting UST and MSC of a specific CRTC
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 6c3a721cde9317233072b573f9502348dcd21b16
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Tue Mar 10 16:52:18 2015 +0900
+
+ DRI2: Use helper functions for DRM event queue management v3
+
+ This is mostly in preparation for Present support, but it also simplifies
+ the DRI2 specific code a little.
+
+ v2: Fix up for struct radeon_drm_queue -> radeon_drm_queue_entry.
+ v3: Removed excess 0s from conversion from microseconds to seconds,
+ thanks to Richard Wilbur <richard.wilbur@gmail.com> for the catch!
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit c3fa22a479e61d1899fa9d327d9c4e2a7f64b0c1
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 11 17:47:59 2015 +0900
+
+ DRI2: Move radeon_dri2_flip_event_handler
+
+ In preparation for the next change, which will modify it to a static
+ function which needs to be in the new place. No functional change.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 65045112fdc8a9fa36e0e00f46739a6152b775ff
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 11 17:33:54 2015 +0900
+
+ DRI2: Remove superfluous assignments to *_info->frame
+
+ That field is only used for page flipping.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit ad27f16f308079d06a2b1c788b3cb0947531253a
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Mar 11 17:30:11 2015 +0900
+
+ DRI2: Simplify blit fallback handling for scheduled swaps
+
+ Also use radeon_dri2_schedule_event when possible.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit b4af8a327ed8420f0ff4ea0f113f4a59406ed4d3
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Mon Mar 2 18:59:54 2015 +0900
+
+ Add DRM event queue helpers v2
+
+ v2: Rename struct radeon_drm_queue to struct radeon_drm_queue_event,
+ thanks to Richard Wilbur <richard.wilbur@gmail.com> for the suggestion.
+ Also changed the corresponding parameter and local variable names from
+ 'q' to 'e'.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 7c3470f4b659206ed23f761948936ede3a2dba3d
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Fri Mar 6 18:51:29 2015 +0900
+
+ Move xorg_list backwards compatibility to new radeon_list.h header
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 7388d0b6c54b9d536fdb161e3aa61b326627b939
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Thu Mar 5 17:35:06 2015 +0900
+
+ Require at least xserver 1.8
+
+ So we can rely on the list.h header.
+
+ xserver 1.8 was released in April 2010.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit b8ec9ed4fe86952763b963c86f0af0dcae69aa6c
+Author: Jerome Glisse <jglisse@redhat.com>
+Date: Thu Feb 19 14:47:41 2015 -0500
+
+ Proper leak fix, previous leak fix was bogus.
+
+ Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
+
+commit 63dc36dc49f93cb00111b497ab6805194bc9d240
+Author: Jerome Glisse <jglisse@redhat.com>
+Date: Thu Feb 19 11:43:08 2015 -0500
+
+ Avoid leaking memory on output.
+
+ Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
+
+commit c80ea1e3e8c5f155cedadbe4588870fb1f410ab4
+Author: Rolf Eike Beer <eb@emlix.com>
+Date: Tue Jan 13 12:11:26 2015 +0100
+
+ radeon: remove unneeded inclusion of sarea.h
+
+ None of the structs or defines from that header is used.
+
+ Signed-off-by: Rolf Eike Beer <eb@emlix.com>
+
+commit 04da199231bb3f11cf17f94574a8df05855a7b82
+Author: Adam Jackson <ajax@redhat.com>
+Date: Wed Dec 17 14:03:58 2014 -0500
+
+ Remove dead accelDFS flag
+
+ Signed-off-by: Adam Jackson <ajax@redhat.com>
+
+commit c9f8f642fd495937400618a4fc25ecae3f8888fc
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Mon Nov 17 12:32:29 2014 +0900
+
+ Prefer drmModeSetCursor2 over drmModeSetCursor
+
+ The former includes information about the position of the hotspot within
+ the cursor image.
+
+ Copied from xf86-video-modesetting.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 2f11dcd43966cf2ee26e61960fd72e6644f5e037
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Nov 10 13:49:29 2014 +1000
+
+ radeon: add support for DP 1.2 display hotplug (v2)
+
+ This allows for dynamic creation of conneectors when the
+ kernel tells us.
+
+ v2: fix dpms off crash
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit c88424d1f4aaa78b569e5d44f0b4a47de2f422f4
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Nov 10 14:17:54 2014 +1000
+
+ radeon: move output name creation to its own function
+
+ The secondary indent is deliberate to make the next patch more
+ parseable for mst support.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit 32b003cb7657e07d5af6338ad44d768eda87fd33
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Nov 10 14:12:34 2014 +1000
+
+ radeon: stop caching mode resources
+
+ This is step one towards MST connector hotplug support,
+ it stop caching the mode resources structure, and
+ just passes a pointer to it around.
+
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit 7c7b38e0b375b6e8853ad2d1092302ea83f6f570
+Author: David Heidelberger <david.heidelberger@ixit.cz>
+Date: Sun Oct 12 16:34:21 2014 +0200
+
+ radeon/vdpau: don't report VDPAU for < r300
+
+ Signed-off-by: David Heidelberger <david.heidelberger@ixit.cz>
+
+commit c74de9fec13fac2c836bb2a07ae6f90e1d61e667
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Aug 6 11:08:00 2014 +0900
+
+ PRIME: Don't advertise offload capabilities when acceleration is disabled
+
+ Xorg tends to crash if the user tries to actually use the offload
+ capabilities with acceleration disabled.
+
+ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57200
+ Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 636a6382f80412ae4e28abe0cd9f98f84cd52291
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date: Wed Oct 15 12:02:17 2014 +0900
+
+ Remove duplicate OPTION_PAGE_FLIP entry
+
+ Reported by 'amanual' on IRC
+
+commit c854b4479ec5122390ede81b655b259efd9b1800
+Author: Alex Deucher <alexdeucher@gmail.com>
+Date: Thu Oct 2 10:22:22 2014 -0400
+
+ radeon: bump version post release
+
+ Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+
commit 068a59e010ce6bfcd54f5a18cc08c55c54b8618d
Author: Alex Deucher <alexander.deucher@amd.com>
Date: Wed Oct 1 23:38:52 2014 -0400
diff --git a/driver/xf86-video-ati/config.h.in b/driver/xf86-video-ati/config.h.in
index f8b7f7890..ba7522f06 100644
--- a/driver/xf86-video-ati/config.h.in
+++ b/driver/xf86-video-ati/config.h.in
@@ -8,6 +8,15 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define to 1 if you have the <dri3.h> header file. */
+#undef HAVE_DRI3_H
+
+/* Have fbGlyphs API */
+#undef HAVE_FBGLYPHS
+
+/* Have glamor_glyphs_init API */
+#undef HAVE_GLAMOR_GLYPHS_INIT
+
/* Define to 1 if you have the <glamor.h> header file. */
#undef HAVE_GLAMOR_H
@@ -17,12 +26,15 @@
/* libudev support */
#undef HAVE_LIBUDEV
-/* Define to 1 if you have the <list.h> header file. */
-#undef HAVE_LIST_H
-
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
+/* Define to 1 if you have the <misyncshm.h> header file. */
+#undef HAVE_MISYNCSHM_H
+
+/* Define to 1 if you have the <present.h> header file. */
+#undef HAVE_PRESENT_H
+
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
diff --git a/driver/xf86-video-ati/configure b/driver/xf86-video-ati/configure
index 3dffa8907..c7b5d121f 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 7.5.0.
+# Generated by GNU Autoconf 2.69 for xf86-video-ati 7.6.1.
#
# Report bugs to <https://bugs.freedesktop.org/enter_bug.cgi?product=xorg>.
#
@@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='xf86-video-ati'
PACKAGE_TARNAME='xf86-video-ati'
-PACKAGE_VERSION='7.5.0'
-PACKAGE_STRING='xf86-video-ati 7.5.0'
+PACKAGE_VERSION='7.6.1'
+PACKAGE_STRING='xf86-video-ati 7.6.1'
PACKAGE_BUGREPORT='https://bugs.freedesktop.org/enter_bug.cgi?product=xorg'
PACKAGE_URL=''
@@ -1386,7 +1386,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 7.5.0 to adapt to many kinds of systems.
+\`configure' configures xf86-video-ati 7.6.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1456,7 +1456,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of xf86-video-ati 7.5.0:";;
+ short | recursive ) echo "Configuration of xf86-video-ati 7.6.1:";;
esac
cat <<\_ACEOF
@@ -1609,7 +1609,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-xf86-video-ati configure 7.5.0
+xf86-video-ati configure 7.6.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2024,7 +2024,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 7.5.0, which was
+It was created by xf86-video-ati $as_me 7.6.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2855,7 +2855,7 @@ fi
# Define the identity of the package.
PACKAGE='xf86-video-ati'
- VERSION='7.5.0'
+ VERSION='7.6.1'
cat >>confdefs.h <<_ACEOF
@@ -18438,12 +18438,12 @@ if test -n "$XORG_CFLAGS"; then
pkg_cv_XORG_CFLAGS="$XORG_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xorg-server >= 1.7 xproto fontsproto xf86driproto \$REQUIRED_MODULES\""; } >&5
- ($PKG_CONFIG --exists --print-errors "xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xorg-server >= 1.8 xproto fontsproto xf86driproto \$REQUIRED_MODULES\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_XORG_CFLAGS=`$PKG_CONFIG --cflags "xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>/dev/null`
+ pkg_cv_XORG_CFLAGS=`$PKG_CONFIG --cflags "xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
@@ -18455,12 +18455,12 @@ if test -n "$XORG_LIBS"; then
pkg_cv_XORG_LIBS="$XORG_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xorg-server >= 1.7 xproto fontsproto xf86driproto \$REQUIRED_MODULES\""; } >&5
- ($PKG_CONFIG --exists --print-errors "xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xorg-server >= 1.8 xproto fontsproto xf86driproto \$REQUIRED_MODULES\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_XORG_LIBS=`$PKG_CONFIG --libs "xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>/dev/null`
+ pkg_cv_XORG_LIBS=`$PKG_CONFIG --libs "xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
@@ -18481,14 +18481,14 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- XORG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>&1`
+ XORG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>&1`
else
- XORG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>&1`
+ XORG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$XORG_PKG_ERRORS" >&5
- as_fn_error $? "Package requirements (xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES) were not met:
+ as_fn_error $? "Package requirements (xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES) were not met:
$XORG_PKG_ERRORS
@@ -18738,6 +18738,16 @@ else
GLAMOR_XSERVER="no"
fi
+
+ ac_fn_c_check_decl "$LINENO" "glamor_glyphs_init" "ac_cv_have_decl_glamor_glyphs_init" "#include \"xorg-server.h\"
+ #include \"glamor.h\"
+"
+if test "x$ac_cv_have_decl_glamor_glyphs_init" = xyes; then :
+
+$as_echo "#define HAVE_GLAMOR_GLYPHS_INIT 1" >>confdefs.h
+
+fi
+
fi
if test "x$GLAMOR_XSERVER" != xyes; then
@@ -18940,36 +18950,81 @@ else
fi
-for ac_header in list.h
+ac_fn_c_check_decl "$LINENO" "fbGlyphs" "ac_cv_have_decl_fbGlyphs" "#include <X11/Xmd.h>
+ #include <X11/Xfuncproto.h>
+ #include <X11/extensions/renderproto.h>
+ #include <xorg-server.h>
+ #include <picture.h>
+ #include <glyphstr.h>
+ #include <fbpict.h>
+"
+if test "x$ac_cv_have_decl_fbGlyphs" = xyes; then :
+
+$as_echo "#define HAVE_FBGLYPHS 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_decl "$LINENO" "xorg_list_init" "ac_cv_have_decl_xorg_list_init" "#include <X11/Xdefs.h>
+ #include \"xorg-server.h\"
+ #include \"list.h\"
+"
+if test "x$ac_cv_have_decl_xorg_list_init" = xyes; then :
+
+$as_echo "#define HAVE_XORG_LIST 1" >>confdefs.h
+
+fi
+
+
+for ac_header in misyncshm.h
do :
- ac_fn_c_check_header_compile "$LINENO" "list.h" "ac_cv_header_list_h" "#include <X11/Xdefs.h>
- #include \"xorg-server.h\"
+ ac_fn_c_check_header_compile "$LINENO" "misyncshm.h" "ac_cv_header_misyncshm_h" "#include <X11/Xdefs.h>
+ #include <X11/Xfuncproto.h>
+ #include <xorg-server.h>
+ #include <screenint.h>
"
-if test "x$ac_cv_header_list_h" = xyes; then :
+if test "x$ac_cv_header_misyncshm_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_LIST_H 1
+#define HAVE_MISYNCSHM_H 1
_ACEOF
- have_list_h="yes"
-else
- have_list_h="no"
+
fi
done
-if test "x$have_list_h" = xyes; then
- ac_fn_c_check_decl "$LINENO" "xorg_list_init" "ac_cv_have_decl_xorg_list_init" "#include <X11/Xdefs.h>
- #include \"xorg-server.h\"
- #include \"list.h\"
+for ac_header in present.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "present.h" "ac_cv_header_present_h" "#include <X11/Xmd.h>
+ #include <X11/Xproto.h>
+ #include <X11/X.h>
+ #include \"xorg-server.h\"
"
-if test "x$ac_cv_have_decl_xorg_list_init" = xyes; then :
-
-$as_echo "#define HAVE_XORG_LIST 1" >>confdefs.h
+if test "x$ac_cv_header_present_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_PRESENT_H 1
+_ACEOF
fi
+done
+
+
+for ac_header in dri3.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "dri3.h" "ac_cv_header_dri3_h" "#include <X11/Xmd.h>
+ #include <xorg-server.h>
+"
+if test "x$ac_cv_header_dri3_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DRI3_H 1
+_ACEOF
+
fi
+done
+
+
CPPFLAGS="$SAVE_CPPFLAGS"
@@ -19762,7 +19817,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 7.5.0, which was
+This file was extended by xf86-video-ati $as_me 7.6.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -19828,7 +19883,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 7.5.0
+xf86-video-ati config.status 7.6.1
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 d30efafa7..c024d484b 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],
- [7.5.0],
+ [7.6.1],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
[xf86-video-ati])
@@ -75,7 +75,7 @@ PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.58])
PKG_CHECK_MODULES(LIBDRM_RADEON, [libdrm_radeon])
# Obtain compiler/linker options for the driver dependencies
-PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES])
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES])
PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1],
HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available]),
HAVE_XEXTPROTO_71="no")
@@ -113,6 +113,12 @@ if test "x$GLAMOR" != "xno"; then
[GLAMOR_XSERVER="yes"], [GLAMOR_XSERVER="no"],
[#include "xorg-server.h"
#include "glamor.h"])
+
+ AC_CHECK_DECL(glamor_glyphs_init,
+ [AC_DEFINE(HAVE_GLAMOR_GLYPHS_INIT, 1,
+ [Have glamor_glyphs_init API])], [],
+ [#include "xorg-server.h"
+ #include "glamor.h"])
fi
if test "x$GLAMOR_XSERVER" != xyes; then
@@ -125,18 +131,37 @@ else
fi
AM_CONDITIONAL(GLAMOR, test x$GLAMOR != xno)
-AC_CHECK_HEADERS([list.h],
- [have_list_h="yes"], [have_list_h="no"],
- [#include <X11/Xdefs.h>
- #include "xorg-server.h"])
-
-if test "x$have_list_h" = xyes; then
- AC_CHECK_DECL(xorg_list_init,
- [AC_DEFINE(HAVE_XORG_LIST, 1, [Have xorg_list API])], [],
- [#include <X11/Xdefs.h>
- #include "xorg-server.h"
- #include "list.h"])
-fi
+AC_CHECK_DECL(fbGlyphs,
+ [AC_DEFINE(HAVE_FBGLYPHS, 1, [Have fbGlyphs API])], [],
+ [#include <X11/Xmd.h>
+ #include <X11/Xfuncproto.h>
+ #include <X11/extensions/renderproto.h>
+ #include <xorg-server.h>
+ #include <picture.h>
+ #include <glyphstr.h>
+ #include <fbpict.h>])
+
+AC_CHECK_DECL(xorg_list_init,
+ [AC_DEFINE(HAVE_XORG_LIST, 1, [Have xorg_list API])], [],
+ [#include <X11/Xdefs.h>
+ #include "xorg-server.h"
+ #include "list.h"])
+
+AC_CHECK_HEADERS([misyncshm.h], [], [],
+ [#include <X11/Xdefs.h>
+ #include <X11/Xfuncproto.h>
+ #include <xorg-server.h>
+ #include <screenint.h>])
+
+AC_CHECK_HEADERS([present.h], [], [],
+ [#include <X11/Xmd.h>
+ #include <X11/Xproto.h>
+ #include <X11/X.h>
+ #include "xorg-server.h"])
+
+AC_CHECK_HEADERS([dri3.h], [], [],
+ [#include <X11/Xmd.h>
+ #include <xorg-server.h>])
CPPFLAGS="$SAVE_CPPFLAGS"
diff --git a/driver/xf86-video-ati/man/radeon.man b/driver/xf86-video-ati/man/radeon.man
index 7dde04005..fa55c6d14 100644
--- a/driver/xf86-video-ati/man/radeon.man
+++ b/driver/xf86-video-ati/man/radeon.man
@@ -267,11 +267,23 @@ The default value is
for R/RV6XX, R/RV7XX, RS780, RS880, EVERGREEN, CAYMAN, ARUBA, Southern Islands, and
Sea Islands.
.TP
+.BI "Option \*qDRI\*q \*q" integer \*q
+Define the maximum level of DRI to enable. Valid values are 2 for DRI2 or 3 for DRI3.
+The default is
+.B 2 for DRI2.
+.TP
.BI "Option \*qEnablePageFlip\*q \*q" boolean \*q
Enable DRI2 page flipping. The default is
.B on.
Pageflipping is supported on all radeon hardware.
.TP
+.BI "Option \*qTearFree\*q \*q" boolean \*q
+Enable tearing prevention using the hardware page flipping mechanism. This
+option currently doesn't have any effect for rotated CRTCs. It requires
+allocating two separate scanout buffers for each non-rotated CRTC. Enabling
+this option currently disables Option \*qEnablePageFlip\*q. The default is
+.B off.
+.TP
.BI "Option \*qAccelMethod\*q \*q" "string" \*q
Chooses between available acceleration architectures. Valid values are
.B EXA
@@ -286,6 +298,22 @@ as of TAHITI, otherwise
The following driver
.B Options
are supported for
+.B glamor
+:
+.TP
+.BI "Option \*qShadowPrimary\*q \*q" boolean \*q
+This option enables a so-called "shadow primary" buffer for fast CPU access to
+pixel data, and separate scanout buffers for each display controller (CRTC).
+This may improve performance for some 2D workloads, potentially at the expense
+of other (e.g. 3D, video) workloads.
+Note in particular that enabling this option currently disables page flipping.
+The default is
+.B off.
+
+.PP
+The following driver
+.B Options
+are supported for
.B EXA
:
.TP
diff --git a/driver/xf86-video-ati/src/Makefile.am b/driver/xf86-video-ati/src/Makefile.am
index 9ff1ffba0..8f39e213e 100644
--- a/driver/xf86-video-ati/src/Makefile.am
+++ b/driver/xf86-video-ati/src/Makefile.am
@@ -27,10 +27,11 @@
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
-radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
+radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS)
-RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
- radeon_bo_helper.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+ radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+ drmmode_display.c
RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
@@ -64,6 +65,7 @@ if GLAMOR
AM_CFLAGS += @LIBGLAMOR_CFLAGS@
radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@
radeon_drv_la_SOURCES += \
+ radeon_glamor_wrappers.c \
radeon_glamor.c
endif
@@ -88,11 +90,13 @@ EXTRA_DIST = \
bicubic_table.h \
bicubic_table.py \
radeon_bo_helper.h \
+ radeon_drm_queue.h \
radeon_exa_render.c \
radeon_exa_funcs.c \
radeon_exa_shared.h \
radeon_glamor.h \
radeon.h \
+ radeon_list.h \
radeon_probe.h \
radeon_reg.h \
radeon_version.h \
diff --git a/driver/xf86-video-ati/src/Makefile.in b/driver/xf86-video-ati/src/Makefile.in
index a84f7d64b..fdb64e268 100644
--- a/driver/xf86-video-ati/src/Makefile.in
+++ b/driver/xf86-video-ati/src/Makefile.in
@@ -81,6 +81,7 @@ host_triplet = @host@
@GLAMOR_TRUE@am__append_2 = @LIBGLAMOR_CFLAGS@
@GLAMOR_TRUE@am__append_3 = @LIBGLAMOR_LIBS@
@GLAMOR_TRUE@am__append_4 = \
+@GLAMOR_TRUE@ radeon_glamor_wrappers.c \
@GLAMOR_TRUE@ radeon_glamor.c
subdir = src
@@ -137,24 +138,26 @@ ati_drv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(ati_drv_la_LDFLAGS) $(LDFLAGS) -o $@
@LIBUDEV_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
radeon_drv_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
am__radeon_drv_la_SOURCES_DIST = radeon_accel.c radeon_video.c \
radeon_misc.c radeon_probe.c radeon_textured_video.c \
radeon_xvmc.c radeon_exa.c r600_exa.c r6xx_accel.c \
r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
evergreen_exa.c evergreen_accel.c evergreen_shader.c \
evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c \
- radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
- radeon_bo_helper.c radeon_glamor.c
+ radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+ radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+ drmmode_display.c radeon_glamor_wrappers.c radeon_glamor.c
am__objects_1 = radeon_exa.lo r600_exa.lo r6xx_accel.lo \
r600_textured_videofuncs.lo r600_shader.lo \
radeon_exa_shared.lo evergreen_exa.lo evergreen_accel.lo \
evergreen_shader.lo evergreen_textured_videofuncs.lo \
cayman_accel.lo cayman_shader.lo
-am__objects_2 = radeon_dri2.lo radeon_kms.lo drmmode_display.lo \
- radeon_vbo.lo radeon_bo_helper.lo
-@GLAMOR_TRUE@am__objects_3 = radeon_glamor.lo
+am__objects_2 = radeon_dri2.lo radeon_dri3.lo radeon_drm_queue.lo \
+ radeon_kms.lo radeon_present.lo radeon_sync.lo radeon_vbo.lo \
+ radeon_bo_helper.lo drmmode_display.lo
+@GLAMOR_TRUE@am__objects_3 = radeon_glamor_wrappers.lo \
+@GLAMOR_TRUE@ radeon_glamor.lo
am_radeon_drv_la_OBJECTS = radeon_accel.lo radeon_video.lo \
radeon_misc.lo radeon_probe.lo radeon_textured_video.lo \
radeon_xvmc.lo $(am__objects_1) $(am__objects_2) \
@@ -363,10 +366,11 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
-radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS) \
- $(am__append_1) $(am__append_3)
-RADEON_KMS_SRCS = radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
- radeon_bo_helper.c
+radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(am__append_1) \
+ $(am__append_3)
+RADEON_KMS_SRCS = radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+ radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+ drmmode_display.c
RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
@@ -406,11 +410,13 @@ EXTRA_DIST = \
bicubic_table.h \
bicubic_table.py \
radeon_bo_helper.h \
+ radeon_drm_queue.h \
radeon_exa_render.c \
radeon_exa_funcs.c \
radeon_exa_shared.h \
radeon_glamor.h \
radeon.h \
+ radeon_list.h \
radeon_probe.h \
radeon_reg.h \
radeon_version.h \
@@ -558,12 +564,17 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_accel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_bo_helper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_dri2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_dri3.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_drm_queue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_exa.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_exa_shared.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_glamor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_glamor_wrappers.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_kms.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_present.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_probe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_sync.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_textured_video.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_vbo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_video.Plo@am__quote@
diff --git a/driver/xf86-video-ati/src/ati_pciids_gen.h b/driver/xf86-video-ati/src/ati_pciids_gen.h
index d867fa71e..c6216a54c 100644
--- a/driver/xf86-video-ati/src/ati_pciids_gen.h
+++ b/driver/xf86-video-ati/src/ati_pciids_gen.h
@@ -692,6 +692,7 @@
#define PCI_CHIP_OLAND_6610 0x6610
#define PCI_CHIP_OLAND_6611 0x6611
#define PCI_CHIP_OLAND_6613 0x6613
+#define PCI_CHIP_OLAND_6617 0x6617
#define PCI_CHIP_OLAND_6620 0x6620
#define PCI_CHIP_OLAND_6621 0x6621
#define PCI_CHIP_OLAND_6623 0x6623
@@ -712,6 +713,7 @@
#define PCI_CHIP_BONAIRE_6658 0x6658
#define PCI_CHIP_BONAIRE_665C 0x665C
#define PCI_CHIP_BONAIRE_665D 0x665D
+#define PCI_CHIP_BONAIRE_665F 0x665F
#define PCI_CHIP_KABINI_9830 0x9830
#define PCI_CHIP_KABINI_9831 0x9831
#define PCI_CHIP_KABINI_9832 0x9832
diff --git a/driver/xf86-video-ati/src/drmmode_display.c b/driver/xf86-video-ati/src/drmmode_display.c
index c8f060a76..4c8931eea 100644
--- a/driver/xf86-video-ati/src/drmmode_display.c
+++ b/driver/xf86-video-ati/src/drmmode_display.c
@@ -32,11 +32,13 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
+#include "cursorstr.h"
+#include "damagestr.h"
#include "micmap.h"
#include "xf86cmap.h"
#include "radeon.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
-#include "sarea.h"
#include "drmmode_display.h"
@@ -97,7 +99,8 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
PixmapPtr pixmap;
struct radeon_surface *surface;
- pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
+ pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth,
+ RADEON_CREATE_PIXMAP_SCANOUT);
if (!pixmap)
return NULL;
@@ -147,7 +150,9 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
}
}
- if (!radeon_glamor_create_textured_pixmap(pixmap)) {
+ if (info->use_glamor &&
+ !radeon_glamor_create_textured_pixmap(pixmap,
+ radeon_get_pixmap_private(pixmap))) {
pScreen->DestroyPixmap(pixmap);
return NULL;
}
@@ -245,6 +250,33 @@ int drmmode_get_current_ust(int drm_fd, CARD64 *ust)
return 0;
}
+/*
+ * Get current frame count and frame count timestamp of the crtc.
+ */
+int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ drmVBlank vbl;
+ int ret;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= radeon_populate_vbl_request_type(crtc);
+ vbl.request.sequence = 0;
+
+ ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "get vblank counter failed: %s\n", strerror(errno));
+ return ret;
+ }
+
+ *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+ *msc = vbl.reply.sequence;
+
+ return Success;
+}
+
static void
drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
@@ -310,18 +342,31 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
static void
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
- /* Nothing to do. drmmode_do_crtc_dpms() is called as appropriate */
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ /* Disable unused CRTCs */
+ if (!crtc->enabled || mode != DPMSModeOn)
+ drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+ else if (drmmode_crtc->dpms_mode != DPMSModeOn)
+ crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
}
static PixmapPtr
create_pixmap_for_fbcon(drmmode_ptr drmmode,
ScrnInfoPtr pScrn, int fbcon_id)
{
- PixmapPtr pixmap = NULL;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ PixmapPtr pixmap = info->fbcon_pixmap;
struct radeon_bo *bo;
drmModeFBPtr fbcon;
struct drm_gem_flink flink;
+ if (pixmap)
+ return pixmap;
+
fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
if (fbcon == NULL)
return NULL;
@@ -348,12 +393,32 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
fbcon->depth, fbcon->bpp,
fbcon->pitch, 0, bo, NULL);
+ info->fbcon_pixmap = pixmap;
radeon_bo_unref(bo);
out_free_fb:
drmModeFreeFB(fbcon);
return pixmap;
}
+static void
+destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ /* XXX: The current GPUVM support in the kernel doesn't allow removing
+ * the virtual address range for this BO, so we need to keep around
+ * the pixmap to avoid breaking glamor with GPUVM
+ */
+ if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN)
+ return;
+
+ if (info->fbcon_pixmap)
+ pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+ info->fbcon_pixmap = NULL;
+}
+
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+
void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -361,13 +426,9 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
PixmapPtr src, dst;
ScreenPtr pScreen = pScrn->pScreen;
int fbcon_id = 0;
+ Bool force;
+ GCPtr gc;
int i;
- int pitch;
- uint32_t tiling_flags = 0;
- Bool ret;
-
- if (info->accelOn == FALSE || info->use_glamor)
- goto fallback;
for (i = 0; i < xf86_config->num_crtc; i++) {
drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
@@ -377,7 +438,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
}
if (!fbcon_id)
- goto fallback;
+ return;
if (fbcon_id == drmmode->fb_id) {
/* in some rare case there might be no fbcon and we might already
@@ -390,54 +451,165 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
if (!src)
- goto fallback;
+ return;
- if (info->allowColorTiling) {
- if (info->ChipFamily >= CHIP_FAMILY_R600) {
- if (info->allowColorTiling2D) {
- tiling_flags |= RADEON_TILING_MACRO;
- } else {
- tiling_flags |= RADEON_TILING_MICRO;
- }
- } else
- tiling_flags |= RADEON_TILING_MACRO;
- }
+ dst = pScreen->GetScreenPixmap(pScreen);
- pitch = RADEON_ALIGN(pScrn->displayWidth,
- drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
- info->pixel_bytes;
+ gc = GetScratchGC(pScrn->depth, pScreen);
+ ValidateGC(&dst->drawable, gc);
+
+ force = info->accel_state->force;
+ info->accel_state->force = TRUE;
+ (*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0,
+ pScrn->virtualX, pScrn->virtualY, 0, 0);
+ info->accel_state->force = force;
+
+ FreeScratchGC(gc);
- dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
- pScrn->virtualY, pScrn->depth,
- pScrn->bitsPerPixel, pitch,
- tiling_flags, info->front_bo, &info->front_surface);
- if (!dst)
- goto out_free_src;
-
- ret = info->accel_state->exa->PrepareCopy (src, dst,
- -1, -1, GXcopy, FB_ALLONES);
- if (!ret)
- goto out_free_src;
- info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
- pScrn->virtualX, pScrn->virtualY);
- info->accel_state->exa->DoneCopy (dst);
radeon_cs_flush_indirect(pScrn);
+ radeon_bo_wait(info->front_bo);
-#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
pScreen->canDoBGNoneRoot = TRUE;
-#endif
- drmmode_destroy_bo_pixmap(dst);
- out_free_src:
- drmmode_destroy_bo_pixmap(src);
+ destroy_pixmap_for_fbcon(pScrn);
return;
+}
-fallback:
- /* map and memset the bo */
- if (radeon_bo_map(info->front_bo, 1))
- return;
+#endif /* GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 */
+
+static void
+drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
+ struct drmmode_scanout *scanout)
+{
+ if (scanout->pixmap) {
+ drmmode_destroy_bo_pixmap(scanout->pixmap);
+ scanout->pixmap = NULL;
+ }
+
+ if (scanout->bo) {
+ drmModeRmFB(drmmode->fd, scanout->fb_id);
+ scanout->fb_id = 0;
+ radeon_bo_unmap(scanout->bo);
+ radeon_bo_unref(scanout->bo);
+ scanout->bo = NULL;
+ }
+
+ if (scanout->damage) {
+ DamageDestroy(scanout->damage);
+ scanout->damage = NULL;
+ }
+}
+
+void
+drmmode_scanout_free(ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ drmmode_crtc_private_ptr drmmode_crtc =
+ xf86_config->crtc[c]->driver_private;
+
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+ &drmmode_crtc->scanout[0]);
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+ &drmmode_crtc->scanout[1]);
+ }
+}
+
+static void *
+drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc,
+ struct drmmode_scanout *scanout,
+ int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int aligned_height;
+ int size;
+ int ret;
+ unsigned long rotate_pitch;
+ int base_align;
+
+ if (scanout->bo) {
+ if (scanout->width == width && scanout->height == height)
+ return scanout->bo->ptr;
+
+ drmmode_crtc_scanout_destroy(drmmode, scanout);
+ }
+
+ rotate_pitch =
+ RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0))
+ * drmmode->cpp;
+ aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, 0));
+ base_align = drmmode_get_base_align(pScrn, drmmode->cpp, 0);
+ size = RADEON_ALIGN(rotate_pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
+
+ scanout->bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+ if (scanout->bo == NULL)
+ return NULL;
+
+ radeon_bo_map(scanout->bo, 1);
+
+ ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth,
+ pScrn->bitsPerPixel, rotate_pitch,
+ scanout->bo->handle,
+ &scanout->fb_id);
+ if (ret) {
+ ErrorF("failed to add scanout fb\n");
+ radeon_bo_unref(scanout->bo);
+ scanout->bo = NULL;
+ return NULL;
+ }
+
+ scanout->width = width;
+ scanout->height = height;
+ return scanout->bo->ptr;
+}
+
+static PixmapPtr
+drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
+ int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ unsigned long rotate_pitch;
+
+ if (scanout->pixmap) {
+ if (scanout->width == width && scanout->height == height)
+ return scanout->pixmap;
+
+ drmmode_crtc_scanout_destroy(drmmode, scanout);
+ }
+
+ if (!scanout->bo) {
+ if (!drmmode_crtc_scanout_allocate(crtc, scanout, width, height))
+ return NULL;
+ }
+
+ rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0))
+ * drmmode->cpp;
+
+ scanout->pixmap = drmmode_create_bo_pixmap(pScrn,
+ width, height,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ rotate_pitch,
+ 0, scanout->bo, NULL);
+ if (scanout->pixmap == NULL)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate scanout pixmap for CRTC\n");
+
+ return scanout->pixmap;
+}
- memset(info->front_bo->ptr, 0x00, info->front_bo->size);
- radeon_bo_unmap(info->front_bo);
+static void
+radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
+{
+ /* Only keep track of the extents */
+ RegionUninit(&damage->damage);
+ damage->damage.data = NULL;
}
static Bool
@@ -452,7 +624,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
int saved_x, saved_y;
Rotation saved_rotation;
DisplayModeRec saved_mode;
- uint32_t *output_ids;
+ uint32_t *output_ids = NULL;
int output_count = 0;
Bool ret = TRUE;
int i;
@@ -460,7 +632,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmModeModeInfo kmode;
int pitch;
uint32_t tiling_flags = 0;
- int height;
if (info->allowColorTiling) {
if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -471,14 +642,13 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
info->pixel_bytes;
- height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags));
if (info->ChipFamily >= CHIP_FAMILY_R600) {
pitch = info->front_surface.level[0].pitch_bytes;
}
if (drmmode->fb_id == 0) {
ret = drmModeAddFB(drmmode->fd,
- pScrn->virtualX, height,
+ pScrn->virtualX, pScrn->virtualY,
pScrn->depth, pScrn->bitsPerPixel,
pitch,
info->front_bo->handle,
@@ -500,15 +670,15 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
crtc->y = y;
crtc->rotation = rotation;
crtc->transformPresent = FALSE;
- }
- output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
- if (!output_ids) {
- ret = FALSE;
- goto done;
- }
+ output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
+ if (!output_ids) {
+ ret = FALSE;
+ goto done;
+ }
+
+ ScreenPtr pScreen = pScrn->pScreen;
- if (mode) {
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
drmmode_output_private_ptr drmmode_output;
@@ -532,24 +702,76 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
fb_id = drmmode->fb_id;
#ifdef RADEON_PIXMAP_SHARING
if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
- x = drmmode_crtc->scanout_pixmap_x;
+ x = drmmode_crtc->prime_pixmap_x;
y = 0;
+
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
} else
#endif
- if (drmmode_crtc->rotate_fb_id) {
- fb_id = drmmode_crtc->rotate_fb_id;
+ if (drmmode_crtc->rotate.fb_id) {
+ fb_id = drmmode_crtc->rotate.fb_id;
x = y = 0;
+
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
+ } else if (info->tear_free || info->shadow_primary) {
+ for (i = 0; i < (info->tear_free ? 2 : 1); i++) {
+ drmmode_crtc_scanout_create(crtc,
+ &drmmode_crtc->scanout[i],
+ mode->HDisplay,
+ mode->VDisplay);
+
+ if (drmmode_crtc->scanout[i].pixmap) {
+ RegionPtr pRegion;
+ BoxPtr pBox;
+
+ if (!drmmode_crtc->scanout[i].damage) {
+ drmmode_crtc->scanout[i].damage =
+ DamageCreate(radeon_screen_damage_report,
+ NULL, DamageReportRawRegion,
+ TRUE, pScreen, NULL);
+ DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
+ drmmode_crtc->scanout[i].damage);
+ }
+
+ pRegion = DamageRegion(drmmode_crtc->scanout[i].damage);
+ RegionUninit(pRegion);
+ pRegion->data = NULL;
+ pBox = RegionExtents(pRegion);
+ pBox->x1 = min(pBox->x1, x);
+ pBox->y1 = min(pBox->y1, y);
+ pBox->x2 = max(pBox->x2, x + mode->HDisplay);
+ pBox->y2 = max(pBox->y2, y + mode->VDisplay);
+ }
+ }
+
+ if (drmmode_crtc->scanout[0].pixmap &&
+ (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
+ drmmode_crtc->scanout_id = 0;
+ fb_id = drmmode_crtc->scanout[0].fb_id;
+ x = y = 0;
+
+ radeon_scanout_update_handler(pScrn, 0, 0, crtc);
+ radeon_bo_wait(drmmode_crtc->scanout[0].bo);
+ }
}
- ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- fb_id, x, y, output_ids, output_count, &kmode);
- if (ret)
+ if (drmModeSetCrtc(drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ fb_id, x, y, output_ids,
+ output_count, &kmode) != 0) {
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "failed to set mode: %s", strerror(-ret));
- else
+ "failed to set mode: %s", strerror(errno));
+ ret = FALSE;
+ goto done;
+ } else
ret = TRUE;
if (crtc->scrn->pScreen)
xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+
+ drmmode_crtc->need_modeset = FALSE;
+
/* go through all the outputs and force DPMS them back on? */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -576,6 +798,7 @@ done:
else
crtc->active = TRUE;
#endif
+ free(output_ids);
return ret;
}
@@ -634,6 +857,22 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
uint32_t handle = drmmode_crtc->cursor_bo->handle;
+ static Bool use_set_cursor2 = TRUE;
+
+ if (use_set_cursor2) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ CursorPtr cursor = xf86_config->cursor;
+ int ret;
+
+ ret =
+ drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ handle, info->cursor_w, info->cursor_h,
+ cursor->bits->xhot, cursor->bits->yhot);
+ if (ret == -EINVAL)
+ use_set_cursor2 = FALSE;
+ else
+ return;
+ }
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
info->cursor_w, info->cursor_h);
@@ -642,73 +881,22 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
static void *
drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
{
- ScrnInfoPtr pScrn = crtc->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
- int size;
- struct radeon_bo *rotate_bo;
- int ret;
- unsigned long rotate_pitch;
- int base_align;
-
- /* rotation requires acceleration */
- if (info->r600_shadow_fb) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Rotation requires acceleration!\n");
- return NULL;
- }
-
- rotate_pitch =
- RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp;
- height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0));
- base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0);
- size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE);
-
- rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
- if (rotate_bo == NULL)
- return NULL;
- radeon_bo_map(rotate_bo, 1);
-
- ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
- crtc->scrn->bitsPerPixel, rotate_pitch,
- rotate_bo->handle,
- &drmmode_crtc->rotate_fb_id);
- if (ret) {
- ErrorF("failed to add rotate fb\n");
- }
-
- drmmode_crtc->rotate_bo = rotate_bo;
- return drmmode_crtc->rotate_bo->ptr;
+ return drmmode_crtc_scanout_allocate(crtc, &drmmode_crtc->rotate,
+ width, height);
}
static PixmapPtr
drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
{
- ScrnInfoPtr pScrn = crtc->scrn;
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
- unsigned long rotate_pitch;
- PixmapPtr rotate_pixmap;
-
- if (!data)
- data = drmmode_crtc_shadow_allocate (crtc, width, height);
-
- rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp;
-
- rotate_pixmap = drmmode_create_bo_pixmap(pScrn,
- width, height,
- pScrn->depth,
- pScrn->bitsPerPixel,
- rotate_pitch,
- 0, drmmode_crtc->rotate_bo, NULL);
- if (rotate_pixmap == NULL) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Couldn't allocate shadow pixmap for rotated CRTC\n");
- }
- return rotate_pixmap;
+ /* Xorg passes in the return value of drmmode_crtc_shadow_allocate
+ * for data, but that's redundant for drmmode_crtc_scanout_create.
+ */
+ return drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width,
+ height);
}
static void
@@ -717,17 +905,7 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- if (rotate_pixmap)
- drmmode_destroy_bo_pixmap(rotate_pixmap);
-
- if (data) {
- drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
- drmmode_crtc->rotate_fb_id = 0;
- radeon_bo_unmap(drmmode_crtc->rotate_bo);
- radeon_bo_unref(drmmode_crtc->rotate_bo);
- drmmode_crtc->rotate_bo = NULL;
- }
-
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->rotate);
}
static void
@@ -754,7 +932,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
if (!ppix) {
if (crtc->randr_crtc->scanout_pixmap)
PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
- drmmode_crtc->scanout_pixmap_x = 0;
+ drmmode_crtc->prime_pixmap_x = 0;
return TRUE;
}
@@ -793,8 +971,10 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
screen->width = screenpix->drawable.width = total_width;
screen->height = screenpix->drawable.height = max_height;
}
- drmmode_crtc->scanout_pixmap_x = this_x;
-#ifdef HAS_DIRTYTRACKING2
+ drmmode_crtc->prime_pixmap_x = this_x;
+#ifdef HAS_DIRTYTRACKING_ROTATION
+ PixmapStartDirtyTracking(ppix, screenpix, 0, 0, this_x, 0, RR_Rotate_0);
+#elif defined(HAS_DIRTYTRACKING2)
PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
#else
PixmapStartDirtyTracking(ppix, screenpix, 0, 0);
@@ -803,7 +983,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
}
#endif
-static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
+static xf86CrtcFuncsRec drmmode_crtc_funcs = {
.dpms = drmmode_crtc_dpms,
.set_mode_major = drmmode_set_mode_major,
.set_cursor_colors = drmmode_set_cursor_colors,
@@ -849,23 +1029,29 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
drmmode_crtc->hw_id = tmp;
}
-static void
-drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+static unsigned int
+drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
{
xf86CrtcPtr crtc;
drmmode_crtc_private_ptr drmmode_crtc;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
if (crtc == NULL)
- return;
+ return 0;
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
- drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
+ drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
drmmode_crtc->drmmode = drmmode;
crtc->driver_private = drmmode_crtc;
drmmode_crtc_hw_id(crtc);
- return;
+ /* Mark num'th crtc as in use on this device. */
+ pRADEONEnt->assigned_crtcs |= (1 << num);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Allocated crtc nr. %d to this screen.\n", num);
+
+ return 1;
}
static xf86OutputStatus
@@ -975,17 +1161,28 @@ static void
drmmode_output_dpms(xf86OutputPtr output, int mode)
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
+ xf86CrtcPtr crtc = output->crtc;
drmModeConnectorPtr koutput = drmmode_output->mode_output;
drmmode_ptr drmmode = drmmode_output->drmmode;
- if (mode != DPMSModeOn && output->crtc)
- drmmode_do_crtc_dpms(output->crtc, mode);
+ if (!koutput)
+ return;
+
+ if (mode != DPMSModeOn && crtc)
+ drmmode_do_crtc_dpms(crtc, mode);
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
drmmode_output->dpms_enum_id, mode);
- if (mode == DPMSModeOn && output->crtc)
- drmmode_do_crtc_dpms(output->crtc, mode);
+ if (mode == DPMSModeOn && crtc) {
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (drmmode_crtc->need_modeset)
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x,
+ crtc->y);
+ else
+ drmmode_do_crtc_dpms(crtc, mode);
+ }
}
@@ -1194,22 +1391,137 @@ const char *output_names[] = { "None",
#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
+static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output;
+
+ drmmode_output = output->driver_private;
+ if (drmmode_output->output_id == id)
+ return output;
+ }
+ return NULL;
+}
+
+static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
+{
+ char *conn;
+ char conn_id[5];
+ int id, len;
+ char *blob_data;
+
+ if (!path_blob)
+ return -1;
+
+ blob_data = path_blob->data;
+ /* we only handle MST paths for now */
+ if (strncmp(blob_data, "mst:", 4))
+ return -1;
+
+ conn = strchr(blob_data + 4, '-');
+ if (!conn)
+ return -1;
+ len = conn - (blob_data + 4);
+ if (len + 1 > 5)
+ return -1;
+ memcpy(conn_id, blob_data + 4, len);
+ conn_id[len] = '\0';
+ id = strtoul(conn_id, NULL, 10);
+
+ *conn_base_id = id;
+
+ *path = conn + 1;
+ return 0;
+}
+
static void
-drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi)
+drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
+ drmModePropertyBlobPtr path_blob, int *num_dvi, int *num_hdmi)
+{
+ xf86OutputPtr output;
+ int conn_id;
+ char *extra_path;
+
+ output = NULL;
+ if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0)
+ output = find_output(pScrn, conn_id);
+ if (output) {
+ snprintf(name, 32, "%s-%s", output->name, extra_path);
+ } else {
+ if (koutput->connector_type >= NUM_OUTPUT_NAMES)
+ snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
+ koutput->connector_type_id - 1);
+#ifdef RADEON_PIXMAP_SHARING
+ else if (pScrn->is_gpu)
+ snprintf(name, 32, "%s-%d-%d",
+ output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
+ koutput->connector_type_id - 1);
+#endif
+ else {
+ /* need to do smart conversion here for compat with non-kms ATI driver */
+ if (koutput->connector_type_id == 1) {
+ switch(koutput->connector_type) {
+ case DRM_MODE_CONNECTOR_DVII:
+ case DRM_MODE_CONNECTOR_DVID:
+ case DRM_MODE_CONNECTOR_DVIA:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
+ (*num_dvi)++;
+ break;
+ case DRM_MODE_CONNECTOR_HDMIA:
+ case DRM_MODE_CONNECTOR_HDMIB:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
+ (*num_hdmi)++;
+ break;
+ case DRM_MODE_CONNECTOR_VGA:
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
+ koutput->connector_type_id - 1);
+ break;
+ default:
+ snprintf(name, 32, "%s", output_names[koutput->connector_type]);
+ break;
+ }
+ } else {
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
+ koutput->connector_type_id - 1);
+ }
+ }
+ }
+}
+
+static unsigned int
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic)
{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
RADEONInfoPtr info = RADEONPTR(pScrn);
xf86OutputPtr output;
drmModeConnectorPtr koutput;
drmModeEncoderPtr *kencoders = NULL;
drmmode_output_private_ptr drmmode_output;
drmModePropertyPtr props;
+ drmModePropertyBlobPtr path_blob = NULL;
char name[32];
int i;
const char *s;
- koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
+ koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
if (!koutput)
- return;
+ return 0;
+
+ for (i = 0; i < koutput->count_props; i++) {
+ props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
+ if (!strcmp(props->name, "PATH")) {
+ path_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
+ drmModeFreeProperty(props);
+ break;
+ }
+ drmModeFreeProperty(props);
+ }
+ }
kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
if (!kencoders) {
@@ -1223,42 +1535,27 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
}
}
- if (koutput->connector_type >= NUM_OUTPUT_NAMES)
- snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
- koutput->connector_type_id - 1);
-#ifdef RADEON_PIXMAP_SHARING
- else if (pScrn->is_gpu)
- snprintf(name, 32, "%s-%d-%d",
- output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
- koutput->connector_type_id - 1);
-#endif
- else {
- /* need to do smart conversion here for compat with non-kms ATI driver */
- if (koutput->connector_type_id == 1) {
- switch(koutput->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- case DRM_MODE_CONNECTOR_DVID:
- case DRM_MODE_CONNECTOR_DVIA:
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
- (*num_dvi)++;
- break;
- case DRM_MODE_CONNECTOR_HDMIA:
- case DRM_MODE_CONNECTOR_HDMIB:
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
- (*num_hdmi)++;
- break;
- case DRM_MODE_CONNECTOR_VGA:
- case DRM_MODE_CONNECTOR_DisplayPort:
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
- koutput->connector_type_id - 1);
- break;
- default:
- snprintf(name, 32, "%s", output_names[koutput->connector_type]);
- break;
- }
- } else {
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
- koutput->connector_type_id - 1);
+ drmmode_create_name(pScrn, koutput, name, path_blob, num_dvi, num_hdmi);
+ if (path_blob)
+ drmModeFreePropertyBlob(path_blob);
+
+ if (path_blob && dynamic) {
+ /* See if we have an output with this name already
+ * and hook stuff up.
+ */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ output = xf86_config->output[i];
+
+ if (strncmp(output->name, name, 32))
+ continue;
+
+ drmmode_output = output->driver_private;
+ drmmode_output->output_id = mode_res->connectors[num];
+ drmmode_output->mode_output = koutput;
+ for (i = 0; i < koutput->count_encoders; i++)
+ drmModeFreeEncoder(kencoders[i]);
+ free(kencoders);
+ return 0;
}
}
@@ -1267,7 +1564,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
if (!RADEONZaphodStringMatches(pScrn, s, name))
goto out_free_encoders;
} else {
- if (info->IsPrimary && (num != 0))
+ if (!info->IsSecondary && (num != 0))
goto out_free_encoders;
else if (info->IsSecondary && (num != 1))
goto out_free_encoders;
@@ -1285,7 +1582,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
goto out_free_encoders;
}
- drmmode_output->output_id = drmmode->mode_res->connectors[num];
+ drmmode_output->output_id = mode_res->connectors[num];
drmmode_output->mode_output = koutput;
drmmode_output->mode_encoders = kencoders;
drmmode_output->drmmode = drmmode;
@@ -1316,7 +1613,12 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
}
}
- return;
+ if (dynamic) {
+ output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
+ drmmode_output_create_resources(output);
+ }
+
+ return 1;
out_free_encoders:
if (kencoders){
for (i = 0; i < koutput->count_encoders; i++)
@@ -1324,7 +1626,7 @@ out_free_encoders:
free(kencoders);
}
drmModeFreeConnector(koutput);
-
+ return 0;
}
uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
@@ -1354,7 +1656,7 @@ uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
static void
-drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res)
{
int i, j;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1369,8 +1671,8 @@ drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
{
int k;
- for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
- if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
+ for (k = 0; k < mode_res->count_encoders; k++) {
+ if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
drmmode_output->enc_mask |= (1 << k);
}
@@ -1488,6 +1790,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
ScreenPtr screen = xf86ScrnToScreen(scrn);
uint32_t old_fb_id;
int i, pitch, old_width, old_height, old_pitch;
+ int aligned_height;
uint32_t screen_size;
int cpp = info->pixel_bytes;
struct radeon_bo *front_bo;
@@ -1496,6 +1799,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
uint32_t tiling_flags = 0, base_align;
PixmapPtr ppix = screen->GetScreenPixmap(screen);
void *fb_shadow;
+ xRectangle rect;
+ Bool force;
+ GCPtr gc;
if (scrn->virtualX == width && scrn->virtualY == height)
return TRUE;
@@ -1506,7 +1812,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
if (front_bo)
radeon_bo_wait(front_bo);
- if (info->allowColorTiling) {
+ if (info->allowColorTiling && !info->shadow_primary) {
if (info->ChipFamily >= CHIP_FAMILY_R600) {
if (info->allowColorTiling2D) {
tiling_flags |= RADEON_TILING_MACRO;
@@ -1518,8 +1824,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
}
pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
- height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
- screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
+ aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
+ screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
base_align = 4096;
if (info->ChipFamily >= CHIP_FAMILY_R600) {
memset(&surface, 0, sizeof(struct radeon_surface));
@@ -1562,7 +1868,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
- tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
+ if (surface.tile_split)
+ tiling_flags |= eg_tile_split(surface.tile_split)
+ << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
break;
case RADEON_SURF_MODE_1D:
tiling_flags |= RADEON_TILING_MICRO;
@@ -1587,7 +1895,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
scrn->virtualY = height;
scrn->displayWidth = pitch / cpp;
- info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
+ info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
+ info->shadow_primary ?
+ RADEON_GEM_DOMAIN_GTT :
+ RADEON_GEM_DOMAIN_VRAM, 0);
if (!info->front_bo)
goto fail;
@@ -1636,6 +1947,24 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
#endif
+ if (info->use_glamor)
+ radeon_glamor_create_screen_resources(scrn->pScreen);
+
+ /* Clear new buffer */
+ gc = GetScratchGC(ppix->drawable.depth, scrn->pScreen);
+ force = info->accel_state->force;
+ info->accel_state->force = TRUE;
+ ValidateGC(&ppix->drawable, gc);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ (*gc->ops->PolyFillRect)(&ppix->drawable, gc, 1, &rect);
+ FreeScratchGC(gc);
+ info->accel_state->force = force;
+ radeon_cs_flush_indirect(scrn);
+ radeon_bo_wait(info->front_bo);
+
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -1646,9 +1975,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
crtc->rotation, crtc->x, crtc->y);
}
- if (info->use_glamor)
- radeon_glamor_create_screen_resources(scrn->pScreen);
-
if (old_fb_id)
drmModeRmFB(drmmode->fd, old_fb_id);
if (old_front)
@@ -1674,45 +2000,55 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
};
static void
-drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+drmmode_flip_free(drmmode_flipevtcarrier_ptr flipcarrier)
+{
+ drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+
+ free(flipcarrier);
+
+ if (--flipdata->flip_count > 0)
+ return;
+
+ free(flipdata);
+}
+
+static void
+drmmode_flip_abort(ScrnInfoPtr scrn, void *event_data)
{
- radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data);
+ drmmode_flipevtcarrier_ptr flipcarrier = event_data;
+ drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+
+ if (flipdata->flip_count == 1)
+ flipdata->abort(scrn, flipdata->event_data);
+
+ drmmode_flip_free(flipcarrier);
}
static void
-drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data)
{
drmmode_flipevtcarrier_ptr flipcarrier = event_data;
drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
- drmmode_ptr drmmode = flipdata->drmmode;
/* Is this the event whose info shall be delivered to higher level? */
if (flipcarrier->dispatch_me) {
/* Yes: Cache msc, ust for later delivery. */
flipdata->fe_frame = frame;
- flipdata->fe_tv_sec = tv_sec;
- flipdata->fe_tv_usec = tv_usec;
+ flipdata->fe_usec = usec;
}
- free(flipcarrier);
-
- /* Last crtc completed flip? */
- flipdata->flip_count--;
- if (flipdata->flip_count > 0)
- return;
- /* Release framebuffer */
- drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
+ if (flipdata->flip_count == 1) {
+ /* Deliver cached msc, ust from reference crtc to flip event handler */
+ if (flipdata->event_data)
+ flipdata->handler(scrn, flipdata->fe_frame,
+ flipdata->fe_usec,
+ flipdata->event_data);
- if (flipdata->event_data == NULL)
- return;
-
- /* Deliver cached msc, ust from reference crtc to flip event handler */
- radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
- flipdata->fe_tv_usec, flipdata->event_data);
+ /* Release framebuffer */
+ drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id);
+ }
- free(flipdata);
+ drmmode_flip_free(flipcarrier);
}
@@ -1729,26 +2065,51 @@ drm_wakeup_handler(pointer data, int err, pointer p)
Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
{
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ RADEONInfoPtr info = RADEONPTR(pScrn);
int i, num_dvi = 0, num_hdmi = 0;
+ drmModeResPtr mode_res;
+ unsigned int crtcs_needed = 0;
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
drmmode->scrn = pScrn;
drmmode->cpp = cpp;
- drmmode->mode_res = drmModeGetResources(drmmode->fd);
- if (!drmmode->mode_res)
+ mode_res = drmModeGetResources(drmmode->fd);
+ if (!mode_res)
return FALSE;
- xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
- for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
- if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
- drmmode_crtc_init(pScrn, drmmode, i);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing outputs ...\n");
+ for (i = 0; i < mode_res->count_connectors; i++)
+ crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res,
+ i, &num_dvi, &num_hdmi, 0);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "%d crtcs needed for screen.\n", crtcs_needed);
+
+ if (info->r600_shadow_fb) {
+ /* Rotation requires hardware acceleration */
+ drmmode_crtc_funcs.shadow_allocate = NULL;
+ drmmode_crtc_funcs.shadow_create = NULL;
+ drmmode_crtc_funcs.shadow_destroy = NULL;
+ }
- for (i = 0; i < drmmode->mode_res->count_connectors; i++)
- drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
+ 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++)
+ if (!xf86IsEntityShared(pScrn->entityList[0]) ||
+ (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
+ crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
+
+ /* All ZaphodHeads outputs provided with matching crtcs? */
+ if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
+ crtcs_needed);
/* workout clones */
- drmmode_clones_init(pScrn, drmmode);
+ drmmode_clones_init(pScrn, drmmode, mode_res);
#ifdef RADEON_PIXMAP_SHARING
xf86ProviderSetup(pScrn, NULL, "radeon");
@@ -1757,9 +2118,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
xf86InitialConfiguration(pScrn, TRUE);
drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
- drmmode->event_context.vblank_handler = drmmode_vblank_handler;
- drmmode->event_context.page_flip_handler = drmmode_flip_handler;
+ drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
+ drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
+ drmModeFreeResources(mode_res);
return TRUE;
}
@@ -1828,13 +2190,12 @@ void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
}
}
-Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
+ Bool set_hw)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
- drmmode_copy_fb(pScrn, drmmode);
-
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
@@ -1843,9 +2204,12 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
/* Skip disabled CRTCs */
if (!crtc->enabled) {
- drmmode_do_crtc_dpms(crtc, DPMSModeOff);
- drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- 0, 0, 0, NULL, 0, NULL);
+ if (set_hw) {
+ drmmode_do_crtc_dpms(crtc, DPMSModeOff);
+ drmModeSetCrtc(drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+ }
continue;
}
@@ -1878,9 +2242,18 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
crtc->desiredY = 0;
}
- if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
- crtc->desiredX, crtc->desiredY))
- return FALSE;
+ if (set_hw) {
+ if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
+ crtc->desiredX, crtc->desiredY))
+ return FALSE;
+ } else {
+ crtc->mode = crtc->desiredMode;
+ crtc->rotation = crtc->desiredRotation;
+ crtc->x = crtc->desiredX;
+ crtc->y = crtc->desiredY;
+ if (!xf86CrtcRotate(crtc))
+ return FALSE;
+ }
}
return TRUE;
}
@@ -1970,6 +2343,75 @@ Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
return TRUE;
}
+void
+radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ drmModeResPtr mode_res;
+ int i, j;
+ Bool found;
+ Bool changed = FALSE;
+
+ mode_res = drmModeGetResources(drmmode->fd);
+ if (!mode_res)
+ goto out;
+
+restart_destroy:
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ found = FALSE;
+ for (j = 0; j < mode_res->count_connectors; j++) {
+ if (mode_res->connectors[j] == drmmode_output->output_id) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ drmModeFreeConnector(drmmode_output->mode_output);
+ drmmode_output->mode_output = NULL;
+ drmmode_output->output_id = -1;
+
+ changed = TRUE;
+ if (drmmode->delete_dp_12_displays) {
+ RROutputDestroy(output->randr_output);
+ xf86OutputDestroy(output);
+ goto restart_destroy;
+ }
+ }
+
+ /* find new output ids we don't have outputs for */
+ for (i = 0; i < mode_res->count_connectors; i++) {
+ found = FALSE;
+
+ for (j = 0; j < config->num_output; j++) {
+ xf86OutputPtr output = config->output[j];
+ drmmode_output_private_ptr drmmode_output;
+
+ drmmode_output = output->driver_private;
+ if (mode_res->connectors[i] == drmmode_output->output_id) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ changed = TRUE;
+ drmmode_output_init(scrn, drmmode, mode_res, i, NULL, NULL, 1);
+ }
+
+ if (changed) {
+ RRSetChanged(xf86ScrnToScreen(scrn));
+ RRTellChanged(xf86ScrnToScreen(scrn));
+ }
+
+ drmModeFreeResources(mode_res);
+out:
+ RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
+}
#ifdef HAVE_LIBUDEV
static void
drmmode_handle_uevents(int fd, void *closure)
@@ -1981,7 +2423,7 @@ drmmode_handle_uevents(int fd, void *closure)
if (!dev)
return;
- RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
+ radeon_mode_hotplug(scrn, drmmode);
udev_device_unref(dev);
}
#endif
@@ -2035,18 +2477,21 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
#endif
}
-Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
+Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+ uint32_t new_front_handle, uint64_t id, void *data,
+ int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort)
{
RADEONInfoPtr info = RADEONPTR(scrn);
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
unsigned int pitch;
- int i, old_fb_id;
+ int i;
uint32_t tiling_flags = 0;
- int height, emitted = 0;
drmmode_flipdata_ptr flipdata;
- drmmode_flipevtcarrier_ptr flipcarrier;
+ drmmode_flipevtcarrier_ptr flipcarrier = NULL;
+ struct radeon_drm_queue_entry *drm_queue = NULL;
if (info->allowColorTiling) {
if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -2057,26 +2502,26 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->pixel_bytes, tiling_flags)) *
info->pixel_bytes;
- height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
pitch = info->front_surface.level[0].pitch_bytes;
}
- /*
- * Create a new handle for the back buffer
- */
- old_fb_id = drmmode->fb_id;
- if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
- scrn->depth, scrn->bitsPerPixel, pitch,
- new_front->handle, &drmmode->fb_id))
- goto error_out;
-
flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
if (!flipdata) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue: data alloc failed.\n");
- goto error_undo;
+ goto error;
}
+
+ /*
+ * Create a new handle for the back buffer
+ */
+ flipdata->old_fb_id = drmmode->fb_id;
+ if (drmModeAddFB(drmmode->fd, scrn->virtualX, scrn->virtualY,
+ scrn->depth, scrn->bitsPerPixel, pitch,
+ new_front_handle, &drmmode->fb_id))
+ goto error;
+
/*
* Queue flips on all enabled CRTCs
* Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -2089,6 +2534,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
flipdata->event_data = data;
flipdata->drmmode = drmmode;
+ flipdata->handler = handler;
+ flipdata->abort = abort;
for (i = 0; i < config->num_crtc; i++) {
if (!config->crtc[i]->enabled)
@@ -2101,9 +2548,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
if (!flipcarrier) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue: carrier alloc failed.\n");
- if (emitted == 0)
- free(flipdata);
- goto error_undo;
+ goto error;
}
/* Only the reference crtc will finally deliver its page flip
@@ -2112,28 +2557,44 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
flipcarrier->flipdata = flipdata;
+ drm_queue = radeon_drm_queue_alloc(scrn, client, id,
+ flipcarrier,
+ drmmode_flip_handler,
+ drmmode_flip_abort);
+ if (!drm_queue) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM queue event entry failed.\n");
+ goto error;
+ }
+
if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
+ drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
+ drm_queue)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue failed: %s\n", strerror(errno));
- free(flipcarrier);
- if (emitted == 0)
- free(flipdata);
- goto error_undo;
+ goto error;
}
- emitted++;
+ flipcarrier = NULL;
+ drm_queue = NULL;
}
- flipdata->old_fb_id = old_fb_id;
- return TRUE;
+ if (flipdata->flip_count > 0)
+ return TRUE;
-error_undo:
- drmModeRmFB(drmmode->fd, drmmode->fb_id);
- drmmode->fb_id = old_fb_id;
+error:
+ if (flipdata && flipdata->flip_count <= 1) {
+ drmModeRmFB(drmmode->fd, drmmode->fb_id);
+ drmmode->fb_id = flipdata->old_fb_id;
+ }
+
+ if (drm_queue)
+ radeon_drm_abort_entry(drm_queue);
+ else if (flipcarrier)
+ drmmode_flip_abort(scrn, flipcarrier);
+ else if (flipdata && flipdata->flip_count <= 1)
+ free(flipdata);
-error_out:
xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
strerror(errno));
return FALSE;
}
-
diff --git a/driver/xf86-video-ati/src/drmmode_display.h b/driver/xf86-video-ati/src/drmmode_display.h
index 41e29f624..ab6c5908a 100644
--- a/driver/xf86-video-ati/src/drmmode_display.h
+++ b/driver/xf86-video-ati/src/drmmode_display.h
@@ -32,6 +32,7 @@
#include "libudev.h"
#endif
+#include "radeon_drm_queue.h"
#include "radeon_probe.h"
#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
@@ -41,7 +42,6 @@
typedef struct {
int fd;
unsigned fb_id;
- drmModeResPtr mode_res;
drmModeFBPtr mode_fb;
int cpp;
struct radeon_bo_manager *bufmgr;
@@ -51,6 +51,12 @@ typedef struct {
InputHandlerProc uevent_handler;
#endif
drmEventContext event_context;
+ int count_crtcs;
+
+ Bool delete_dp_12_displays;
+
+ Bool dri2_flipping;
+ Bool present_flipping;
} drmmode_rec, *drmmode_ptr;
typedef struct {
@@ -59,8 +65,9 @@ typedef struct {
int flip_count;
void *event_data;
unsigned int fe_frame;
- unsigned int fe_tv_sec;
- unsigned int fe_tv_usec;
+ uint64_t fe_usec;
+ radeon_drm_handler_proc handler;
+ radeon_drm_abort_proc abort;
} drmmode_flipdata_rec, *drmmode_flipdata_ptr;
typedef struct {
@@ -68,20 +75,33 @@ typedef struct {
Bool dispatch_me;
} drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
+struct drmmode_scanout {
+ struct radeon_bo *bo;
+ PixmapPtr pixmap;
+ DamagePtr damage;
+ unsigned fb_id;
+ int width, height;
+};
+
typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
int hw_id;
struct radeon_bo *cursor_bo;
- struct radeon_bo *rotate_bo;
- unsigned rotate_fb_id;
+ struct drmmode_scanout rotate;
+ struct drmmode_scanout scanout[2];
+ unsigned scanout_id;
+ Bool scanout_update_pending;
int dpms_mode;
CARD64 dpms_last_ust;
uint32_t dpms_last_seq;
int dpms_last_fps;
uint32_t interpolated_vblanks;
uint16_t lut_r[256], lut_g[256], lut_b[256];
- int scanout_pixmap_x;
+ int prime_pixmap_x;
+
+ /* Modeset needed for DPMS on */
+ Bool need_modeset;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
@@ -112,18 +132,28 @@ 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);
+extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
+ Bool set_hw);
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+#endif
extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+extern void drmmode_scanout_free(ScrnInfoPtr scrn);
+
extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
+extern int drmmode_get_crtc_id(xf86CrtcPtr crtc);
extern int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling);
extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
-Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id);
+Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+ uint32_t new_front_handle, uint64_t id, void *data,
+ int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort);
+int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
int drmmode_get_current_ust(int drm_fd, CARD64 *ust);
#endif
diff --git a/driver/xf86-video-ati/src/evergreen_accel.c b/driver/xf86-video-ati/src/evergreen_accel.c
index 41ebc1a9f..43146bbfa 100644
--- a/driver/xf86-video-ati/src/evergreen_accel.c
+++ b/driver/xf86-video-ati/src/evergreen_accel.c
@@ -79,9 +79,9 @@ unsigned eg_tile_split(unsigned tile_split)
case 128: tile_split = 1; break;
case 256: tile_split = 2; break;
case 512: tile_split = 3; break;
+ default:
case 1024: tile_split = 4; break;
case 2048: tile_split = 5; break;
- default:
case 4096: tile_split = 6; break;
}
return tile_split;
diff --git a/driver/xf86-video-ati/src/pcidb/ati_pciids.csv b/driver/xf86-video-ati/src/pcidb/ati_pciids.csv
index 1c92f5b52..55d7b1dfd 100644
--- a/driver/xf86-video-ati/src/pcidb/ati_pciids.csv
+++ b/driver/xf86-video-ati/src/pcidb/ati_pciids.csv
@@ -693,6 +693,7 @@
"0x6610","OLAND_6610","OLAND",,,,,,"OLAND"
"0x6611","OLAND_6611","OLAND",,,,,,"OLAND"
"0x6613","OLAND_6613","OLAND",,,,,,"OLAND"
+"0x6617","OLAND_6617","OLAND",1,,,,,"OLAND"
"0x6620","OLAND_6620","OLAND",1,,,,,"OLAND"
"0x6621","OLAND_6621","OLAND",1,,,,,"OLAND"
"0x6623","OLAND_6623","OLAND",1,,,,,"OLAND"
@@ -713,6 +714,7 @@
"0x6658","BONAIRE_6658","BONAIRE",,,,,,"BONAIRE"
"0x665C","BONAIRE_665C","BONAIRE",,,,,,"BONAIRE"
"0x665D","BONAIRE_665D","BONAIRE",,,,,,"BONAIRE"
+"0x665F","BONAIRE_665F","BONAIRE",,,,,,"BONAIRE"
"0x9830","KABINI_9830","KABINI",1,1,,,1,"KABINI"
"0x9831","KABINI_9831","KABINI",,1,,,1,"KABINI"
"0x9832","KABINI_9832","KABINI",1,1,,,1,"KABINI"
diff --git a/driver/xf86-video-ati/src/radeon.h b/driver/xf86-video-ati/src/radeon.h
index 6123cc26a..e2fd41cfd 100644
--- a/driver/xf86-video-ati/src/radeon.h
+++ b/driver/xf86-video-ati/src/radeon.h
@@ -51,8 +51,6 @@
#include "exa.h"
-#include "radeon_glamor.h"
-
/* Exa and Cursor Support */
#include "xf86Cursor.h"
@@ -92,6 +90,8 @@
#include "simple_list.h"
#include "atipcirename.h"
+struct _SyncFence;
+
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
@@ -148,7 +148,12 @@ typedef enum {
OPTION_ACCELMETHOD,
OPTION_EXA_VSYNC,
OPTION_ZAPHOD_HEADS,
- OPTION_SWAPBUFFERS_WAIT
+ OPTION_SWAPBUFFERS_WAIT,
+ OPTION_DELETE_DP12,
+ OPTION_DRI3,
+ OPTION_DRI,
+ OPTION_SHADOW_PRIMARY,
+ OPTION_TEAR_FREE,
} RADEONOpts;
@@ -241,6 +246,47 @@ typedef enum {
#define CURSOR_WIDTH_CIK 128
#define CURSOR_HEIGHT_CIK 128
+
+#ifdef USE_GLAMOR
+
+struct radeon_pixmap {
+ struct radeon_surface surface;
+
+ uint_fast32_t gpu_read;
+ uint_fast32_t gpu_write;
+
+ struct radeon_bo *bo;
+
+ uint32_t tiling_flags;
+
+ /* GEM handle for glamor-only pixmaps shared via DRI3 */
+ Bool handle_valid;
+ uint32_t handle;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec glamor_pixmap_index;
+#else
+extern int glamor_pixmap_index;
+#endif
+
+static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
+{
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#else
+ return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#endif
+}
+
+static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
+{
+ dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
+}
+
+#endif /* USE_GLAMOR */
+
+
struct radeon_exa_pixmap_priv {
struct radeon_bo *bo;
uint32_t tiling_flags;
@@ -412,6 +458,9 @@ typedef struct {
void (*BlockHandler)(BLOCKHANDLER_ARGS_DECL);
+ void (*CreateFence) (ScreenPtr pScreen, struct _SyncFence *pFence,
+ Bool initially_triggered);
+
int pix24bpp; /* Depth of pixmap for 24bpp fb */
Bool dac6bits; /* Use 6 bit DAC? */
@@ -419,15 +468,19 @@ typedef struct {
Bool directRenderingEnabled;
struct radeon_dri2 dri2;
- Bool accelDFS;
/* accel */
Bool RenderAccel; /* Render */
Bool allowColorTiling;
Bool allowColorTiling2D;
+ uint_fast32_t gpu_flushed;
+ uint_fast32_t gpu_synced;
struct radeon_accel_state *accel_state;
+ PixmapPtr fbcon_pixmap;
Bool accelOn;
Bool use_glamor;
+ Bool shadow_primary;
+ Bool tear_free;
Bool exa_pixmaps;
Bool exa_force_create;
XF86ModReqInfo exaReq;
@@ -442,9 +495,11 @@ typedef struct {
DisplayModePtr currentMode;
CreateScreenResourcesProcPtr CreateScreenResources;
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+ CreateWindowProcPtr CreateWindow;
+#endif
Bool IsSecondary;
- Bool IsPrimary;
Bool r600_shadow_fb;
void *fb_shadow;
@@ -483,6 +538,31 @@ typedef struct {
/* cursor size */
int cursor_w;
int cursor_h;
+
+#ifdef USE_GLAMOR
+ struct {
+ CreateGCProcPtr SavedCreateGC;
+ RegionPtr (*SavedCopyArea)(DrawablePtr, DrawablePtr, GCPtr, int, int,
+ int, int, int, int);
+ void (*SavedPolyFillRect)(DrawablePtr, GCPtr, int, xRectangle*);
+ CloseScreenProcPtr SavedCloseScreen;
+ GetImageProcPtr SavedGetImage;
+ GetSpansProcPtr SavedGetSpans;
+ CreatePixmapProcPtr SavedCreatePixmap;
+ DestroyPixmapProcPtr SavedDestroyPixmap;
+ CopyWindowProcPtr SavedCopyWindow;
+ ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
+ BitmapToRegionProcPtr SavedBitmapToRegion;
+#ifdef RENDER
+ CompositeProcPtr SavedComposite;
+ TrianglesProcPtr SavedTriangles;
+ GlyphsProcPtr SavedGlyphs;
+ TrapezoidsProcPtr SavedTrapezoids;
+ AddTrapsProcPtr SavedAddTraps;
+ UnrealizeGlyphProcPtr SavedUnrealizeGlyph;
+#endif
+ } glamor;
+#endif /* USE_GLAMOR */
} RADEONInfoRec, *RADEONInfoPtr;
/* radeon_accel.c */
@@ -512,6 +592,20 @@ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type);
extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
uint32_t *pitch_offset);
+/* radeon_dri3.c */
+Bool radeon_dri3_screen_init(ScreenPtr screen);
+
+/* radeon_kms.c */
+void radeon_scanout_update_handler(ScrnInfoPtr scrn, uint32_t frame,
+ uint64_t usec, void *event_data);
+
+/* radeon_present.c */
+Bool radeon_present_screen_init(ScreenPtr screen);
+
+/* radeon_sync.c */
+extern Bool radeon_sync_init(ScreenPtr screen);
+extern void radeon_sync_close(ScreenPtr screen);
+
/* radeon_video.c */
extern void RADEONInitVideo(ScreenPtr pScreen);
extern void RADEONResetVideo(ScrnInfoPtr pScrn);
@@ -630,7 +724,7 @@ static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
{
struct radeon_exa_pixmap_priv *driver_priv;
driver_priv = exaGetPixmapDriverPrivate(pPix);
- return driver_priv->bo;
+ return driver_priv ? driver_priv->bo : NULL;
}
return NULL;
@@ -786,6 +880,7 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
}
enum {
+ RADEON_CREATE_PIXMAP_SCANOUT = 0x02000000,
RADEON_CREATE_PIXMAP_DRI2 = 0x04000000,
RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE = 0x08000000,
RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000,
diff --git a/driver/xf86-video-ati/src/radeon_accel.c b/driver/xf86-video-ati/src/radeon_accel.c
index 8eff5c52a..1def2a3fb 100644
--- a/driver/xf86-video-ati/src/radeon_accel.c
+++ b/driver/xf86-video-ati/src/radeon_accel.c
@@ -78,6 +78,7 @@
#include <assert.h>
/* Driver data structures */
#include "radeon.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
#include "r600_reg.h"
#include "radeon_probe.h"
diff --git a/driver/xf86-video-ati/src/radeon_bo_helper.c b/driver/xf86-video-ati/src/radeon_bo_helper.c
index ed964d7b0..ce964e0ea 100644
--- a/driver/xf86-video-ati/src/radeon_bo_helper.c
+++ b/driver/xf86-video-ati/src/radeon_bo_helper.c
@@ -25,6 +25,7 @@
#endif
#include "radeon.h"
+#include "radeon_glamor.h"
#ifdef RADEON_PIXMAP_SHARING
#include "radeon_bo_gem.h"
@@ -87,12 +88,15 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
+ if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
+ info->shadow_primary)
#ifdef CREATE_PIXMAP_USAGE_SHARED
- if ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) {
+ || (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED
+#endif
+ ) {
tiling = 0;
domain = RADEON_GEM_DOMAIN_GTT;
}
-#endif
}
/* Small pixmaps must not be macrotiled on R300, hw cannot sample them
@@ -164,7 +168,8 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
- tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
+ if (surface.tile_split)
+ tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
break;
case RADEON_SURF_MODE_1D:
@@ -187,6 +192,87 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
return bo;
}
+/* Get GEM handle for the pixmap */
+Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle)
+{
+ struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+#ifdef USE_GLAMOR
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
+#endif
+
+ if (bo) {
+ *handle = bo->handle;
+ return TRUE;
+ }
+
+#ifdef USE_GLAMOR
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+ CARD16 stride;
+ CARD32 size;
+ int fd, r;
+
+ if (!priv) {
+ priv = calloc(1, sizeof(*priv));
+ radeon_set_pixmap_private(pixmap, priv);
+ }
+
+ if (priv->handle_valid) {
+ *handle = priv->handle;
+ return TRUE;
+ }
+
+ fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
+ if (fd < 0)
+ return FALSE;
+
+ r = drmPrimeFDToHandle(info->dri2.drm_fd, fd, &priv->handle);
+ close(fd);
+ if (r == 0) {
+ struct drm_radeon_gem_set_tiling args = { .handle = priv->handle };
+
+ priv->handle_valid = TRUE;
+ *handle = priv->handle;
+
+ if (drmCommandWriteRead(info->dri2.drm_fd,
+ DRM_RADEON_GEM_GET_TILING, &args,
+ sizeof(args)) == 0)
+ priv->tiling_flags = args.tiling_flags;
+
+ return TRUE;
+ }
+ }
+#endif
+
+ return FALSE;
+}
+
+uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
+
+ if (!priv || (!priv->bo && !priv->handle_valid)) {
+ uint32_t handle;
+
+ radeon_get_pixmap_handle(pPix, &handle);
+ priv = radeon_get_pixmap_private(pPix);
+ }
+
+ return priv ? priv->tiling_flags : 0;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ return driver_priv ? driver_priv->tiling_flags : 0;
+ }
+}
+
#ifdef RADEON_PIXMAP_SHARING
Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
@@ -200,6 +286,21 @@ Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
return TRUE;
}
+static unsigned eg_tile_split_opp(unsigned tile_split)
+{
+ switch (tile_split) {
+ case 0: tile_split = 64; break;
+ case 1: tile_split = 128; break;
+ case 2: tile_split = 256; break;
+ case 3: tile_split = 512; break;
+ default:
+ case 4: tile_split = 1024; break;
+ case 5: tile_split = 2048; break;
+ case 6: tile_split = 4096; break;
+ }
+ return tile_split;
+}
+
Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
struct radeon_surface *surface)
{
@@ -215,7 +316,22 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
memset(surface, 0, sizeof(struct radeon_surface));
+ radeon_set_pixmap_bo(ppix, bo);
+
if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+ uint32_t tiling_flags;
+
+#ifdef USE_GLAMOR
+ if (info->use_glamor) {
+ tiling_flags = radeon_get_pixmap_private(ppix)->tiling_flags;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+
+ driver_priv = exaGetPixmapDriverPrivate(ppix);
+ tiling_flags = driver_priv->tiling_flags;
+ }
surface->npix_x = ppix->drawable.width;
surface->npix_y = ppix->drawable.height;
@@ -229,7 +345,17 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
/* we are requiring a recent enough libdrm version */
surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
- surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+ if (tiling_flags & RADEON_TILING_MACRO)
+ surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+ else if (tiling_flags & RADEON_TILING_MICRO)
+ surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+ else
+ surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
+ surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK;
+ surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK;
+ surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK);
+ surface->stencil_tile_split = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK;
+ surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
if (radeon_surface_best(info->surf_man, surface)) {
return FALSE;
}
@@ -241,7 +367,6 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
surface->level[0].pitch_bytes = ppix->devKind;
surface->level[0].nblk_x = ppix->devKind / surface->bpe;
}
- radeon_set_pixmap_bo(ppix, bo);
close(ihandle);
/* we have a reference from the alloc and one from set pixmap bo,
diff --git a/driver/xf86-video-ati/src/radeon_bo_helper.h b/driver/xf86-video-ati/src/radeon_bo_helper.h
index 9c3d73f97..d4a4ee018 100644
--- a/driver/xf86-video-ati/src/radeon_bo_helper.h
+++ b/driver/xf86-video-ati/src/radeon_bo_helper.h
@@ -29,6 +29,12 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
struct radeon_surface *new_surface, uint32_t *new_tiling);
extern Bool
+radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle);
+
+extern uint32_t
+radeon_get_pixmap_tiling_flags(PixmapPtr pPix);
+
+extern Bool
radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p);
extern Bool
diff --git a/driver/xf86-video-ati/src/radeon_chipinfo_gen.h b/driver/xf86-video-ati/src/radeon_chipinfo_gen.h
index 40577c9eb..91ef8df8a 100644
--- a/driver/xf86-video-ati/src/radeon_chipinfo_gen.h
+++ b/driver/xf86-video-ati/src/radeon_chipinfo_gen.h
@@ -612,6 +612,7 @@ static RADEONCardInfo RADEONCards[] = {
{ 0x6610, CHIP_FAMILY_OLAND, 0, 0, 0, 0, 0 },
{ 0x6611, CHIP_FAMILY_OLAND, 0, 0, 0, 0, 0 },
{ 0x6613, CHIP_FAMILY_OLAND, 0, 0, 0, 0, 0 },
+ { 0x6617, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
{ 0x6620, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
{ 0x6621, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
{ 0x6623, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
@@ -632,6 +633,7 @@ static RADEONCardInfo RADEONCards[] = {
{ 0x6658, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
{ 0x665C, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
{ 0x665D, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
+ { 0x665F, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
{ 0x9830, CHIP_FAMILY_KABINI, 1, 1, 0, 0, 1 },
{ 0x9831, CHIP_FAMILY_KABINI, 0, 1, 0, 0, 1 },
{ 0x9832, CHIP_FAMILY_KABINI, 1, 1, 0, 0, 1 },
diff --git a/driver/xf86-video-ati/src/radeon_chipset_gen.h b/driver/xf86-video-ati/src/radeon_chipset_gen.h
index e3f23b6c9..5d6d2334e 100644
--- a/driver/xf86-video-ati/src/radeon_chipset_gen.h
+++ b/driver/xf86-video-ati/src/radeon_chipset_gen.h
@@ -612,6 +612,7 @@ SymTabRec RADEONChipsets[] = {
{ PCI_CHIP_OLAND_6610, "OLAND" },
{ PCI_CHIP_OLAND_6611, "OLAND" },
{ PCI_CHIP_OLAND_6613, "OLAND" },
+ { PCI_CHIP_OLAND_6617, "OLAND" },
{ PCI_CHIP_OLAND_6620, "OLAND" },
{ PCI_CHIP_OLAND_6621, "OLAND" },
{ PCI_CHIP_OLAND_6623, "OLAND" },
@@ -632,6 +633,7 @@ SymTabRec RADEONChipsets[] = {
{ PCI_CHIP_BONAIRE_6658, "BONAIRE" },
{ PCI_CHIP_BONAIRE_665C, "BONAIRE" },
{ PCI_CHIP_BONAIRE_665D, "BONAIRE" },
+ { PCI_CHIP_BONAIRE_665F, "BONAIRE" },
{ PCI_CHIP_KABINI_9830, "KABINI" },
{ PCI_CHIP_KABINI_9831, "KABINI" },
{ PCI_CHIP_KABINI_9832, "KABINI" },
diff --git a/driver/xf86-video-ati/src/radeon_dri2.c b/driver/xf86-video-ati/src/radeon_dri2.c
index 9a9918b0f..d30bbd0bd 100644
--- a/driver/xf86-video-ati/src/radeon_dri2.c
+++ b/driver/xf86-video-ati/src/radeon_dri2.c
@@ -40,25 +40,13 @@
#include <fcntl.h>
#include <errno.h>
+#include "radeon_bo_helper.h"
#include "radeon_version.h"
-
-#if HAVE_LIST_H
-#include "list.h"
-#if !HAVE_XORG_LIST
-#define xorg_list list
-#define xorg_list_init list_init
-#define xorg_list_add list_add
-#define xorg_list_del list_del
-#define xorg_list_for_each_entry list_for_each_entry
-#endif
-#endif
-
+#include "radeon_list.h"
#include "radeon_bo_gem.h"
-#if DRI2INFOREC_VERSION >= 4 && HAVE_LIST_H
-#define USE_DRI2_SCHEDULING
-#endif
+#include <xf86Priv.h>
#if DRI2INFOREC_VERSION >= 9
#define USE_DRI2_PRIME
@@ -66,9 +54,7 @@
#define FALLBACK_SWAP_DELAY 16
-#ifdef USE_GLAMOR
-#include <glamor.h>
-#endif
+#include "radeon_glamor.h"
typedef DRI2BufferPtr BufferPtr;
@@ -79,6 +65,28 @@ struct dri2_buffer_priv {
};
+struct dri2_window_priv {
+ xf86CrtcPtr crtc;
+ int vblank_delta;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+
+static DevPrivateKeyRec dri2_window_private_key_rec;
+#define dri2_window_private_key (&dri2_window_private_key_rec)
+
+#else
+
+static int dri2_window_private_key_index;
+DevPrivateKey dri2_window_private_key = &dri2_window_private_key_index;
+
+#endif /* HAS_DEVPRIVATEKEYREC */
+
+#define get_dri2_window_priv(window) \
+ ((struct dri2_window_priv*) \
+ dixLookupPrivate(&(window)->devPrivates, dri2_window_private_key))
+
+
static PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
{
if (drawable->type == DRAWABLE_PIXMAP)
@@ -125,21 +133,43 @@ static PixmapPtr fixup_glamor(DrawablePtr drawable, PixmapPtr pixmap)
/* And redirect the pixmap to the new bo (for 3D). */
glamor_egl_exchange_buffers(old, pixmap);
radeon_set_pixmap_private(old, priv);
- screen->DestroyPixmap(pixmap);
old->refcnt++;
screen->ModifyPixmapHeader(old,
old->drawable.width,
old->drawable.height,
0, 0,
- priv->stride,
+ pixmap->devKind,
NULL);
+ old->devPrivate.ptr = NULL;
+
+ screen->DestroyPixmap(pixmap);
#endif /* USE_GLAMOR*/
return old;
}
+/* Get GEM flink name for a pixmap */
+static Bool
+radeon_get_flink_name(RADEONInfoPtr info, PixmapPtr pixmap, uint32_t *name)
+{
+ struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+ struct drm_gem_flink flink;
+
+ if (bo)
+ return radeon_gem_get_kernel_name(bo, name) == 0;
+
+ if (radeon_get_pixmap_handle(pixmap, &flink.handle)) {
+ if (drmIoctl(info->dri2.drm_fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
+ return FALSE;
+
+ *name = flink.name;
+ return TRUE;
+ }
+
+ return FALSE;
+}
static BufferPtr
radeon_dri2_create_buffer2(ScreenPtr pScreen,
@@ -151,8 +181,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
RADEONInfoPtr info = RADEONPTR(pScrn);
BufferPtr buffers;
struct dri2_buffer_priv *privates;
- PixmapPtr pixmap, depth_pixmap;
- struct radeon_bo *bo;
+ PixmapPtr pixmap;
int flags;
unsigned front_width;
uint32_t tiling = 0;
@@ -180,25 +209,23 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
cpp = drawable->bitsPerPixel / 8;
}
- pixmap = pScreen->GetScreenPixmap(pScreen);
- front_width = pixmap->drawable.width;
+ front_width = pScreen->GetScreenPixmap(pScreen)->drawable.width;
- pixmap = depth_pixmap = NULL;
+ pixmap = NULL;
if (attachment == DRI2BufferFrontLeft) {
+ uint32_t handle;
+
pixmap = get_drawable_pixmap(drawable);
if (pScreen != pixmap->drawable.pScreen)
pixmap = NULL;
- else if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+ else if (info->use_glamor && !radeon_get_pixmap_handle(pixmap, &handle)) {
is_glamor_pixmap = TRUE;
aligned_width = pixmap->drawable.width;
height = pixmap->drawable.height;
pixmap = NULL;
} else
pixmap->refcnt++;
- } else if (attachment == DRI2BufferStencil && depth_pixmap) {
- pixmap = depth_pixmap;
- pixmap->refcnt++;
}
if (!pixmap && (is_glamor_pixmap || attachment != DRI2BufferFrontLeft)) {
@@ -283,10 +310,6 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
if (buffers == NULL)
goto error;
- if (attachment == DRI2BufferDepth) {
- depth_pixmap = pixmap;
- }
-
if (pixmap) {
if (!info->use_glamor) {
info->exa_force_create = TRUE;
@@ -300,8 +323,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
if (is_glamor_pixmap)
pixmap = fixup_glamor(drawable, pixmap);
- bo = radeon_get_pixmap_bo(pixmap);
- if (!bo || radeon_gem_get_kernel_name(bo, &buffers->name) != 0)
+ if (!radeon_get_flink_name(info, pixmap, &buffers->name))
goto error;
}
@@ -490,8 +512,6 @@ radeon_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
pDstBuffer, pSrcBuffer);
}
-#ifdef USE_DRI2_SCHEDULING
-
enum DRI2FrameEventType {
DRI2_SWAP,
DRI2_FLIP,
@@ -502,67 +522,20 @@ typedef struct _DRI2FrameEvent {
XID drawable_id;
ClientPtr client;
enum DRI2FrameEventType type;
- int frame;
+ unsigned frame;
xf86CrtcPtr crtc;
+ OsTimerPtr timer;
+ struct radeon_drm_queue_entry *drm_queue;
/* for swaps & flips only */
DRI2SwapEventPtr event_complete;
void *event_data;
DRI2BufferPtr front;
DRI2BufferPtr back;
-
- Bool valid;
-
- struct xorg_list link;
} DRI2FrameEventRec, *DRI2FrameEventPtr;
-typedef struct _DRI2ClientEvents {
- struct xorg_list reference_list;
-} DRI2ClientEventsRec, *DRI2ClientEventsPtr;
-
-#if HAS_DEVPRIVATEKEYREC
-
static int DRI2InfoCnt;
-static DevPrivateKeyRec DRI2ClientEventsPrivateKeyRec;
-#define DRI2ClientEventsPrivateKey (&DRI2ClientEventsPrivateKeyRec)
-
-#else
-
-static int DRI2ClientEventsPrivateKeyIndex;
-DevPrivateKey DRI2ClientEventsPrivateKey = &DRI2ClientEventsPrivateKeyIndex;
-
-#endif /* HAS_DEVPRIVATEKEYREC */
-
-#define GetDRI2ClientEvents(pClient) ((DRI2ClientEventsPtr) \
- dixLookupPrivate(&(pClient)->devPrivates, DRI2ClientEventsPrivateKey))
-
-static int
-ListAddDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
- DRI2ClientEventsPtr pClientPriv;
- pClientPriv = GetDRI2ClientEvents(client);
-
- if (!pClientPriv) {
- return BadAlloc;
- }
-
- xorg_list_add(entry, &pClientPriv->reference_list);
- return 0;
-}
-
-static void
-ListDelDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
- DRI2ClientEventsPtr pClientPriv;
- pClientPriv = GetDRI2ClientEvents(client);
-
- if (!pClientPriv) {
- return;
- }
- xorg_list_del(entry);
-}
-
static void
radeon_dri2_ref_buffer(BufferPtr buffer)
{
@@ -582,52 +555,159 @@ radeon_dri2_unref_buffer(BufferPtr buffer)
static void
radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer data, pointer calldata)
{
- DRI2ClientEventsPtr pClientEventsPriv;
- DRI2FrameEventPtr ref;
NewClientInfoRec *clientinfo = calldata;
ClientPtr pClient = clientinfo->client;
- pClientEventsPriv = GetDRI2ClientEvents(pClient);
switch (pClient->clientState) {
- case ClientStateInitial:
- xorg_list_init(&pClientEventsPriv->reference_list);
- break;
- case ClientStateRunning:
- break;
-
case ClientStateRetained:
case ClientStateGone:
- if (pClientEventsPriv) {
- xorg_list_for_each_entry(ref, &pClientEventsPriv->reference_list, link) {
- ref->valid = FALSE;
- radeon_dri2_unref_buffer(ref->front);
- radeon_dri2_unref_buffer(ref->back);
- }
- }
+ radeon_drm_abort_client(pClient);
break;
default:
break;
}
}
+/*
+ * Get current frame count delta for the specified drawable and CRTC
+ */
+static uint32_t radeon_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (pDraw && pDraw->type == DRAWABLE_WINDOW)
+ return drmmode_crtc->interpolated_vblanks +
+ get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta;
+
+ return drmmode_crtc->interpolated_vblanks;
+}
+
+/*
+ * Get current frame count and timestamp of the specified CRTC
+ */
+static Bool radeon_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ if (!radeon_crtc_is_enabled(crtc) ||
+ drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) {
+ /* CRTC is not running, extrapolate MSC and timestamp */
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ ScrnInfoPtr scrn = crtc->scrn;
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ CARD64 now, delta_t, delta_seq;
+
+ if (!drmmode_crtc->dpms_last_ust)
+ return FALSE;
+
+ if (drmmode_get_current_ust(info->dri2.drm_fd, &now) != 0) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "%s cannot get current time\n", __func__);
+ return FALSE;
+ }
+
+ delta_t = now - drmmode_crtc->dpms_last_ust;
+ delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
+ delta_seq /= 1000000;
+ *ust = drmmode_crtc->dpms_last_ust;
+ delta_t = delta_seq * 1000000;
+ delta_t /= drmmode_crtc->dpms_last_fps;
+ *ust += delta_t;
+ *msc = drmmode_crtc->dpms_last_seq;
+ *msc += delta_seq;
+ }
+
+ return TRUE;
+}
+
static
xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
{
ScreenPtr pScreen = pDraw->pScreen;
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
- xf86CrtcPtr crtc;
+ xf86CrtcPtr crtc = radeon_pick_best_crtc(pScrn, consider_disabled,
+ pDraw->x, pDraw->x + pDraw->width,
+ pDraw->y, pDraw->y + pDraw->height);
- crtc = radeon_pick_best_crtc(pScrn, consider_disabled,
- pDraw->x,
- pDraw->x + pDraw->width,
- pDraw->y,
- pDraw->y + pDraw->height);
+ if (crtc && pDraw->type == DRAWABLE_WINDOW) {
+ struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw);
- /* Make sure the CRTC is valid and this is the real front buffer */
- if (crtc != NULL && !crtc->rotatedData)
- return crtc;
- else
- return NULL;
+ if (priv->crtc && priv->crtc != crtc) {
+ CARD64 ust, mscold, mscnew;
+
+ if (radeon_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) &&
+ radeon_dri2_get_crtc_msc(crtc, &ust, &mscnew))
+ priv->vblank_delta += mscold - mscnew;
+ }
+
+ priv->crtc = crtc;
+ }
+
+ return crtc;
+}
+
+static void
+radeon_dri2_flip_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ free(event_data);
+}
+
+static void
+radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
+ void *event_data)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ DRI2FrameEventPtr flip = event_data;
+ unsigned tv_sec, tv_usec;
+ DrawablePtr drawable;
+ ScreenPtr screen;
+ int status;
+ PixmapPtr pixmap;
+
+ status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
+ M_ANY, DixWriteAccess);
+ if (status != Success)
+ goto abort;
+
+ if (!flip->crtc)
+ goto abort;
+ frame += radeon_get_msc_delta(drawable, flip->crtc);
+
+ screen = scrn->pScreen;
+ pixmap = screen->GetScreenPixmap(screen);
+ xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
+ __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
+
+ tv_sec = usec / 1000000;
+ tv_usec = usec % 1000000;
+
+ /* We assume our flips arrive in order, so we don't check the frame */
+ switch (flip->type) {
+ case DRI2_SWAP:
+ /* Check for too small vblank count of pageflip completion, taking wraparound
+ * into account. This usually means some defective kms pageflip completion,
+ * causing wrong (msc, ust) return values and possible visual corruption.
+ */
+ if ((frame < flip->frame) && (flip->frame - frame < 5)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
+ __func__, frame, flip->frame);
+ /* All-Zero values signal failure of (msc, ust) timestamping to client. */
+ frame = tv_sec = tv_usec = 0;
+ }
+
+ DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
+ DRI2_FLIP_COMPLETE, flip->event_complete,
+ flip->event_data);
+ info->drmmode.dri2_flipping = FALSE;
+ break;
+ default:
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
+ /* Unknown type */
+ break;
+ }
+
+abort:
+ radeon_dri2_flip_event_abort(scrn, event_data);
}
static Bool
@@ -636,6 +716,7 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
DRI2BufferPtr back, DRI2SwapEventPtr func,
void *data, unsigned int target_msc)
{
+ RADEONInfoPtr info = RADEONPTR(scrn);
struct dri2_buffer_priv *back_priv;
struct radeon_bo *bo;
DRI2FrameEventPtr flip_info;
@@ -662,26 +743,31 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
back_priv = back->driverPrivate;
bo = radeon_get_pixmap_bo(back_priv->pixmap);
- return radeon_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
+ if (radeon_do_pageflip(scrn, client, bo->handle,
+ RADEON_DRM_QUEUE_ID_DEFAULT, flip_info,
+ ref_crtc_hw_id,
+ radeon_dri2_flip_event_handler,
+ radeon_dri2_flip_event_abort)) {
+ info->drmmode.dri2_flipping = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
}
static Bool
update_front(DrawablePtr draw, DRI2BufferPtr front)
{
- int r;
PixmapPtr pixmap;
RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(draw->pScreen));
struct dri2_buffer_priv *priv = front->driverPrivate;
- struct radeon_bo *bo;
pixmap = get_drawable_pixmap(draw);
pixmap->refcnt++;
if (!info->use_glamor)
exaMoveInPixmap(pixmap);
- bo = radeon_get_pixmap_bo(pixmap);
- r = radeon_gem_get_kernel_name(bo, &front->name);
- if (r) {
+ if (!radeon_get_flink_name(info, pixmap, &front->name)) {
(*draw->pScreen->DestroyPixmap)(pixmap);
return FALSE;
}
@@ -734,8 +820,11 @@ static Bool
can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
DRI2BufferPtr front, DRI2BufferPtr back)
{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
return draw->type == DRAWABLE_WINDOW &&
- RADEONPTR(pScrn)->allowPageFlip &&
+ info->allowPageFlip &&
+ !info->drmmode.present_flipping &&
pScrn->vtSema &&
DRI2CanFlip(draw) &&
can_exchange(pScrn, draw, front, back);
@@ -784,31 +873,36 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
DamageRegionProcessPending(&front_priv->pixmap->drawable);
}
-void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+static void radeon_dri2_frame_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ DRI2FrameEventPtr event = event_data;
+
+ TimerCancel(event->timer);
+ TimerFree(event->timer);
+ radeon_dri2_unref_buffer(event->front);
+ radeon_dri2_unref_buffer(event->back);
+ free(event);
+}
+
+static void radeon_dri2_frame_event_handler(ScrnInfoPtr scrn, uint32_t seq,
+ uint64_t usec, void *event_data)
{
DRI2FrameEventPtr event = event_data;
DrawablePtr drawable;
- ScreenPtr screen;
- ScrnInfoPtr scrn;
int status;
int swap_type;
BoxRec box;
RegionRec region;
- if (!event->valid)
+ if (!event->crtc)
goto cleanup;
status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
M_ANY, DixWriteAccess);
if (status != Success)
goto cleanup;
- if (!event->crtc)
- goto cleanup;
- frame += radeon_get_interpolated_vblanks(event->crtc);
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+ seq += radeon_get_msc_delta(drawable, event->crtc);
switch (event->type) {
case DRI2_FLIP:
@@ -840,12 +934,14 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
swap_type = DRI2_BLIT_COMPLETE;
}
- DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec,
- swap_type, event->event_complete, event->event_data);
+ DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
+ usec % 1000000, swap_type, event->event_complete,
+ event->event_data);
break;
case DRI2_WAITMSC:
- DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec, tv_usec);
+ DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
+ usec % 1000000);
break;
default:
/* Unknown type */
@@ -855,12 +951,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
}
cleanup:
- if (event->valid) {
- radeon_dri2_unref_buffer(event->front);
- radeon_dri2_unref_buffer(event->back);
- ListDelDRI2ClientEvents(event->client, &event->link);
- }
- free(event);
+ radeon_dri2_frame_event_abort(scrn, event_data);
}
drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc)
@@ -898,8 +989,6 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
int nominal_frame_rate = drmmode_crtc->dpms_last_fps;
CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust;
uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq;
- int interpolated_vblanks = drmmode_crtc->interpolated_vblanks;
- int target_seq;
CARD64 now, target_time, delta_t;
int64_t d, delta_seq;
int ret;
@@ -916,16 +1005,15 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
*target_msc = 0;
return FALLBACK_SWAP_DELAY;
}
- target_seq = (int)*target_msc - interpolated_vblanks;
- delta_seq = (int64_t)target_seq - (int64_t)last_vblank_seq;
+ delta_seq = *target_msc - last_vblank_seq;
delta_seq *= 1000000;
target_time = last_vblank_ust;
target_time += delta_seq / nominal_frame_rate;
d = target_time - now;
if (d < 0) {
/* we missed the event, adjust target_msc, do the divisor magic */
- CARD64 current_msc;
- current_msc = last_vblank_seq + interpolated_vblanks;
+ CARD64 current_msc = last_vblank_seq;
+
delta_t = now - last_vblank_ust;
delta_seq = delta_t * nominal_frame_rate;
current_msc += delta_seq / 1000000;
@@ -938,8 +1026,7 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
if ((current_msc % divisor) >= remainder)
*target_msc += divisor;
*target_msc &= 0xffffffff;
- target_seq = (int)*target_msc - interpolated_vblanks;
- delta_seq = (int64_t)target_seq - (int64_t)last_vblank_seq;
+ delta_seq = *target_msc - last_vblank_seq;
delta_seq *= 1000000;
target_time = last_vblank_ust;
target_time += delta_seq / nominal_frame_rate;
@@ -960,16 +1047,11 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
}
/*
- * Get current frame count and frame count timestamp, based on drawable's
- * crtc.
+ * Get current interpolated frame count and frame count timestamp, based on
+ * drawable's crtc.
*/
static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
{
- ScreenPtr screen = draw->pScreen;
- ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
- RADEONInfoPtr info = RADEONPTR(scrn);
- drmVBlank vbl;
- int ret;
xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
/* Drawable not displayed, make up a value */
@@ -978,47 +1060,12 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
*msc = 0;
return TRUE;
}
- if (radeon_crtc_is_enabled(crtc)) {
- /* CRTC is running, read vblank counter and timestamp */
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.type |= radeon_populate_vbl_request_type(crtc);
- vbl.request.sequence = 0;
-
- ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
- if (ret) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "get vblank counter failed: %s\n", strerror(errno));
- return FALSE;
- }
- *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
- *msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
- *msc &= 0xffffffff;
- } else {
- /* CRTC is not running, extrapolate MSC and timestamp */
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- CARD64 now, delta_t, delta_seq;
+ if (!radeon_dri2_get_crtc_msc(crtc, ust, msc))
+ return FALSE;
- if (!drmmode_crtc->dpms_last_ust)
- return FALSE;
- ret = drmmode_get_current_ust(info->dri2.drm_fd, &now);
- if (ret) {
- xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "%s cannot get current time\n", __func__);
- return FALSE;
- }
- delta_t = now - drmmode_crtc->dpms_last_ust;
- delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
- delta_seq /= 1000000;
- *ust = drmmode_crtc->dpms_last_ust;
- delta_t = delta_seq * 1000000;
- delta_t /= drmmode_crtc->dpms_last_fps;
- *ust += delta_t;
- *msc = drmmode_crtc->dpms_last_seq;
- *msc += drmmode_crtc->interpolated_vblanks;
- *msc += delta_seq;
- *msc &= 0xffffffff;
- }
+ *msc += radeon_get_msc_delta(draw, crtc);
+ *msc &= 0xffffffff;
return TRUE;
}
@@ -1026,17 +1073,13 @@ static
CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
{
DRI2FrameEventPtr event_info = (DRI2FrameEventPtr)data;
- DrawablePtr drawable;
- ScreenPtr screen;
+ xf86CrtcPtr crtc = event_info->crtc;
ScrnInfoPtr scrn;
RADEONInfoPtr info;
- int status;
CARD64 drm_now;
int ret;
- unsigned int tv_sec, tv_usec;
CARD64 delta_t, delta_seq, frame;
drmmode_crtc_private_ptr drmmode_crtc;
- TimerFree(timer);
/*
* This is emulated event, so its time is current time, which we
@@ -1047,28 +1090,26 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
*/
if (!event_info->crtc) {
ErrorF("%s no crtc\n", __func__);
- radeon_dri2_frame_event_handler(0, 0, 0, data);
+ if (event_info->drm_queue)
+ radeon_drm_abort_entry(event_info->drm_queue);
+ else
+ radeon_dri2_frame_event_abort(NULL, data);
return 0;
}
- status = dixLookupDrawable(&drawable, event_info->drawable_id, serverClient,
- M_ANY, DixWriteAccess);
- if (status != Success) {
- ErrorF("%s cannot lookup drawable\n", __func__);
- radeon_dri2_frame_event_handler(0, 0, 0, data);
- return 0;
- }
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+
+ scrn = crtc->scrn;
info = RADEONPTR(scrn);
ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"%s cannot get current time\n", __func__);
- radeon_dri2_frame_event_handler(0, 0, 0, data);
+ if (event_info->drm_queue)
+ radeon_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0,
+ event_info->drm_queue);
+ else
+ radeon_dri2_frame_event_handler(scrn, 0, 0, data);
return 0;
}
- tv_sec = (unsigned int)(drm_now / 1000000);
- tv_usec = (unsigned int)(drm_now - (CARD64)tv_sec * 1000000);
/*
* calculate the frame number from current time
* that would come from CRTC if it were running
@@ -1078,20 +1119,22 @@ 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;
- frame &= 0xffffffff;
- radeon_dri2_frame_event_handler((unsigned int)frame, tv_sec, tv_usec, data);
+ if (event_info->drm_queue)
+ radeon_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000,
+ drm_now % 1000000, event_info->drm_queue);
+ else
+ radeon_dri2_frame_event_handler(scrn, frame, drm_now, data);
return 0;
}
static
-void radeon_dri2_schedule_event(CARD32 delay, pointer arg)
+void radeon_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
{
- OsTimerPtr timer;
-
- timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event, arg);
+ event_info->timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event,
+ event_info);
if (delay == 0) {
CARD32 now = GetTimeInMillis();
- radeon_dri2_deferred_event(timer, now, arg);
+ radeon_dri2_deferred_event(event_info->timer, now, event_info);
}
}
@@ -1109,7 +1152,9 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
RADEONInfoPtr info = RADEONPTR(scrn);
DRI2FrameEventPtr wait_info = NULL;
+ struct radeon_drm_queue_entry *wait = NULL;
xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
+ uint32_t msc_delta;
drmVBlank vbl;
int ret;
CARD64 current_msc;
@@ -1124,6 +1169,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
if (crtc == NULL)
goto out_complete;
+ msc_delta = radeon_get_msc_delta(draw, crtc);
+
wait_info = calloc(1, sizeof(DRI2FrameEventRec));
if (!wait_info)
goto out_complete;
@@ -1131,26 +1178,17 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
wait_info->drawable_id = draw->id;
wait_info->client = client;
wait_info->type = DRI2_WAITMSC;
- wait_info->valid = TRUE;
wait_info->crtc = crtc;
- if (ListAddDRI2ClientEvents(client, &wait_info->link)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "add events to client private failed.\n");
- free(wait_info);
- wait_info = NULL;
- goto out_complete;
- }
-
/*
* CRTC is in DPMS off state, calculate wait time from current time,
* target_msc and last vblank time/sequence when CRTC was turned off
*/
if (!radeon_crtc_is_enabled(crtc)) {
CARD32 delay;
+ target_msc -= msc_delta;
delay = radeon_dri2_extrapolate_msc_delay(crtc, &target_msc,
divisor, remainder);
- wait_info->frame = target_msc;
radeon_dri2_schedule_event(delay, wait_info);
DRI2BlockClient(client, draw);
return TRUE;
@@ -1167,9 +1205,19 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
goto out_complete;
}
- current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
+ current_msc = vbl.reply.sequence + msc_delta;
current_msc &= 0xffffffff;
+ wait = radeon_drm_queue_alloc(scrn, client, RADEON_DRM_QUEUE_ID_DEFAULT,
+ wait_info, radeon_dri2_frame_event_handler,
+ radeon_dri2_frame_event_abort);
+ if (!wait) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM queue event entry failed.\n");
+ goto out_complete;
+ }
+ wait_info->drm_queue = wait;
+
/*
* If divisor is zero, or current_msc is smaller than target_msc,
* we just need to make sure target_msc passes before waking up the
@@ -1186,9 +1234,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
target_msc = current_msc;
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
vbl.request.type |= radeon_populate_vbl_request_type(crtc);
- vbl.request.sequence = target_msc;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)wait_info;
+ vbl.request.sequence = target_msc - msc_delta;
+ vbl.request.signal = (unsigned long)wait;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1196,8 +1243,6 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
goto out_complete;
}
- wait_info->frame = vbl.reply.sequence;
- wait_info->frame += radeon_get_interpolated_vblanks(crtc);
DRI2BlockClient(client, draw);
return TRUE;
}
@@ -1210,7 +1255,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
vbl.request.type |= radeon_populate_vbl_request_type(crtc);
vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder;
+ remainder - msc_delta;
/*
* If calculated remainder is larger than requested remainder,
@@ -1220,9 +1265,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
*/
if ((current_msc % divisor) >= remainder)
vbl.request.sequence += divisor;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)wait_info;
+ vbl.request.signal = (unsigned long)wait;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1230,79 +1274,16 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
goto out_complete;
}
- wait_info->frame = vbl.reply.sequence;
- wait_info->frame += radeon_get_interpolated_vblanks(crtc);
DRI2BlockClient(client, draw);
return TRUE;
out_complete:
- if (wait_info) {
- ListDelDRI2ClientEvents(wait_info->client, &wait_info->link);
- free(wait_info);
- }
- DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+ if (wait_info)
+ radeon_dri2_deferred_event(NULL, 0, wait_info);
return TRUE;
}
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- DRI2FrameEventPtr flip = event_data;
- DrawablePtr drawable;
- ScreenPtr screen;
- ScrnInfoPtr scrn;
- int status;
- PixmapPtr pixmap;
-
- status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
- M_ANY, DixWriteAccess);
- if (status != Success) {
- free(flip);
- return;
- }
- if (!flip->crtc) {
- free(flip);
- return;
- }
- frame += radeon_get_interpolated_vblanks(flip->crtc);
-
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
-
- pixmap = screen->GetScreenPixmap(screen);
- xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
- "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
- __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
-
- /* We assume our flips arrive in order, so we don't check the frame */
- switch (flip->type) {
- case DRI2_SWAP:
- /* Check for too small vblank count of pageflip completion, taking wraparound
- * into account. This usually means some defective kms pageflip completion,
- * causing wrong (msc, ust) return values and possible visual corruption.
- */
- if ((frame < flip->frame) && (flip->frame - frame < 5)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
- __func__, frame, flip->frame);
- /* All-Zero values signal failure of (msc, ust) timestamping to client. */
- frame = tv_sec = tv_usec = 0;
- }
-
- DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
- DRI2_FLIP_COMPLETE, flip->event_complete,
- flip->event_data);
- break;
- default:
- xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
- /* Unknown type */
- break;
- }
-
- free(flip);
-}
-
/*
* ScheduleSwap is responsible for requesting a DRM vblank event for the
* appropriate frame.
@@ -1333,10 +1314,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
RADEONInfoPtr info = RADEONPTR(scrn);
xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
+ uint32_t msc_delta;
drmVBlank vbl;
int ret, flip = 0;
DRI2FrameEventPtr swap_info = NULL;
- enum DRI2FrameEventType swap_type = DRI2_SWAP;
+ struct radeon_drm_queue_entry *swap;
CARD64 current_msc;
BoxRec box;
RegionRec region;
@@ -1358,25 +1340,30 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
if (crtc == NULL)
goto blit_fallback;
+ msc_delta = radeon_get_msc_delta(draw, crtc);
+
swap_info = calloc(1, sizeof(DRI2FrameEventRec));
if (!swap_info)
goto blit_fallback;
+ swap_info->type = DRI2_SWAP;
swap_info->drawable_id = draw->id;
swap_info->client = client;
swap_info->event_complete = func;
swap_info->event_data = data;
swap_info->front = front;
swap_info->back = back;
- swap_info->valid = TRUE;
swap_info->crtc = crtc;
- if (ListAddDRI2ClientEvents(client, &swap_info->link)) {
+
+ swap = radeon_drm_queue_alloc(scrn, client, RADEON_DRM_QUEUE_ID_DEFAULT,
+ swap_info, radeon_dri2_frame_event_handler,
+ radeon_dri2_frame_event_abort);
+ if (!swap) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "add events to client private failed.\n");
- free(swap_info);
- swap_info = NULL;
+ "Allocating DRM queue entry failed.\n");
goto blit_fallback;
}
+ swap_info->drm_queue = swap;
/*
* CRTC is in DPMS off state, fallback to blit, but calculate
@@ -1385,9 +1372,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
*/
if (!radeon_crtc_is_enabled(crtc)) {
CARD32 delay;
+ *target_msc -= msc_delta;
delay = radeon_dri2_extrapolate_msc_delay(crtc, target_msc,
divisor, remainder);
- swap_info->frame = *target_msc;
+ *target_msc += msc_delta;
+ *target_msc &= 0xffffffff;
radeon_dri2_schedule_event(delay, swap_info);
return TRUE;
}
@@ -1401,23 +1390,19 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"first get vblank counter failed: %s\n",
strerror(errno));
- *target_msc = 0;
- radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
- return TRUE;
+ goto blit_fallback;
}
- current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
+ current_msc = vbl.reply.sequence + msc_delta;
current_msc &= 0xffffffff;
/* Flips need to be submitted one frame before */
if (can_flip(scrn, draw, front, back)) {
- swap_type = DRI2_FLIP;
+ swap_info->type = DRI2_FLIP;
flip = 1;
}
- swap_info->type = swap_type;
-
- /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
+ /* Correct target_msc by 'flip' if swap_info->type == DRI2_FLIP.
* Do it early, so handling of different timing constraints
* for divisor, remainder and msc vs. target_msc works.
*/
@@ -1446,21 +1431,17 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
if (current_msc >= *target_msc)
*target_msc = current_msc;
- vbl.request.sequence = *target_msc;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)swap_info;
+ vbl.request.sequence = *target_msc - msc_delta;
+ vbl.request.signal = (unsigned long)swap;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"divisor 0 get vblank counter failed: %s\n",
strerror(errno));
- *target_msc = 0;
- radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
- return TRUE;
+ goto blit_fallback;
}
- *target_msc = vbl.reply.sequence + flip;
- *target_msc += radeon_get_interpolated_vblanks(crtc);
+ *target_msc = vbl.reply.sequence + flip + msc_delta;
swap_info->frame = *target_msc;
return TRUE;
@@ -1477,7 +1458,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
vbl.request.type |= radeon_populate_vbl_request_type(crtc);
vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder;
+ remainder - msc_delta;
/*
* If the calculated deadline vbl.request.sequence is smaller than
@@ -1492,53 +1473,49 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
*/
if (vbl.request.sequence <= current_msc)
vbl.request.sequence += divisor;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
/* Account for 1 frame extra pageflip delay if flip > 0 */
vbl.request.sequence -= flip;
- vbl.request.signal = (unsigned long)swap_info;
+ vbl.request.signal = (unsigned long)swap;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"final get vblank counter failed: %s\n",
strerror(errno));
- *target_msc = 0;
- radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
- return TRUE;
+ goto blit_fallback;
}
/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
- *target_msc = vbl.reply.sequence + flip;
- *target_msc += radeon_get_interpolated_vblanks(crtc);
+ *target_msc = vbl.reply.sequence + flip + msc_delta;
+ *target_msc &= 0xffffffff;
swap_info->frame = *target_msc;
return TRUE;
blit_fallback:
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = draw->width;
- box.y2 = draw->height;
- REGION_INIT(pScreen, &region, &box, 0);
+ if (swap_info) {
+ swap_info->type = DRI2_SWAP;
+ radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
+ } else {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = draw->width;
+ box.y2 = draw->height;
+ REGION_INIT(pScreen, &region, &box, 0);
- radeon_dri2_copy_region(draw, &region, front, back);
+ radeon_dri2_copy_region(draw, &region, front, back);
- DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
- if (swap_info) {
- ListDelDRI2ClientEvents(swap_info->client, &swap_info->link);
- free(swap_info);
- }
+ DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
- radeon_dri2_unref_buffer(front);
- radeon_dri2_unref_buffer(back);
+ radeon_dri2_unref_buffer(front);
+ radeon_dri2_unref_buffer(back);
+ }
*target_msc = 0; /* offscreen, so zero out target vblank count */
return TRUE;
}
-#endif /* USE_DRI2_SCHEDULING */
-
Bool
radeon_dri2_screen_init(ScreenPtr pScreen)
@@ -1546,10 +1523,8 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
DRI2InfoRec dri2_info = { 0 };
-#ifdef USE_DRI2_SCHEDULING
const char *driverNames[2];
Bool scheduling_works = TRUE;
-#endif
if (!info->dri2.available)
return FALSE;
@@ -1574,14 +1549,13 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
dri2_info.CopyRegion = radeon_dri2_copy_region;
-#ifdef USE_DRI2_SCHEDULING
if (info->dri2.pKernelDRMVersion->version_minor < 4) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for "
"sync extension\n");
scheduling_works = FALSE;
}
- if (scheduling_works && info->drmmode.mode_res->count_crtcs > 2) {
+ if (scheduling_works && info->drmmode.count_crtcs > 2) {
#ifdef DRM_CAP_VBLANK_HIGH_CRTC
uint64_t cap_value;
@@ -1608,31 +1582,32 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
dri2_info.ScheduleWaitMSC = radeon_dri2_schedule_wait_msc;
dri2_info.numDrivers = RADEON_ARRAY_SIZE(driverNames);
dri2_info.driverNames = driverNames;
- driverNames[0] = driverNames[1] = dri2_info.driverName;
+ driverNames[0] = dri2_info.driverName;
+
+ if (info->ChipFamily >= CHIP_FAMILY_R300)
+ driverNames[1] = driverNames[0];
+ else
+ driverNames[1] = NULL; /* no VDPAU support */
if (DRI2InfoCnt == 0) {
#if HAS_DIXREGISTERPRIVATEKEY
- if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey,
- PRIVATE_CLIENT, sizeof(DRI2ClientEventsRec))) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 registering "
- "private key to client failed\n");
- return FALSE;
- }
+ if (!dixRegisterPrivateKey(dri2_window_private_key,
+ PRIVATE_WINDOW,
+ sizeof(struct dri2_window_priv))) {
#else
- if (!dixRequestPrivate(DRI2ClientEventsPrivateKey,
- sizeof(DRI2ClientEventsRec))) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requesting "
- "private key to client failed\n");
+ if (!dixRequestPrivate(dri2_window_private_key,
+ sizeof(struct dri2_window_priv))) {
+#endif
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to get DRI2 window private\n");
return FALSE;
}
-#endif
AddCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
}
DRI2InfoCnt++;
}
-#endif
#if DRI2INFOREC_VERSION >= 9
dri2_info.version = 9;
@@ -1650,10 +1625,8 @@ void radeon_dri2_close_screen(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
-#ifdef USE_DRI2_SCHEDULING
if (--DRI2InfoCnt == 0)
DeleteCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
-#endif
DRI2CloseScreen(pScreen);
drmFree(info->dri2.device_name);
diff --git a/driver/xf86-video-ati/src/radeon_dri2.h b/driver/xf86-video-ati/src/radeon_dri2.h
index 37d46f3d0..9ba47c78f 100644
--- a/driver/xf86-video-ati/src/radeon_dri2.h
+++ b/driver/xf86-video-ati/src/radeon_dri2.h
@@ -43,48 +43,11 @@ struct radeon_dri2 {
Bool radeon_dri2_screen_init(ScreenPtr pScreen);
void radeon_dri2_close_screen(ScreenPtr pScreen);
-int drmmode_get_crtc_id(xf86CrtcPtr crtc);
-void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data);
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data);
-
#else
static inline Bool radeon_dri2_screen_init(ScreenPtr pScreen) { return FALSE; }
static inline void radeon_dri2_close_screen(ScreenPtr pScreen) {}
-static inline void
-radeon_dri2_dummy_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data,
- const char *name)
-{
- static Bool warned;
-
- if (!warned) {
- ErrorF("%s called but DRI2 disabled at build time\n", name);
- warned = TRUE;
- }
-
- free(event_data);
-}
-
-static inline void
-radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- radeon_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
- __func__);
-}
-
-static inline void
-radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- radeon_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
- __func__);
-}
-
#endif
#endif /* RADEON_DRI2_H */
diff --git a/driver/xf86-video-ati/src/radeon_dri3.c b/driver/xf86-video-ati/src/radeon_dri3.c
new file mode 100644
index 000000000..1415a0df7
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_dri3.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "radeon.h"
+
+#ifdef HAVE_DRI3_H
+
+#include "radeon_bo_gem.h"
+#include "radeon_glamor.h"
+#include "dri3.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+static int
+radeon_dri3_open(ScreenPtr screen, RRProviderPtr provider, int *out)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ drm_magic_t magic;
+ int fd;
+
+ fd = open(info->dri2.device_name, O_RDWR | O_CLOEXEC);
+ if (fd < 0)
+ return BadAlloc;
+
+ /* Before FD passing in the X protocol with DRI3 (and increased
+ * security of rendering with per-process address spaces on the
+ * GPU), the kernel had to come up with a way to have the server
+ * decide which clients got to access the GPU, which was done by
+ * each client getting a unique (magic) number from the kernel,
+ * passing it to the server, and the server then telling the
+ * kernel which clients were authenticated for using the device.
+ *
+ * Now that we have FD passing, the server can just set up the
+ * authentication on its own and hand the prepared FD off to the
+ * client.
+ */
+ if (drmGetMagic(fd, &magic) < 0) {
+ if (errno == EACCES) {
+ /* Assume that we're on a render node, and the fd is
+ * already as authenticated as it should be.
+ */
+ *out = fd;
+ return Success;
+ } else {
+ close(fd);
+ return BadMatch;
+ }
+ }
+
+ if (drmAuthMagic(info->dri2.drm_fd, magic) < 0) {
+ close(fd);
+ return BadMatch;
+ }
+
+ *out = fd;
+ return Success;
+}
+
+static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen,
+ int fd,
+ CARD16 width,
+ CARD16 height,
+ CARD16 stride,
+ CARD8 depth,
+ CARD8 bpp)
+{
+ PixmapPtr pixmap;
+
+#ifdef USE_GLAMOR
+ /* Avoid generating a GEM flink name if possible */
+ if (RADEONPTR(xf86ScreenToScrn(screen))->use_glamor) {
+ pixmap = glamor_pixmap_from_fd(screen, fd, width, height,
+ stride, depth, bpp);
+ if (pixmap) {
+ struct radeon_pixmap *priv =
+ calloc(1, sizeof(struct radeon_pixmap));
+
+ if (priv) {
+ radeon_set_pixmap_private(pixmap, priv);
+ return pixmap;
+ }
+
+ screen->DestroyPixmap(pixmap);
+ }
+ }
+#endif
+
+ if (depth < 8)
+ return NULL;
+
+ switch (bpp) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return NULL;
+ }
+
+ pixmap = screen->CreatePixmap(screen, 0, 0, depth, RADEON_CREATE_PIXMAP_DRI2);
+ if (!pixmap)
+ return NULL;
+
+ if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, bpp, stride,
+ NULL))
+ goto free_pixmap;
+
+ if (screen->SetSharedPixmapBacking(pixmap, (void*)(intptr_t)fd))
+ return pixmap;
+
+free_pixmap:
+ fbDestroyPixmap(pixmap);
+ return NULL;
+}
+
+static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride,
+ CARD32 *size)
+{
+ struct radeon_bo *bo;
+ int fd;
+
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo) {
+#ifdef USE_GLAMOR
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ if (info->use_glamor)
+ return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+#endif
+
+ exaMoveInPixmap(pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo)
+ return -1;
+ }
+
+ if (pixmap->devKind > UINT16_MAX)
+ return -1;
+
+ if (radeon_gem_prime_share_bo(bo, &fd) < 0)
+ return -1;
+
+ *stride = pixmap->devKind;
+ *size = bo->size;
+ return fd;
+}
+
+static dri3_screen_info_rec radeon_dri3_screen_info = {
+ .version = 0,
+
+ .open = radeon_dri3_open,
+ .pixmap_from_fd = radeon_dri3_pixmap_from_fd,
+ .fd_from_pixmap = radeon_dri3_fd_from_pixmap
+};
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ if (!dri3_screen_init(screen, &radeon_dri3_screen_info)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "dri3_screen_init failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#else /* !HAVE_DRI3_H */
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "Can't initialize DRI3 because dri3.h not available at "
+ "build time\n");
+
+ return FALSE;
+}
+
+#endif
diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.c b/driver/xf86-video-ati/src/radeon_drm_queue.c
new file mode 100644
index 000000000..5e54ef8bb
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_drm_queue.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+
+#include "radeon.h"
+#include "radeon_drm_queue.h"
+#include "radeon_list.h"
+
+
+struct radeon_drm_queue_entry {
+ struct xorg_list list;
+ uint64_t id;
+ void *data;
+ ClientPtr client;
+ ScrnInfoPtr scrn;
+ radeon_drm_handler_proc handler;
+ radeon_drm_abort_proc abort;
+};
+
+static int radeon_drm_queue_refcnt;
+static struct xorg_list radeon_drm_queue;
+
+
+/*
+ * Handle a DRM event
+ */
+void
+radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *user_ptr)
+{
+ struct radeon_drm_queue_entry *user_data = user_ptr;
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e == user_data) {
+ xorg_list_del(&e->list);
+ e->handler(e->scrn, frame,
+ (uint64_t)sec * 1000000 + usec, e->data);
+ free(e);
+ break;
+ }
+ }
+}
+
+/*
+ * Enqueue a potential drm response; when the associated response
+ * appears, we've got data to pass to the handler from here
+ */
+struct radeon_drm_queue_entry *
+radeon_drm_queue_alloc(ScrnInfoPtr scrn, ClientPtr client,
+ uint64_t id, void *data,
+ radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort)
+{
+ struct radeon_drm_queue_entry *e;
+
+ e = calloc(1, sizeof(struct radeon_drm_queue_entry));
+ if (!e)
+ return NULL;
+
+ e->client = client;
+ e->scrn = scrn;
+ e->id = id;
+ e->data = data;
+ e->handler = handler;
+ e->abort = abort;
+
+ xorg_list_add(&e->list, &radeon_drm_queue);
+
+ return 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->scrn, e->data);
+ free(e);
+}
+
+/*
+ * Abort drm queue entries for a client
+ */
+void
+radeon_drm_abort_client(ClientPtr client)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->client == client)
+ radeon_drm_abort_one(e);
+ }
+}
+
+/*
+ * Abort specific drm queue entry
+ */
+void
+radeon_drm_abort_entry(struct radeon_drm_queue_entry *entry)
+{
+ radeon_drm_abort_one(entry);
+}
+
+/*
+ * Abort specific drm queue entry by ID
+ */
+void
+radeon_drm_abort_id(uint64_t id)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->id == id) {
+ radeon_drm_abort_one(e);
+ break;
+ }
+ }
+}
+
+/*
+ * Initialize the DRM event queue
+ */
+void
+radeon_drm_queue_init()
+{
+ if (radeon_drm_queue_refcnt++)
+ return;
+
+ xorg_list_init(&radeon_drm_queue);
+}
+
+/*
+ * Deinitialize the DRM event queue
+ */
+void
+radeon_drm_queue_close(ScrnInfoPtr scrn)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->scrn == scrn)
+ radeon_drm_abort_one(e);
+ }
+
+ radeon_drm_queue_refcnt--;
+}
diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.h b/driver/xf86-video-ati/src/radeon_drm_queue.h
new file mode 100644
index 000000000..8fc1c42e0
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_drm_queue.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifndef _RADEON_DRM_QUEUE_H_
+#define _RADEON_DRM_QUEUE_H_
+
+#define RADEON_DRM_QUEUE_CLIENT_DEFAULT serverClient
+#define RADEON_DRM_QUEUE_ID_DEFAULT ~0ULL
+
+struct radeon_drm_queue_entry;
+
+typedef void (*radeon_drm_handler_proc)(ScrnInfoPtr scrn, uint32_t seq,
+ uint64_t usec, void *data);
+typedef void (*radeon_drm_abort_proc)(ScrnInfoPtr scrn, void *data);
+
+void radeon_drm_queue_handler(int fd, unsigned int frame,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_ptr);
+struct radeon_drm_queue_entry *radeon_drm_queue_alloc(ScrnInfoPtr scrn,
+ ClientPtr client,
+ uint64_t id,
+ void *data,
+ radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort);
+void radeon_drm_abort_client(ClientPtr client);
+void radeon_drm_abort_entry(struct radeon_drm_queue_entry *entry);
+void radeon_drm_abort_id(uint64_t id);
+void radeon_drm_queue_init();
+void radeon_drm_queue_close(ScrnInfoPtr scrn);
+
+#endif /* _RADEON_DRM_QUEUE_H_ */
diff --git a/driver/xf86-video-ati/src/radeon_exa.c b/driver/xf86-video-ati/src/radeon_exa.c
index 0d6cd2400..1e457a8bb 100644
--- a/driver/xf86-video-ati/src/radeon_exa.c
+++ b/driver/xf86-video-ati/src/radeon_exa.c
@@ -330,7 +330,6 @@ Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
return FALSE;
driver_priv->shared = TRUE;
- driver_priv->tiling_flags = 0;
return TRUE;
}
#endif
diff --git a/driver/xf86-video-ati/src/radeon_glamor.c b/driver/xf86-video-ati/src/radeon_glamor.c
index 210ddcf27..fdd5aeac4 100644
--- a/driver/xf86-video-ati/src/radeon_glamor.c
+++ b/driver/xf86-video-ati/src/radeon_glamor.c
@@ -29,11 +29,10 @@
#endif
#include <xf86.h>
-#define GLAMOR_FOR_XORG 1
-#include <glamor.h>
#include "radeon.h"
#include "radeon_bo_helper.h"
+#include "radeon_glamor.h"
#if HAS_DEVPRIVATEKEYREC
DevPrivateKeyRec glamor_pixmap_index;
@@ -61,8 +60,10 @@ radeon_glamor_create_screen_resources(ScreenPtr screen)
if (!info->use_glamor)
return TRUE;
+#ifdef HAVE_GLAMOR_GLYPHS_INIT
if (!glamor_glyphs_init(screen))
return FALSE;
+#endif
if (!glamor_egl_create_textured_screen_ext(screen,
info->front_bo->handle,
@@ -152,51 +153,30 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn)
}
Bool
-radeon_glamor_create_textured_pixmap(PixmapPtr pixmap)
-{
- ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
- RADEONInfoPtr info = RADEONPTR(scrn);
- struct radeon_pixmap *priv;
-
- if ((info->use_glamor) == 0)
- return TRUE;
-
- priv = radeon_get_pixmap_private(pixmap);
- if (!priv->stride)
- priv->stride = pixmap->devKind;
- if (glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
- priv->stride))
- return TRUE;
- else
- return FALSE;
-}
-
-Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap)
+radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv)
{
- struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
- return priv && priv->bo;
+ return glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
+ pixmap->devKind);
}
-#ifndef CREATE_PIXMAP_USAGE_SHARED
-#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2
-#endif
-
-#define RADEON_CREATE_PIXMAP_SHARED(usage) \
- (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \
- (usage) == CREATE_PIXMAP_USAGE_SHARED)
-
static PixmapPtr
radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
unsigned usage)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
struct radeon_pixmap *priv;
PixmapPtr pixmap, new_pixmap = NULL;
if (!RADEON_CREATE_PIXMAP_SHARED(usage)) {
- pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
- if (pixmap)
- return pixmap;
+ if (info->shadow_primary) {
+ if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+ } else {
+ pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ if (pixmap)
+ return pixmap;
+ }
}
if (w > 32767 || h > 32767)
@@ -213,13 +193,15 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
return pixmap;
if (w && h) {
+ int stride;
+
priv = calloc(1, sizeof (struct radeon_pixmap));
if (priv == NULL)
goto fallback_pixmap;
priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage,
pixmap->drawable.bitsPerPixel,
- &priv->stride,
+ &stride,
&priv->surface,
&priv->tiling_flags);
if (!priv->bo)
@@ -227,10 +209,12 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
radeon_set_pixmap_private(pixmap, priv);
- screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL);
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
- if (!radeon_glamor_create_textured_pixmap(pixmap))
+ if (!radeon_glamor_create_textured_pixmap(pixmap, priv))
goto fallback_glamor;
+
+ pixmap->devPrivate.ptr = NULL;
}
return pixmap;
@@ -269,6 +253,13 @@ fallback_pixmap:
static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
{
if (pixmap->refcnt == 1) {
+ if (pixmap->devPrivate.ptr) {
+ struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+
+ if (bo)
+ radeon_bo_unmap(bo);
+ }
+
glamor_egl_destroy_textured_pixmap(pixmap);
radeon_set_pixmap_bo(pixmap, NULL);
}
@@ -302,11 +293,9 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
return FALSE;
priv = radeon_get_pixmap_private(pixmap);
- priv->stride = pixmap->devKind;
priv->surface = surface;
- priv->tiling_flags = 0;
- if (!radeon_glamor_create_textured_pixmap(pixmap)) {
+ if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to get PRIME drawable for glamor pixmap.\n");
return FALSE;
@@ -315,9 +304,7 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
screen->ModifyPixmapHeader(pixmap,
pixmap->drawable.width,
pixmap->drawable.height,
- 0, 0,
- priv->stride,
- NULL);
+ 0, 0, 0, NULL);
return TRUE;
}
@@ -328,12 +315,30 @@ Bool
radeon_glamor_init(ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+#ifdef RENDER
+#ifdef HAVE_FBGLYPHS
+ UnrealizeGlyphProcPtr SavedUnrealizeGlyph = NULL;
+#endif
+ PictureScreenPtr ps = NULL;
+
+ if (info->shadow_primary) {
+ ps = GetPictureScreenIfSet(screen);
- if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN |
-#ifdef GLAMOR_NO_DRI3
- GLAMOR_NO_DRI3 |
+ if (ps) {
+#ifdef HAVE_FBGLYPHS
+ SavedUnrealizeGlyph = ps->UnrealizeGlyph;
#endif
- GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN)) {
+ info->glamor.SavedGlyphs = ps->Glyphs;
+ info->glamor.SavedTriangles = ps->Triangles;
+ info->glamor.SavedTrapezoids = ps->Trapezoids;
+ }
+ }
+#endif /* RENDER */
+
+ if (!glamor_init(screen, GLAMOR_USE_EGL_SCREEN | GLAMOR_USE_SCREEN |
+ GLAMOR_USE_PICTURE_SCREEN | GLAMOR_INVERTED_Y_AXIS |
+ GLAMOR_NO_DRI3)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to initialize glamor.\n");
return FALSE;
@@ -352,6 +357,17 @@ radeon_glamor_init(ScreenPtr screen)
#endif
return FALSE;
+ if (info->shadow_primary)
+ radeon_glamor_screen_init(screen);
+
+#if defined(RENDER) && defined(HAVE_FBGLYPHS)
+ /* For ShadowPrimary, we need fbUnrealizeGlyph instead of
+ * glamor_unrealize_glyph
+ */
+ if (ps)
+ ps->UnrealizeGlyph = SavedUnrealizeGlyph;
+#endif
+
screen->CreatePixmap = radeon_glamor_create_pixmap;
screen->DestroyPixmap = radeon_glamor_destroy_pixmap;
#ifdef RADEON_PIXMAP_SHARING
@@ -364,15 +380,6 @@ radeon_glamor_init(ScreenPtr screen)
return TRUE;
}
-void
-radeon_glamor_flush(ScrnInfoPtr pScrn)
-{
- RADEONInfoPtr info = RADEONPTR(pScrn);
-
- if (info->use_glamor)
- glamor_block_handler(pScrn->pScreen);
-}
-
XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt)
{
return glamor_xv_init(pScreen, num_adapt);
diff --git a/driver/xf86-video-ati/src/radeon_glamor.h b/driver/xf86-video-ati/src/radeon_glamor.h
index 36addd70d..246336b18 100644
--- a/driver/xf86-video-ati/src/radeon_glamor.h
+++ b/driver/xf86-video-ati/src/radeon_glamor.h
@@ -28,52 +28,51 @@
#define RADEON_GLAMOR_H
#include "xf86xv.h"
+
+struct radeon_pixmap;
+
#ifdef USE_GLAMOR
+#define GLAMOR_FOR_XORG 1
+#include <glamor.h>
+
#include "radeon_surface.h"
+#ifndef CREATE_PIXMAP_USAGE_SHARED
+#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2
+#endif
+
+#define RADEON_CREATE_PIXMAP_SHARED(usage) \
+ (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \
+ (usage) == CREATE_PIXMAP_USAGE_SHARED)
+
+#ifndef GLAMOR_NO_DRI3
+#define GLAMOR_NO_DRI3 0
+#define glamor_fd_from_pixmap glamor_dri3_fd_from_pixmap
+#define glamor_pixmap_from_fd glamor_egl_dri3_pixmap_from_fd
+#endif
+
+#ifndef GLAMOR_INVERTED_Y_AXIS
+#define GLAMOR_INVERTED_Y_AXIS 0
+#endif
+#ifndef GLAMOR_USE_SCREEN
+#define GLAMOR_USE_SCREEN 0
+#endif
+#ifndef GLAMOR_USE_PICTURE_SCREEN
+#define GLAMOR_USE_PICTURE_SCREEN 0
+#endif
+
Bool radeon_glamor_pre_init(ScrnInfoPtr scrn);
Bool radeon_glamor_init(ScreenPtr screen);
+void radeon_glamor_screen_init(ScreenPtr screen);
Bool radeon_glamor_create_screen_resources(ScreenPtr screen);
void radeon_glamor_free_screen(int scrnIndex, int flags);
-void radeon_glamor_flush(ScrnInfoPtr pScrn);
-
-Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap);
+Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv);
void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
-Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
-
XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt);
-struct radeon_pixmap {
- struct radeon_surface surface;
- struct radeon_bo *bo;
-
- uint32_t tiling_flags;
- int stride;
-};
-
-#if HAS_DEVPRIVATEKEYREC
-extern DevPrivateKeyRec glamor_pixmap_index;
-#else
-extern int glamor_pixmap_index;
-#endif
-
-static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
-{
-#if HAS_DEVPRIVATEKEYREC
- return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
-#else
- return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
-#endif
-}
-
-static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
-{
- dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
-}
-
#else
static inline Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; }
@@ -81,14 +80,10 @@ static inline Bool radeon_glamor_init(ScreenPtr screen) { return FALSE; }
static inline Bool radeon_glamor_create_screen_resources(ScreenPtr screen) { return FALSE; }
static inline void radeon_glamor_free_screen(int scrnIndex, int flags) { }
-static inline void radeon_glamor_flush(ScrnInfoPtr pScrn) { }
-
-static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap) { return TRUE; }
+static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv) { return TRUE; }
static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {}
-static inline Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap) { return FALSE; }
-
static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return NULL; }
static inline XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt) { return NULL; }
diff --git a/driver/xf86-video-ati/src/radeon_glamor_wrappers.c b/driver/xf86-video-ati/src/radeon_glamor_wrappers.c
new file mode 100644
index 000000000..ec81560cc
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_glamor_wrappers.c
@@ -0,0 +1,994 @@
+/*
+ * Copyright © 2001 Keith Packard
+ * 2010 Intel Corporation
+ * 2012,2015 Advanced Micro Devices, Inc.
+ *
+ * Partly based on code Copyright © 2008 Red Hat, Inc.
+ * Partly based on code Copyright © 2000 SuSE, Inc.
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the opyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef USE_GLAMOR
+
+#include "radeon.h"
+#include "radeon_glamor.h"
+
+
+/**
+ * get_drawable_pixmap() returns the backing pixmap for a given drawable.
+ *
+ * @param pDrawable the drawable being requested.
+ *
+ * This function returns the backing pixmap for a drawable, whether it is a
+ * redirected window, unredirected window, or already a pixmap.
+ */
+static PixmapPtr
+get_drawable_pixmap(DrawablePtr pDrawable)
+{
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ return pDrawable->pScreen->
+ GetWindowPixmap((WindowPtr) pDrawable);
+ else
+ return (PixmapPtr) pDrawable;
+}
+
+/* Are there any outstanding GPU operations for this pixmap? */
+static Bool
+radeon_glamor_gpu_pending(uint_fast32_t gpu_synced, uint_fast32_t gpu_access)
+{
+ return (int_fast32_t)(gpu_access - gpu_synced) > 0;
+}
+
+/*
+ * Pixmap CPU access wrappers
+ */
+
+static Bool
+radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
+ PixmapPtr pixmap, struct radeon_pixmap *priv,
+ Bool need_sync)
+{
+ struct radeon_bo *bo = priv->bo;
+ int ret;
+
+ /* When falling back to swrast, flush all pending operations */
+ if (need_sync) {
+ glamor_block_handler(scrn->pScreen);
+ info->gpu_flushed++;
+ }
+
+ if (!pixmap->devPrivate.ptr) {
+ ret = radeon_bo_map(bo, 1);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: bo map (tiling_flags %d) failed: %s\n",
+ __FUNCTION__,
+ priv->tiling_flags,
+ strerror(-ret));
+ return FALSE;
+ }
+
+ pixmap->devPrivate.ptr = bo->ptr;
+ info->gpu_synced = info->gpu_flushed;
+ } else if (need_sync) {
+ radeon_bo_wait(bo);
+ info->gpu_synced = info->gpu_flushed;
+ }
+
+ return TRUE;
+}
+
+static Bool
+radeon_glamor_prepare_access_cpu_ro(ScrnInfoPtr scrn, PixmapPtr pixmap,
+ struct radeon_pixmap *priv)
+{
+ RADEONInfoPtr info;
+ Bool need_sync;
+
+ if (!priv)
+ return TRUE;
+
+ info = RADEONPTR(scrn);
+ need_sync = radeon_glamor_gpu_pending(info->gpu_synced, priv->gpu_write);
+ return radeon_glamor_prepare_access_cpu(scrn, RADEONPTR(scrn), pixmap,
+ priv, need_sync);
+}
+
+static Bool
+radeon_glamor_prepare_access_cpu_rw(ScrnInfoPtr scrn, PixmapPtr pixmap,
+ struct radeon_pixmap *priv)
+{
+ RADEONInfoPtr info;
+ uint_fast32_t gpu_synced;
+ Bool need_sync;
+
+ if (!priv)
+ return TRUE;
+
+ info = RADEONPTR(scrn);
+ gpu_synced = info->gpu_synced;
+ need_sync = radeon_glamor_gpu_pending(gpu_synced, priv->gpu_write) |
+ radeon_glamor_gpu_pending(gpu_synced, priv->gpu_read);
+ return radeon_glamor_prepare_access_cpu(scrn, info, pixmap, priv,
+ need_sync);
+}
+
+static void
+radeon_glamor_finish_access_cpu(PixmapPtr pixmap)
+{
+ /* Nothing to do */
+}
+
+/*
+ * Pixmap GPU access wrappers
+ */
+
+static Bool
+radeon_glamor_prepare_access_gpu(struct radeon_pixmap *priv)
+{
+ return priv != NULL;
+}
+
+static void
+radeon_glamor_finish_access_gpu_ro(RADEONInfoPtr info,
+ struct radeon_pixmap *priv)
+{
+ priv->gpu_read = info->gpu_flushed + 1;
+}
+
+static void
+radeon_glamor_finish_access_gpu_rw(RADEONInfoPtr info,
+ struct radeon_pixmap *priv)
+{
+ priv->gpu_write = priv->gpu_read = info->gpu_flushed + 1;
+}
+
+/*
+ * GC CPU access wrappers
+ */
+
+static Bool
+radeon_glamor_prepare_access_gc(ScrnInfoPtr scrn, GCPtr pGC)
+{
+ struct radeon_pixmap *priv;
+
+ if (pGC->stipple) {
+ priv = radeon_get_pixmap_private(pGC->stipple);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->stipple, priv))
+ return FALSE;
+ }
+ if (pGC->fillStyle == FillTiled) {
+ priv = radeon_get_pixmap_private(pGC->tile.pixmap);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->tile.pixmap,
+ priv)) {
+ if (pGC->stipple)
+ radeon_glamor_finish_access_cpu(pGC->stipple);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void
+radeon_glamor_finish_access_gc(GCPtr pGC)
+{
+ if (pGC->fillStyle == FillTiled)
+ radeon_glamor_finish_access_cpu(pGC->tile.pixmap);
+ if (pGC->stipple)
+ radeon_glamor_finish_access_cpu(pGC->stipple);
+}
+
+/*
+ * Picture CPU access wrappers
+ */
+
+static void
+radeon_glamor_picture_finish_access_cpu(PicturePtr picture)
+{
+ /* Nothing to do */
+}
+
+static Bool
+radeon_glamor_picture_prepare_access_cpu_ro(ScrnInfoPtr scrn,
+ PicturePtr picture)
+{
+ PixmapPtr pixmap;
+ struct radeon_pixmap *priv;
+
+ if (picture->pDrawable == NULL)
+ return TRUE;
+
+ pixmap = get_drawable_pixmap(picture->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv))
+ return FALSE;
+
+ if (picture->alphaMap) {
+ pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
+ radeon_glamor_picture_finish_access_cpu(picture);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+radeon_glamor_picture_prepare_access_cpu_rw(ScrnInfoPtr scrn,
+ PicturePtr picture)
+{
+ PixmapPtr pixmap;
+ struct radeon_pixmap *priv;
+
+ pixmap = get_drawable_pixmap(picture->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv))
+ return FALSE;
+
+ if (picture->alphaMap) {
+ pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ radeon_glamor_picture_finish_access_cpu(picture);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * GC rendering wrappers
+ */
+
+static void
+radeon_glamor_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
+ fSorted);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *bits)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ bits);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static RegionPtr
+radeon_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty,
+ unsigned long bitPlane)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
+ PixmapPtr dst_pix = get_drawable_pixmap(pDst);
+ struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pix);
+ RegionPtr ret = NULL;
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pix, dst_priv)) {
+ PixmapPtr src_pix = get_drawable_pixmap(pSrc);
+ struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix);
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
+ ret =
+ fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
+ dsty, bitPlane);
+ radeon_glamor_finish_access_cpu(src_pix);
+ }
+ radeon_glamor_finish_access_cpu(dst_pix);
+ }
+ return ret;
+}
+
+static RegionPtr
+radeon_glamor_copy_plane_nodstbo(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
+ PixmapPtr src_pix = get_drawable_pixmap(pSrc);
+ struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix);
+ RegionPtr ret = NULL;
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
+ ret = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, bitPlane);
+ radeon_glamor_finish_access_cpu(src_pix);
+ }
+ return ret;
+}
+
+static void
+radeon_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbPolyPoint(pDrawable, pGC, mode, npt, pptInit);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ if (pGC->lineWidth == 0) {
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolyLine(pDrawable, pGC, mode, npt, ppt);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolyLine(pDrawable, pGC, mode, npt, ppt);
+}
+
+static void
+radeon_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment *pSegInit)
+{
+ if (pGC->lineWidth == 0) {
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolySegment(pDrawable, pGC, nsegInit,
+ pSegInit);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
+}
+
+static void
+radeon_glamor_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
+ int nrect, xRectangle *prect)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if ((info->accel_state->force || (priv && !priv->bo)) &&
+ radeon_glamor_prepare_access_gpu(priv)) {
+ info->glamor.SavedPolyFillRect(pDrawable, pGC, nrect, prect);
+ radeon_glamor_finish_access_gpu_rw(info, priv);
+ return;
+ }
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolyFillRect(pDrawable, pGC, nrect, prect);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable, int w, int h, int x, int y)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ priv = radeon_get_pixmap_private(pBitmap);
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
+ y);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pBitmap);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_push_pixels_nodstbo(GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable, int w, int h,
+ int x, int y)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pBitmap);
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
+ fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
+ radeon_glamor_finish_access_cpu(pBitmap);
+ }
+}
+
+static RegionPtr
+radeon_glamor_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty)
+{
+ ScreenPtr screen = pDstDrawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
+ PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
+ struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pixmap);
+ struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pixmap);
+ RegionPtr ret = NULL;
+
+ if (info->accel_state->force || (src_priv && !src_priv->bo) ||
+ (dst_priv && !dst_priv->bo)) {
+ if (!radeon_glamor_prepare_access_gpu(dst_priv))
+ goto fallback;
+ if (src_priv != dst_priv &&
+ !radeon_glamor_prepare_access_gpu(src_priv))
+ goto fallback;
+
+ ret = info->glamor.SavedCopyArea(pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy,
+ width, height, dstx, dsty);
+ radeon_glamor_finish_access_gpu_rw(info, dst_priv);
+ if (src_priv != dst_priv)
+ radeon_glamor_finish_access_gpu_ro(info, src_priv);
+
+ return ret;
+ }
+
+fallback:
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pixmap, dst_priv)) {
+ if (pSrcDrawable == pDstDrawable ||
+ radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
+ src_priv)) {
+ ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+ if (pSrcDrawable != pDstDrawable)
+ radeon_glamor_finish_access_cpu(src_pixmap);
+ }
+ radeon_glamor_finish_access_cpu(dst_pixmap);
+ }
+
+ return ret;
+}
+
+static RegionPtr
+radeon_glamor_copy_area_nodstbo(DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty)
+{
+ ScreenPtr screen = pDstDrawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
+ PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
+ struct radeon_pixmap *src_priv;
+ RegionPtr ret = NULL;
+
+ if (src_pixmap != dst_pixmap) {
+ src_priv = radeon_get_pixmap_private(src_pixmap);
+
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
+ src_priv))
+ return ret;
+ }
+
+ ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
+ width, height, dstx, dsty);
+
+ if (src_pixmap != dst_pixmap)
+ radeon_glamor_finish_access_cpu(src_pixmap);
+
+ return ret;
+}
+
+static const GCOps radeon_glamor_ops = {
+ radeon_glamor_fill_spans,
+ radeon_glamor_set_spans,
+ radeon_glamor_put_image,
+ radeon_glamor_copy_area,
+ radeon_glamor_copy_plane,
+ radeon_glamor_poly_point,
+ radeon_glamor_poly_lines,
+ radeon_glamor_poly_segment,
+ miPolyRectangle,
+ miPolyArc,
+ miFillPolygon,
+ radeon_glamor_poly_fill_rect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ radeon_glamor_image_glyph_blt,
+ radeon_glamor_poly_glyph_blt,
+ radeon_glamor_push_pixels,
+};
+
+static GCOps radeon_glamor_nodstbo_ops;
+
+/**
+ * radeon_glamor_validate_gc() sets the ops to our implementations, which may be
+ * accelerated or may sync the card and fall back to fb.
+ */
+static void
+radeon_glamor_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pGC->pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ glamor_validate_gc(pGC, changes, pDrawable);
+ info->glamor.SavedCopyArea = pGC->ops->CopyArea;
+ info->glamor.SavedPolyFillRect = pGC->ops->PolyFillRect;
+
+ if (radeon_get_pixmap_private(get_drawable_pixmap(pDrawable)) ||
+ (pGC->stipple && radeon_get_pixmap_private(pGC->stipple)) ||
+ (pGC->fillStyle == FillTiled &&
+ radeon_get_pixmap_private(pGC->tile.pixmap)))
+ pGC->ops = (GCOps *)&radeon_glamor_ops;
+ else
+ pGC->ops = &radeon_glamor_nodstbo_ops;
+}
+
+static GCFuncs glamorGCFuncs = {
+ radeon_glamor_validate_gc,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+/**
+ * radeon_glamor_create_gc makes a new GC and hooks up its funcs handler, so that
+ * radeon_glamor_validate_gc() will get called.
+ */
+static int
+radeon_glamor_create_gc(GCPtr pGC)
+{
+ static Bool nodstbo_ops_initialized;
+
+ if (!fbCreateGC(pGC))
+ return FALSE;
+
+ if (!nodstbo_ops_initialized) {
+ radeon_glamor_nodstbo_ops = radeon_glamor_ops;
+
+ radeon_glamor_nodstbo_ops.FillSpans = pGC->ops->FillSpans;
+ radeon_glamor_nodstbo_ops.SetSpans = pGC->ops->SetSpans;
+ radeon_glamor_nodstbo_ops.PutImage = pGC->ops->PutImage;
+ radeon_glamor_nodstbo_ops.CopyArea = radeon_glamor_copy_area_nodstbo;
+ radeon_glamor_nodstbo_ops.CopyPlane = radeon_glamor_copy_plane_nodstbo;
+ radeon_glamor_nodstbo_ops.PolyPoint = pGC->ops->PolyPoint;
+ radeon_glamor_nodstbo_ops.Polylines = pGC->ops->Polylines;
+ radeon_glamor_nodstbo_ops.PolySegment = pGC->ops->PolySegment;
+ radeon_glamor_nodstbo_ops.PolyFillRect = pGC->ops->PolyFillRect;
+ radeon_glamor_nodstbo_ops.ImageGlyphBlt = pGC->ops->ImageGlyphBlt;
+ radeon_glamor_nodstbo_ops.PolyGlyphBlt = pGC->ops->PolyGlyphBlt;
+ radeon_glamor_nodstbo_ops.PushPixels = radeon_glamor_push_pixels_nodstbo;
+
+ nodstbo_ops_initialized = TRUE;
+ }
+
+ pGC->funcs = &glamorGCFuncs;
+
+ return TRUE;
+}
+
+/*
+ * Screen rendering wrappers
+ */
+
+static RegionPtr
+radeon_glamor_bitmap_to_region(PixmapPtr pPix)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
+ RegionPtr ret;
+
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pPix, priv))
+ return NULL;
+ ret = fbPixmapToRegion(pPix);
+ radeon_glamor_finish_access_cpu(pPix);
+ return ret;
+}
+
+static void
+radeon_glamor_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pWin->drawable.pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(&pWin->drawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbCopyWindow(pWin, ptOldOrg, prgnSrc);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
+ fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_get_spans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
+ int *pwidth, int nspans, char *pdstStart)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
+ fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+/*
+ * Picture screen rendering wrappers
+ */
+
+#ifdef RENDER
+
+static void
+radeon_glamor_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pDrawable->pScreen);
+ RADEONInfoPtr info;
+ PixmapPtr pixmap;
+ struct radeon_pixmap *dst_priv, *src_priv = NULL, *mask_priv = NULL;
+ Bool gpu_done = FALSE;
+
+ if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
+ goto fallback;
+
+ pixmap = get_drawable_pixmap(pDst->pDrawable);
+ if (&pixmap->drawable != pDst->pDrawable ||
+ pixmap->usage_hint != RADEON_CREATE_PIXMAP_SCANOUT)
+ goto fallback;
+
+ dst_priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_gpu(dst_priv))
+ goto fallback;
+
+ info = RADEONPTR(scrn);
+ if (!pSrc->pDrawable ||
+ ((pixmap = get_drawable_pixmap(pSrc->pDrawable)) &&
+ (src_priv = radeon_get_pixmap_private(pixmap)) &&
+ radeon_glamor_prepare_access_gpu(src_priv))) {
+ if (!pMask || !pMask->pDrawable ||
+ ((pixmap = get_drawable_pixmap(pMask->pDrawable)) &&
+ (mask_priv = radeon_get_pixmap_private(pixmap)) &&
+ radeon_glamor_prepare_access_gpu(mask_priv))) {
+ info->glamor.SavedComposite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+ gpu_done = TRUE;
+
+ if (mask_priv)
+ radeon_glamor_finish_access_gpu_ro(info, mask_priv);
+ }
+
+ if (src_priv)
+ radeon_glamor_finish_access_gpu_ro(info, src_priv);
+ }
+ radeon_glamor_finish_access_gpu_rw(info, dst_priv);
+
+ if (gpu_done)
+ return;
+
+fallback:
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pDst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, pSrc)) {
+ if (!pMask ||
+ radeon_glamor_picture_prepare_access_cpu_ro(scrn, pMask)) {
+ fbComposite(op, pSrc, pMask, pDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+ if (pMask)
+ radeon_glamor_picture_finish_access_cpu(pMask);
+ }
+ radeon_glamor_picture_finish_access_cpu(pSrc);
+ }
+ radeon_glamor_picture_finish_access_cpu(pDst);
+ }
+}
+
+static void
+radeon_glamor_add_traps(PicturePtr pPicture,
+ INT16 x_off, INT16 y_off, int ntrap, xTrap *traps)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pPicture->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pPicture)) {
+ fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
+ radeon_glamor_picture_finish_access_cpu(pPicture);
+ }
+}
+
+static void
+radeon_glamor_glyphs(CARD8 op,
+ PicturePtr src,
+ PicturePtr dst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->glamor.SavedGlyphs(op, src, dst, maskFormat, xSrc,
+ ySrc, nlist, list, glyphs);
+ radeon_glamor_picture_finish_access_cpu(src);
+ }
+ radeon_glamor_picture_finish_access_cpu(dst);
+ }
+}
+
+static void
+radeon_glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->glamor.SavedTrapezoids(op, src, dst, maskFormat,
+ xSrc, ySrc, ntrap, traps);
+ radeon_glamor_picture_finish_access_cpu(src);
+ }
+ radeon_glamor_picture_finish_access_cpu(dst);
+ }
+}
+
+static void
+radeon_glamor_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tri)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->glamor.SavedTriangles(op, src, dst, maskFormat,
+ xSrc, ySrc, ntri, tri);
+ radeon_glamor_picture_finish_access_cpu(src);
+ }
+ radeon_glamor_picture_finish_access_cpu(dst);
+ }
+}
+
+#endif /* RENDER */
+
+
+/**
+ * radeon_glamor_close_screen() unwraps its wrapped screen functions and tears
+ * down our screen private, before calling down to the next CloseScreen.
+ */
+static Bool
+radeon_glamor_close_screen(CLOSE_SCREEN_ARGS_DECL)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pScreen));
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ pScreen->CreateGC = info->glamor.SavedCreateGC;
+ pScreen->CloseScreen = info->glamor.SavedCloseScreen;
+ pScreen->GetImage = info->glamor.SavedGetImage;
+ pScreen->GetSpans = info->glamor.SavedGetSpans;
+ pScreen->CreatePixmap = info->glamor.SavedCreatePixmap;
+ pScreen->DestroyPixmap = info->glamor.SavedDestroyPixmap;
+ pScreen->CopyWindow = info->glamor.SavedCopyWindow;
+ pScreen->ChangeWindowAttributes =
+ info->glamor.SavedChangeWindowAttributes;
+ pScreen->BitmapToRegion = info->glamor.SavedBitmapToRegion;
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = info->glamor.SavedComposite;
+ ps->Glyphs = info->glamor.SavedGlyphs;
+ ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
+ ps->Trapezoids = info->glamor.SavedTrapezoids;
+ ps->AddTraps = info->glamor.SavedAddTraps;
+ ps->Triangles = info->glamor.SavedTriangles;
+
+ ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
+ }
+#endif
+
+ return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
+}
+
+/**
+ * @param screen screen being initialized
+ */
+void
+radeon_glamor_screen_init(ScreenPtr screen)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
+
+ /*
+ * Replace various fb screen functions
+ */
+ info->glamor.SavedCloseScreen = screen->CloseScreen;
+ screen->CloseScreen = radeon_glamor_close_screen;
+
+ info->glamor.SavedCreateGC = screen->CreateGC;
+ screen->CreateGC = radeon_glamor_create_gc;
+
+ info->glamor.SavedGetImage = screen->GetImage;
+ screen->GetImage = radeon_glamor_get_image;
+
+ info->glamor.SavedGetSpans = screen->GetSpans;
+ screen->GetSpans = radeon_glamor_get_spans;
+
+ info->glamor.SavedCreatePixmap = screen->CreatePixmap;
+ info->glamor.SavedDestroyPixmap = screen->DestroyPixmap;
+
+ info->glamor.SavedCopyWindow = screen->CopyWindow;
+ screen->CopyWindow = radeon_glamor_copy_window;
+
+ info->glamor.SavedBitmapToRegion = screen->BitmapToRegion;
+ screen->BitmapToRegion = radeon_glamor_bitmap_to_region;
+
+#ifdef RENDER
+ {
+ PictureScreenPtr ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ info->glamor.SavedComposite = ps->Composite;
+ ps->Composite = radeon_glamor_composite;
+
+ info->glamor.SavedUnrealizeGlyph = ps->UnrealizeGlyph;
+
+ ps->Glyphs = radeon_glamor_glyphs;
+ ps->Triangles = radeon_glamor_triangles;
+ ps->Trapezoids = radeon_glamor_trapezoids;
+
+ info->glamor.SavedAddTraps = ps->AddTraps;
+ ps->AddTraps = radeon_glamor_add_traps;
+ }
+ }
+#endif
+}
+
+#endif /* USE_GLAMOR */
diff --git a/driver/xf86-video-ati/src/radeon_kms.c b/driver/xf86-video-ati/src/radeon_kms.c
index 1703349f1..8aa763327 100644
--- a/driver/xf86-video-ati/src/radeon_kms.c
+++ b/driver/xf86-video-ati/src/radeon_kms.c
@@ -32,6 +32,8 @@
#include <sys/ioctl.h>
/* Driver data structures */
#include "radeon.h"
+#include "radeon_drm_queue.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
#include "radeon_probe.h"
#include "micmap.h"
@@ -68,12 +70,16 @@ const OptionInfoRec RADEONOptions_KMS[] = {
{ OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE },
#ifdef USE_GLAMOR
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
+ { OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE },
#endif
{ OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE },
- { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -82,12 +88,22 @@ const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions_KMS; }
void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
- struct radeon_accel_state *accel_state = info->accel_state;
+ struct radeon_accel_state *accel_state;
int ret;
+#ifdef USE_GLAMOR
+ if (info->use_glamor) {
+ glamor_block_handler(pScrn->pScreen);
+ info->gpu_flushed++;
+ return;
+ }
+#endif
+
if (!info->cs->cdw)
return;
+ accel_state = info->accel_state;
+
/* release the current VBO so we don't block on mapping it later */
if (info->accel_state->vbo.vb_offset && info->accel_state->vbo.vb_bo) {
radeon_vbo_put(pScrn, &info->accel_state->vbo);
@@ -171,6 +187,9 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn)
info = RADEONPTR(pScrn);
+ if (info->fbcon_pixmap)
+ pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+
if (info->dri2.drm_fd > 0) {
DevUnion *pPriv;
RADEONEntPtr pRADEONEnt;
@@ -230,7 +249,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
return FALSE;
pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
- if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+ if (!drmmode_set_desired_modes(pScrn, &info->drmmode, FALSE))
return FALSE;
drmmode_uevent_init(pScrn, &info->drmmode);
@@ -269,7 +288,11 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
PixmapRegionInit(&pixregion, dirty->slave_dst);
DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+#ifdef HAS_DIRTYTRACKING_ROTATION
+ PixmapSyncDirtyHelper(dirty);
+#else
PixmapSyncDirtyHelper(dirty, &pixregion);
+#endif
radeon_cs_flush_indirect(pScrn);
DamageRegionProcessPending(&dirty->slave_dst->drawable);
@@ -295,6 +318,204 @@ radeon_dirty_update(ScreenPtr screen)
}
#endif
+static Bool
+radeon_scanout_extents_intersect(BoxPtr extents, int x, int y, int w, int h)
+{
+ extents->x1 = max(extents->x1 - x, 0);
+ extents->y1 = max(extents->y1 - y, 0);
+ extents->x2 = min(extents->x2 - x, w);
+ extents->y2 = min(extents->y2 - y, h);
+
+ return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
+}
+
+static Bool
+radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ ScrnInfoPtr scrn;
+ DamagePtr pDamage;
+ RegionPtr pRegion;
+ DrawablePtr pDraw;
+ ScreenPtr pScreen;
+ GCPtr gc;
+ BoxRec extents;
+ RADEONInfoPtr info;
+ Bool force;
+
+ if (!xf86_crtc->enabled ||
+ drmmode_crtc->dpms_mode != DPMSModeOn ||
+ !drmmode_crtc->scanout[scanout_id].pixmap)
+ return FALSE;
+
+ pDamage = drmmode_crtc->scanout[scanout_id].damage;
+ if (!pDamage)
+ return FALSE;
+
+ pRegion = DamageRegion(pDamage);
+ if (!RegionNotEmpty(pRegion))
+ return FALSE;
+
+ pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
+ extents = *RegionExtents(pRegion);
+ RegionEmpty(pRegion);
+ if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y,
+ pDraw->width, pDraw->height))
+ return FALSE;
+
+ pScreen = pDraw->pScreen;
+ gc = GetScratchGC(pDraw->depth, pScreen);
+ scrn = xf86_crtc->scrn;
+ info = RADEONPTR(scrn);
+ force = info->accel_state->force;
+ info->accel_state->force = TRUE;
+
+ ValidateGC(pDraw, gc);
+ (*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable,
+ pDraw, gc,
+ xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
+ extents.x2 - extents.x1, extents.y2 - extents.y1,
+ extents.x1, extents.y1);
+ FreeScratchGC(gc);
+
+ info->accel_state->force = force;
+
+ radeon_cs_flush_indirect(scrn);
+
+ return TRUE;
+}
+
+static void
+radeon_scanout_update_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ xf86CrtcPtr xf86_crtc = event_data;
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+
+ drmmode_crtc->scanout_update_pending = FALSE;
+}
+
+void
+radeon_scanout_update_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
+ void *event_data)
+{
+ radeon_scanout_do_update(event_data, 0);
+
+ radeon_scanout_update_abort(scrn, event_data);
+}
+
+static void
+radeon_scanout_update(xf86CrtcPtr xf86_crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ struct radeon_drm_queue_entry *drm_queue_entry;
+ ScrnInfoPtr scrn;
+ drmVBlank vbl;
+ DamagePtr pDamage;
+ RegionPtr pRegion;
+ DrawablePtr pDraw;
+ BoxRec extents;
+
+ if (!xf86_crtc->enabled ||
+ drmmode_crtc->scanout_update_pending ||
+ !drmmode_crtc->scanout[0].pixmap ||
+ drmmode_crtc->dpms_mode != DPMSModeOn)
+ return;
+
+ pDamage = drmmode_crtc->scanout[0].damage;
+ if (!pDamage)
+ return;
+
+ pRegion = DamageRegion(pDamage);
+ if (!RegionNotEmpty(pRegion))
+ return;
+
+ pDraw = &drmmode_crtc->scanout[0].pixmap->drawable;
+ extents = *RegionExtents(pRegion);
+ if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y,
+ pDraw->width, pDraw->height))
+ return;
+
+ scrn = xf86_crtc->scrn;
+ drm_queue_entry = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+ RADEON_DRM_QUEUE_ID_DEFAULT,
+ xf86_crtc,
+ radeon_scanout_update_handler,
+ radeon_scanout_update_abort);
+ if (!drm_queue_entry) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "radeon_drm_queue_alloc failed for scanout update\n");
+ return;
+ }
+
+ vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+ vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc);
+ vbl.request.sequence = 1;
+ vbl.request.signal = (unsigned long)drm_queue_entry;
+ if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "drmWaitVBlank failed for scanout update: %s\n",
+ strerror(errno));
+ radeon_drm_abort_entry(drm_queue_entry);
+ return;
+ }
+
+ drmmode_crtc->scanout_update_pending = TRUE;
+}
+
+static void
+radeon_scanout_flip_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = event_data;
+
+ drmmode_crtc->scanout_update_pending = FALSE;
+}
+
+static void
+radeon_scanout_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data)
+{
+ radeon_scanout_flip_abort(scrn, event_data);
+}
+
+static void
+radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
+ xf86CrtcPtr xf86_crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ ScrnInfoPtr scrn;
+ struct radeon_drm_queue_entry *drm_queue_entry;
+ unsigned scanout_id;
+
+ if (drmmode_crtc->scanout_update_pending)
+ return;
+
+ scanout_id = drmmode_crtc->scanout_id ^ 1;
+ if (!radeon_scanout_do_update(xf86_crtc, scanout_id))
+ return;
+
+ scrn = xf86_crtc->scrn;
+ drm_queue_entry = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+ RADEON_DRM_QUEUE_ID_DEFAULT,
+ drmmode_crtc,
+ radeon_scanout_flip_handler,
+ radeon_scanout_flip_abort);
+ if (!drm_queue_entry) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM event queue entry failed.\n");
+ return;
+ }
+
+ if (drmModePageFlip(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ drmmode_crtc->scanout[scanout_id].fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, drm_queue_entry)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
+ __func__, strerror(errno));
+ return;
+ }
+
+ drmmode_crtc->scanout_id = scanout_id;
+ drmmode_crtc->scanout_update_pending = TRUE;
+}
+
static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
{
SCREEN_PTR(arg);
@@ -305,25 +526,44 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
pScreen->BlockHandler = RADEONBlockHandler_KMS;
- if (info->use_glamor)
- radeon_glamor_flush(pScrn);
+ if (info->tear_free || info->shadow_primary) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ if (info->tear_free)
+ radeon_scanout_flip(pScreen, info, xf86_config->crtc[c]);
+ else
+ radeon_scanout_update(xf86_config->crtc[c]);
+ }
+ }
radeon_cs_flush_indirect(pScrn);
+
#ifdef RADEON_PIXMAP_SHARING
radeon_dirty_update(pScreen);
#endif
}
+static void RADEONBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
+{
+ SCREEN_PTR(arg);
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
+
+ RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS);
+}
+
static void
radeon_flush_callback(CallbackListPtr *list,
pointer user_data, pointer call_data)
{
ScrnInfoPtr pScrn = user_data;
- if (pScrn->vtSema) {
+ if (pScrn->vtSema)
radeon_cs_flush_indirect(pScrn);
- radeon_glamor_flush(pScrn);
- }
}
static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
@@ -779,14 +1019,48 @@ static void RADEONSetupCapabilities(ScrnInfoPtr pScrn)
pScrn->capabilities = 0;
ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_PRIME, &value);
if (ret == 0) {
- if (value & DRM_PRIME_CAP_EXPORT)
- pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
- if (value & DRM_PRIME_CAP_IMPORT)
- pScrn->capabilities |= RR_Capability_SourceOffload | RR_Capability_SinkOutput;
+ if (value & DRM_PRIME_CAP_EXPORT) {
+ pScrn->capabilities |= RR_Capability_SourceOutput;
+ if (!info->r600_shadow_fb && info->dri2.available)
+ pScrn->capabilities |= RR_Capability_SinkOffload;
+ }
+ if (value & DRM_PRIME_CAP_IMPORT) {
+ pScrn->capabilities |= RR_Capability_SinkOutput;
+ if (!info->r600_shadow_fb && info->dri2.available)
+ pScrn->capabilities |= RR_Capability_SourceOffload;
+ }
}
#endif
}
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+
+/* When the root window is created, initialize the screen contents from
+ * console if -background none was specified on the command line
+ */
+static Bool RADEONCreateWindow_oneshot(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn;
+ RADEONInfoPtr info;
+ Bool ret;
+
+ if (pWin != pScreen->root)
+ ErrorF("%s called for non-root window %p\n", __func__, pWin);
+
+ pScrn = xf86ScreenToScrn(pScreen);
+ info = RADEONPTR(pScrn);
+ pScreen->CreateWindow = info->CreateWindow;
+ ret = pScreen->CreateWindow(pWin);
+
+ if (ret)
+ drmmode_copy_fb(pScrn, &info->drmmode);
+
+ return ret;
+}
+
+#endif
+
Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
{
RADEONInfoPtr info;
@@ -806,7 +1080,6 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
info = RADEONPTR(pScrn);
info->IsSecondary = FALSE;
- info->IsPrimary = FALSE;
info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
if (info->pEnt->location.type != BUS_PCI
#ifdef XSERVER_PLATFORM_BUS
@@ -824,14 +1097,10 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
if(xf86IsPrimInitDone(pScrn->entityList[0]))
{
info->IsSecondary = TRUE;
- pRADEONEnt->pSecondaryScrn = pScrn;
}
else
{
- info->IsPrimary = TRUE;
xf86SetPrimInitDone(pScrn->entityList[0]);
- pRADEONEnt->pPrimaryScrn = pScrn;
- pRADEONEnt->HasSecondary = FALSE;
}
}
@@ -870,6 +1139,8 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
if (!RADEONPreInitAccel_KMS(pScrn)) goto fail;
+ radeon_drm_queue_init();
+
info->allowColorTiling2D = FALSE;
RADEONSetupCapabilities(pScrn);
@@ -920,11 +1191,37 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"KMS Color Tiling 2D: %sabled\n", info->allowColorTiling2D ? "en" : "dis");
+#if USE_GLAMOR
+ if (info->use_glamor) {
+ info->shadow_primary = xf86ReturnOptValBool(info->Options,
+ OPTION_SHADOW_PRIMARY, FALSE);
+
+ if (info->shadow_primary)
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
+ }
+#endif
+
+ info->tear_free = xf86ReturnOptValBool(info->Options, OPTION_TEAR_FREE,
+ FALSE);
+
+ if (info->tear_free)
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TearFree enabled\n");
+
if (info->dri2.pKernelDRMVersion->version_minor >= 8) {
info->allowPageFlip = xf86ReturnOptValBool(info->Options,
OPTION_PAGE_FLIP, TRUE);
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis");
+
+ if (info->tear_free || info->shadow_primary) {
+ xf86DrvMsg(pScrn->scrnIndex,
+ info->allowPageFlip ? X_WARNING : X_DEFAULT,
+ "KMS Pageflipping: disabled%s\n",
+ info->allowPageFlip ?
+ " because of ShadowPrimary/TearFree" : "");
+ info->allowPageFlip = FALSE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis");
+ }
}
info->swapBuffersWait = xf86ReturnOptValBool(info->Options,
@@ -932,12 +1229,16 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"SwapBuffers wait for vsync: %sabled\n", info->swapBuffersWait ? "en" : "dis");
+ if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
+ info->drmmode.delete_dp_12_displays = TRUE;
+ }
+
if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
goto fail;
}
- if (info->drmmode.mode_res->count_crtcs == 1)
+ if (info->drmmode.count_crtcs == 1)
pRADEONEnt->HasCRTC2 = FALSE;
else
pRADEONEnt->HasCRTC2 = TRUE;
@@ -1158,11 +1459,16 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
"RADEONCloseScreen\n");
+ /* Clear mask of assigned crtc's in this generation */
+ pRADEONEnt->assigned_crtcs = 0;
+
drmmode_uevent_fini(pScrn, &info->drmmode);
+ radeon_drm_queue_close(pScrn);
radeon_cs_flush_indirect(pScrn);
DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
@@ -1173,6 +1479,8 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
info->accel_state->exa = NULL;
}
+ radeon_sync_close(pScreen);
+
if (info->accel_state->use_vbos)
radeon_vbo_free_lists(pScrn);
@@ -1209,6 +1517,9 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
int subPixelOrder = SubPixelUnknown;
+ MessageType from;
+ Bool value;
+ int driLevel;
const char *s;
void *front_ptr;
@@ -1319,6 +1630,28 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
}
#endif
+ value = FALSE;
+ from = X_DEFAULT;
+ if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
+ from = X_CONFIG;
+
+ if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
+ (driLevel == 2 || driLevel == 3)) {
+ from = X_CONFIG;
+ value = driLevel == 3;
+ }
+
+ if (value) {
+ value = radeon_sync_init(pScreen) &&
+ radeon_present_screen_init(pScreen) &&
+ radeon_dri3_screen_init(pScreen);
+
+ if (!value)
+ from = X_WARNING;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
+
pScrn->vtSema = TRUE;
xf86SetBackingStore(pScreen);
@@ -1388,13 +1721,20 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
}
pScrn->pScreen = pScreen;
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+ if (serverGeneration == 1 && bgNoneRoot && info->accelOn) {
+ info->CreateWindow = pScreen->CreateWindow;
+ pScreen->CreateWindow = RADEONCreateWindow_oneshot;
+ }
+#endif
+
/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
/* Wrap CloseScreen */
info->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = RADEONCloseScreen_KMS;
pScreen->SaveScreen = RADEONSaveScreen_KMS;
info->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = RADEONBlockHandler_KMS;
+ pScreen->BlockHandler = RADEONBlockHandler_oneshot;
if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn))
return FALSE;
@@ -1447,7 +1787,7 @@ Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL)
pScrn->vtSema = TRUE;
- if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+ if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
return FALSE;
return TRUE;
@@ -1465,6 +1805,7 @@ void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL)
radeon_drop_drm_master(pScrn);
xf86RotateFreeShadow(pScrn);
+ drmmode_scanout_free(pScrn);
xf86_hide_cursors (pScrn);
info->accel_state->XInited3D = FALSE;
@@ -1515,7 +1856,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
}
}
- if (info->allowColorTiling) {
+ if (info->allowColorTiling && !info->shadow_primary) {
if (info->ChipFamily >= CHIP_FAMILY_R600) {
if (info->allowColorTiling2D) {
tiling_flags |= RADEON_TILING_MACRO;
@@ -1578,7 +1919,9 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
- tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
+ if (surface.tile_split)
+ tiling_flags |= eg_tile_split(surface.tile_split)
+ << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
break;
case RADEON_SURF_MODE_1D:
tiling_flags |= RADEON_TILING_MICRO;
@@ -1618,7 +1961,10 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
if (info->front_bo == NULL) {
info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
- base_align, RADEON_GEM_DOMAIN_VRAM, 0);
+ base_align,
+ info->shadow_primary ?
+ RADEON_GEM_DOMAIN_GTT :
+ RADEON_GEM_DOMAIN_VRAM, 0);
if (info->r600_shadow_fb == TRUE) {
if (radeon_bo_map(info->front_bo, 1)) {
ErrorF("Failed to map cursor buffer memory\n");
diff --git a/driver/xf86-video-ati/src/radeon_list.h b/driver/xf86-video-ati/src/radeon_list.h
new file mode 100644
index 000000000..77f74affc
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_list.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RADEON_LIST_H_
+#define _RADEON_LIST_H_
+
+#include <xorg-server.h>
+#include <list.h>
+
+#if !HAVE_XORG_LIST
+#define xorg_list list
+#define xorg_list_init list_init
+#define xorg_list_add list_add
+#define xorg_list_del list_del
+#define xorg_list_for_each_entry list_for_each_entry
+#define xorg_list_for_each_entry_safe list_for_each_entry_safe
+#endif
+
+#endif /* _RADEON_LIST_H_ */
diff --git a/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h b/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h
index bd689201f..4b4b8e454 100644
--- a/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h
+++ b/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h
@@ -612,6 +612,7 @@ static PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_OLAND_6610, PCI_CHIP_OLAND_6610, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6611, PCI_CHIP_OLAND_6611, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6613, PCI_CHIP_OLAND_6613, RES_SHARED_VGA },
+ { PCI_CHIP_OLAND_6617, PCI_CHIP_OLAND_6617, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6620, PCI_CHIP_OLAND_6620, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6621, PCI_CHIP_OLAND_6621, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6623, PCI_CHIP_OLAND_6623, RES_SHARED_VGA },
@@ -632,6 +633,7 @@ static PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_BONAIRE_6658, PCI_CHIP_BONAIRE_6658, RES_SHARED_VGA },
{ PCI_CHIP_BONAIRE_665C, PCI_CHIP_BONAIRE_665C, RES_SHARED_VGA },
{ PCI_CHIP_BONAIRE_665D, PCI_CHIP_BONAIRE_665D, RES_SHARED_VGA },
+ { PCI_CHIP_BONAIRE_665F, PCI_CHIP_BONAIRE_665F, RES_SHARED_VGA },
{ PCI_CHIP_KABINI_9830, PCI_CHIP_KABINI_9830, RES_SHARED_VGA },
{ PCI_CHIP_KABINI_9831, PCI_CHIP_KABINI_9831, RES_SHARED_VGA },
{ PCI_CHIP_KABINI_9832, PCI_CHIP_KABINI_9832, RES_SHARED_VGA },
diff --git a/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h b/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h
index eaf280a28..6dfe1e42f 100644
--- a/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h
+++ b/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h
@@ -612,6 +612,7 @@ static const struct pci_id_match radeon_device_match[] = {
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6610, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6611, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6613, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6617, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6620, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6621, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6623, 0 ),
@@ -632,6 +633,7 @@ static const struct pci_id_match radeon_device_match[] = {
ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_6658, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_665C, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_665D, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_665F, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_KABINI_9830, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_KABINI_9831, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_KABINI_9832, 0 ),
diff --git a/driver/xf86-video-ati/src/radeon_present.c b/driver/xf86-video-ati/src/radeon_present.c
new file mode 100644
index 000000000..bd4d8f284
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_present.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "radeon.h"
+
+#ifdef HAVE_PRESENT_H
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include "radeon_bo_helper.h"
+#include "radeon_glamor.h"
+#include "radeon_video.h"
+
+#include "present.h"
+
+struct radeon_present_vblank_event {
+ uint64_t event_id;
+ xf86CrtcPtr crtc;
+};
+
+static uint32_t crtc_select(int crtc_id)
+{
+ if (crtc_id > 1)
+ return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
+ else if (crtc_id > 0)
+ return DRM_VBLANK_SECONDARY;
+ else
+ return 0;
+}
+
+static RRCrtcPtr
+radeon_present_get_crtc(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
+ xf86CrtcPtr crtc;
+ RRCrtcPtr randr_crtc = NULL;
+
+ crtc = radeon_pick_best_crtc(pScrn, FALSE,
+ window->drawable.x,
+ window->drawable.x + window->drawable.width,
+ window->drawable.y,
+ window->drawable.y + window->drawable.height);
+
+ /* Make sure the CRTC is valid and this is the real front buffer */
+ if (crtc != NULL && !crtc->rotatedData)
+ randr_crtc = crtc->randr_crtc;
+
+ return randr_crtc;
+}
+
+static int
+radeon_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+
+ if (drmmode_crtc->dpms_mode != DPMSModeOn)
+ return BadAlloc;
+
+ return drmmode_crtc_get_ust_msc(xf86_crtc, ust, msc);
+}
+
+/*
+ * Flush the DRM event queue when full; this
+ * makes space for new requests
+ */
+static Bool
+radeon_present_flush_drm_events(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ struct pollfd p = { .fd = drmmode->fd, .events = POLLIN };
+ int r;
+
+ do {
+ r = poll(&p, 1, 0);
+ } while (r == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (r <= 0)
+ return 0;
+
+ return drmHandleEvent(drmmode->fd, &drmmode->event_context) >= 0;
+}
+
+/*
+ * Called when the queued vblank event has occurred
+ */
+static void
+radeon_present_vblank_handler(ScrnInfoPtr scrn, unsigned int msc,
+ uint64_t usec, void *data)
+{
+ struct radeon_present_vblank_event *event = data;
+
+ present_event_notify(event->event_id, usec, msc);
+ free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+radeon_present_vblank_abort(ScrnInfoPtr scrn, void *data)
+{
+ struct radeon_present_vblank_event *event = data;
+
+ free(event);
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ int crtc_id = drmmode_get_crtc_id(xf86_crtc);
+ struct radeon_present_vblank_event *event;
+ struct radeon_drm_queue_entry *queue;
+ drmVBlank vbl;
+ int ret;
+
+ event = calloc(sizeof(struct radeon_present_vblank_event), 1);
+ if (!event)
+ return BadAlloc;
+ event->event_id = event_id;
+ queue = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+ event_id, event,
+ radeon_present_vblank_handler,
+ radeon_present_vblank_abort);
+ if (!queue) {
+ free(event);
+ return BadAlloc;
+ }
+
+ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id);
+ vbl.request.sequence = msc;
+ vbl.request.signal = (unsigned long)queue;
+ for (;;) {
+ ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
+ if (!ret)
+ break;
+ if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) {
+ radeon_drm_abort_entry(queue);
+ return BadAlloc;
+ }
+ }
+
+ return Success;
+}
+
+/*
+ * Remove a pending vblank event from the DRM queue so that it is not reported
+ * to the extension
+ */
+static void
+radeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ radeon_drm_abort_id(event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+radeon_present_flush(WindowPtr window)
+{
+ radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen));
+}
+
+static uint32_t
+radeon_present_get_pixmap_tiling_flags(RADEONInfoPtr info, PixmapPtr pixmap)
+{
+ uint32_t tiling_flags = radeon_get_pixmap_tiling_flags(pixmap);
+
+ /* Micro tiling is always enabled with macro tiling on >= R600, so we
+ * can ignore the micro tiling bit in that case
+ */
+ if ((tiling_flags & RADEON_TILING_MACRO) &&
+ info->ChipFamily >= CHIP_FAMILY_R600)
+ tiling_flags &= ~RADEON_TILING_MICRO;
+
+ return tiling_flags;
+}
+
+/*
+ * Test to see if page flipping is possible on the target crtc
+ */
+static Bool
+radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
+ Bool sync_flip)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr screen_pixmap;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int num_crtcs_on;
+ int i;
+
+ if (!scrn->vtSema)
+ return FALSE;
+
+ if (!info->allowPageFlip)
+ return FALSE;
+
+ if (!sync_flip)
+ return FALSE;
+
+ if (info->drmmode.dri2_flipping)
+ return FALSE;
+
+ /* 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;
+
+ for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
+ drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private;
+
+ if (!config->crtc[i]->enabled)
+ continue;
+
+ if (!drmmode_crtc || drmmode_crtc->rotate.bo != NULL)
+ return FALSE;
+
+ if (drmmode_crtc->dpms_mode == DPMSModeOn)
+ num_crtcs_on++;
+ }
+
+ return num_crtcs_on > 0;
+}
+
+/*
+ * Once the flip has been completed on all CRTCs, notify the
+ * extension code telling it when that happened
+ */
+static void
+radeon_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_present_vblank_event *event = pageflip_data;
+
+ if (!event->crtc)
+ info->drmmode.present_flipping = FALSE;
+
+ present_event_notify(event->event_id, ust, msc);
+ free(event);
+}
+
+/*
+ * The flip has been aborted, free the structure
+ */
+static void
+radeon_present_flip_abort(ScrnInfoPtr scrn, void *pageflip_data)
+{
+ struct radeon_present_vblank_event *event = pageflip_data;
+
+ free(event);
+}
+
+/*
+ * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true,
+ * then wait for vblank. Otherwise, flip immediately
+ */
+static Bool
+radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
+ PixmapPtr pixmap, Bool sync_flip)
+{
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_present_vblank_event *event;
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1;
+ uint32_t handle;
+ Bool ret;
+
+ if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip))
+ return FALSE;
+
+ if (!radeon_get_pixmap_handle(pixmap, &handle))
+ return FALSE;
+
+ event = calloc(1, sizeof(struct radeon_present_vblank_event));
+ if (!event)
+ return FALSE;
+
+ event->event_id = event_id;
+ event->crtc = xf86_crtc;
+
+ ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
+ event_id, event, crtc_id,
+ radeon_present_flip_event,
+ radeon_present_flip_abort);
+ if (!ret)
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
+ else
+ info->drmmode.present_flipping = TRUE;
+
+ return ret;
+}
+
+/*
+ * Queue a flip back to the normal frame buffer
+ */
+static void
+radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ struct radeon_present_vblank_event *event;
+ PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+ uint32_t handle;
+ int i;
+
+ if (!radeon_present_check_flip(NULL, screen->root, pixmap, TRUE))
+ goto modeset;
+
+ if (!radeon_get_pixmap_handle(pixmap, &handle)) {
+ ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n",
+ __func__);
+ goto modeset;
+ }
+
+ event = calloc(1, sizeof(struct radeon_present_vblank_event));
+ if (!event) {
+ ErrorF("%s: calloc failed, display might freeze\n", __func__);
+ goto modeset;
+ }
+
+ event->event_id = event_id;
+
+ if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
+ event_id, event, -1, radeon_present_flip_event,
+ radeon_present_flip_abort))
+ return;
+
+modeset:
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (!crtc->enabled)
+ continue;
+
+ if (drmmode_crtc->dpms_mode == DPMSModeOn)
+ crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
+ else
+ drmmode_crtc->need_modeset = TRUE;
+ }
+
+ present_event_notify(event_id, 0, 0);
+
+ info->drmmode.present_flipping = FALSE;
+}
+
+static present_screen_info_rec radeon_present_screen_info = {
+ .version = 0,
+
+ .get_crtc = radeon_present_get_crtc,
+ .get_ust_msc = radeon_present_get_ust_msc,
+ .queue_vblank = radeon_present_queue_vblank,
+ .abort_vblank = radeon_present_abort_vblank,
+ .flush = radeon_present_flush,
+
+ .capabilities = PresentCapabilityNone,
+ .check_flip = radeon_present_check_flip,
+ .flip = radeon_present_flip,
+ .unflip = radeon_present_unflip,
+};
+
+static Bool
+radeon_present_has_async_flip(ScreenPtr screen)
+{
+#ifdef DRM_CAP_ASYNC_PAGE_FLIP
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ int ret;
+ uint64_t value;
+
+ ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+ if (ret == 0)
+ return value == 1;
+#endif
+ return FALSE;
+}
+
+Bool
+radeon_present_screen_init(ScreenPtr screen)
+{
+ if (radeon_present_has_async_flip(screen))
+ radeon_present_screen_info.capabilities |= PresentCapabilityAsync;
+
+ if (!present_screen_init(screen, &radeon_present_screen_info)) {
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING,
+ "Present extension disabled because present_screen_init failed\n");
+ return FALSE;
+ }
+
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "Present extension enabled\n");
+
+ return TRUE;
+}
+
+#else /* !HAVE_PRESENT_H */
+
+Bool
+radeon_present_screen_init(ScreenPtr screen)
+{
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "Present extension disabled because present.h not available at "
+ "build time\n");
+
+ return FALSE;
+}
+
+#endif
diff --git a/driver/xf86-video-ati/src/radeon_probe.c b/driver/xf86-video-ati/src/radeon_probe.c
index ad1e96ea9..65cf0c9fa 100644
--- a/driver/xf86-video-ati/src/radeon_probe.c
+++ b/driver/xf86-video-ati/src/radeon_probe.c
@@ -154,7 +154,6 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
*/
{
DevUnion *pPriv;
- RADEONEntPtr pRADEONEnt;
xf86SetEntitySharable(entity_num);
@@ -166,14 +165,8 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
- if (!pPriv->ptr) {
+ if (!pPriv->ptr)
pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
- pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = FALSE;
- } else {
- pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = TRUE;
- }
}
free(pEnt);
@@ -271,10 +264,8 @@ radeon_platform_probe(DriverPtr pDriver,
if (!pPriv->ptr) {
pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = FALSE;
} else {
pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = TRUE;
}
pRADEONEnt->platform_dev = dev;
}
diff --git a/driver/xf86-video-ati/src/radeon_probe.h b/driver/xf86-video-ati/src/radeon_probe.h
index 3fe4644c3..258c7be1d 100644
--- a/driver/xf86-video-ati/src/radeon_probe.h
+++ b/driver/xf86-video-ati/src/radeon_probe.h
@@ -132,16 +132,13 @@ typedef struct {
typedef struct
{
- Bool HasSecondary;
Bool HasCRTC2; /* All cards except original Radeon */
- ScrnInfoPtr pSecondaryScrn;
- ScrnInfoPtr pPrimaryScrn;
-
int fd; /* for sharing across zaphod heads */
int fd_ref;
unsigned long fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */
int fd_wakeup_ref;
+ unsigned int assigned_crtcs;
#ifdef XSERVER_PLATFORM_BUS
struct xf86_platform_device *platform_dev;
#endif
diff --git a/driver/xf86-video-ati/src/radeon_sync.c b/driver/xf86-video-ati/src/radeon_sync.c
new file mode 100644
index 000000000..d9ffbaf8e
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_sync.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "radeon.h"
+
+#ifdef HAVE_MISYNCSHM_H
+
+#include "misync.h"
+#include "misyncshm.h"
+#include "misyncstr.h"
+
+/*
+ * This whole file exists to wrap a sync fence trigger operation
+ * so that we can flush the batch buffer to provide serialization
+ * between the server and the shm fence client
+ */
+
+static DevPrivateKeyRec radeon_sync_fence_private_key;
+
+typedef struct _radeon_sync_fence_private {
+ SyncFenceSetTriggeredFunc set_triggered;
+} radeon_sync_fence_private;
+
+#define SYNC_FENCE_PRIV(pFence) \
+ (radeon_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &radeon_sync_fence_private_key)
+
+static void
+radeon_sync_fence_set_triggered (SyncFence *fence)
+{
+ ScreenPtr screen = fence->pScreen;
+ radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+ /* Flush pending rendering operations */
+ radeon_cs_flush_indirect(xf86ScreenToScrn(screen));
+
+ fence->funcs.SetTriggered = private->set_triggered;
+ fence->funcs.SetTriggered(fence);
+ private->set_triggered = fence->funcs.SetTriggered;
+ fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+static void
+radeon_sync_create_fence(ScreenPtr screen,
+ SyncFence *fence,
+ Bool initially_triggered)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+ radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+ screen_funcs->CreateFence = info->CreateFence;
+ screen_funcs->CreateFence(screen, fence, initially_triggered);
+ info->CreateFence = screen_funcs->CreateFence;
+ screen_funcs->CreateFence = radeon_sync_create_fence;
+
+ private->set_triggered = fence->funcs.SetTriggered;
+ fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs;
+
+ if (!miSyncShmScreenInit(screen)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "SYNC extension fences disabled because "
+ "miSyncShmScreenInit failed\n");
+ return FALSE;
+ }
+
+ if (!dixPrivateKeyRegistered(&radeon_sync_fence_private_key)) {
+ if (!dixRegisterPrivateKey(&radeon_sync_fence_private_key,
+ PRIVATE_SYNC_FENCE,
+ sizeof (radeon_sync_fence_private))) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "SYNC extension fences disabled because "
+ "dixRegisterPrivateKey failed\n");
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "SYNC extension fences enabled\n");
+
+ screen_funcs = miSyncGetScreenFuncs(screen);
+ info->CreateFence = screen_funcs->CreateFence;
+ screen_funcs->CreateFence = radeon_sync_create_fence;
+ return TRUE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+
+ if (screen_funcs && info->CreateFence)
+ screen_funcs->CreateFence = info->CreateFence;
+
+ info->CreateFence = NULL;
+}
+
+#else /* !HAVE_MISYNCSHM_H */
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "SYNC extension fences disabled because misyncshm.h not "
+ "available at build time\n");
+
+ return FALSE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+}
+
+#endif
diff --git a/driver/xf86-video-ati/src/radeon_video.c b/driver/xf86-video-ati/src/radeon_video.c
index cbfd554b2..48b06e26d 100644
--- a/driver/xf86-video-ati/src/radeon_video.c
+++ b/driver/xf86-video-ati/src/radeon_video.c
@@ -9,6 +9,7 @@
#include <math.h>
#include "radeon.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
#include "radeon_probe.h"
#include "radeon_video.h"
@@ -73,18 +74,12 @@ Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
return drmmode_crtc->dpms_mode == DPMSModeOn;
}
-uint32_t radeon_get_interpolated_vblanks(xf86CrtcPtr crtc)
-{
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- return drmmode_crtc->interpolated_vblanks;
-}
-
xf86CrtcPtr
radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
int x1, int x2, int y1, int y2)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int coverage, best_coverage, c;
+ int coverage, best_coverage, c, cd;
BoxRec box, crtc_box, cover_box;
RROutputPtr primary_output = NULL;
xf86CrtcPtr best_crtc = NULL, primary_crtc = NULL;
@@ -108,38 +103,30 @@ radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
if (primary_output && primary_output->crtc)
primary_crtc = primary_output->crtc->devPrivate;
- /* first consider only enabled CRTCs */
- for (c = 0; c < xf86_config->num_crtc; c++) {
- xf86CrtcPtr crtc = xf86_config->crtc[c];
-
- if (!radeon_crtc_is_enabled(crtc))
- continue;
-
- radeon_crtc_box(crtc, &crtc_box);
- radeon_box_intersect(&cover_box, &crtc_box, &box);
- coverage = radeon_box_area(&cover_box);
- if (coverage > best_coverage ||
- (coverage == best_coverage && crtc == primary_crtc)) {
- best_crtc = crtc;
- best_coverage = coverage;
- }
- }
- if (best_crtc || !consider_disabled)
- return best_crtc;
-
- /* if we found nothing, repeat the search including disabled CRTCs */
- for (c = 0; c < xf86_config->num_crtc; c++) {
- xf86CrtcPtr crtc = xf86_config->crtc[c];
-
- radeon_crtc_box(crtc, &crtc_box);
- radeon_box_intersect(&cover_box, &crtc_box, &box);
- coverage = radeon_box_area(&cover_box);
- if (coverage > best_coverage ||
- (coverage == best_coverage && crtc == primary_crtc)) {
- best_crtc = crtc;
- best_coverage = coverage;
+ /* first consider only enabled CRTCs
+ * then on second pass consider disabled ones
+ */
+ for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (!cd && !radeon_crtc_is_enabled(crtc))
+ continue;
+
+ radeon_crtc_box(crtc, &crtc_box);
+ radeon_box_intersect(&cover_box, &crtc_box, &box);
+ coverage = radeon_box_area(&cover_box);
+ if (coverage > best_coverage ||
+ (coverage == best_coverage &&
+ crtc == primary_crtc)) {
+ best_crtc = crtc;
+ best_coverage = coverage;
+ }
}
+ if (best_crtc)
+ break;
}
+
return best_crtc;
}
@@ -158,7 +145,7 @@ void RADEONInitVideo(ScreenPtr pScreen)
return;
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
- newAdaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+ newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors));
if (newAdaptors == NULL)
return;
diff --git a/driver/xf86-video-ati/src/radeon_video.h b/driver/xf86-video-ati/src/radeon_video.h
index 2a0929546..e6068e86b 100644
--- a/driver/xf86-video-ati/src/radeon_video.h
+++ b/driver/xf86-video-ati/src/radeon_video.h
@@ -101,6 +101,5 @@ RADEONCopyMungedData(ScrnInfoPtr pScrn,
unsigned int dstPitch, unsigned int h, unsigned int w);
Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc);
-uint32_t radeon_get_interpolated_vblanks(xf86CrtcPtr crtc);
#endif