diff options
author | Matthieu Herrb <matthieu@herrb.eu> | 2017-10-22 18:23:33 +0200 |
---|---|---|
committer | Matthieu Herrb <matthieu@herrb.eu> | 2017-10-22 18:23:33 +0200 |
commit | 7e4b90a9639792571c3f981309acec75f5f25deb (patch) | |
tree | 8d6fa735182d20f4449bae906d36e6a144c8f06b | |
parent | 0ce00785ebdab96f1634a3bc46e6fab055b830dd (diff) | |
parent | b93ae9b159790e8a979e9d5d567a0e6fccd7d08a (diff) |
Merge remote-tracking branch 'origin/master' into obsd
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | README | 16 | ||||
-rwxr-xr-x | autogen.sh | 2 | ||||
-rw-r--r-- | configure.ac | 15 | ||||
-rw-r--r-- | man/radeon.man | 19 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/compat-api.h | 70 | ||||
-rw-r--r-- | src/drmmode_display.c | 1127 | ||||
-rw-r--r-- | src/drmmode_display.h | 103 | ||||
-rw-r--r-- | src/evergreen_exa.c | 2 | ||||
-rw-r--r-- | src/r600_exa.c | 2 | ||||
-rw-r--r-- | src/radeon.h | 137 | ||||
-rw-r--r-- | src/radeon_accel.c | 4 | ||||
-rw-r--r-- | src/radeon_bo_helper.c | 42 | ||||
-rw-r--r-- | src/radeon_bo_helper.h | 4 | ||||
-rw-r--r-- | src/radeon_dri2.c | 243 | ||||
-rw-r--r-- | src/radeon_dri2.h | 1 | ||||
-rw-r--r-- | src/radeon_dri3.c | 3 | ||||
-rw-r--r-- | src/radeon_drm_queue.c | 5 | ||||
-rw-r--r-- | src/radeon_exa.c | 4 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 2 | ||||
-rw-r--r-- | src/radeon_glamor.c | 18 | ||||
-rw-r--r-- | src/radeon_glamor.h | 4 | ||||
-rw-r--r-- | src/radeon_glamor_wrappers.c | 4 | ||||
-rw-r--r-- | src/radeon_kms.c | 742 | ||||
-rw-r--r-- | src/radeon_list.h | 40 | ||||
-rw-r--r-- | src/radeon_present.c | 152 | ||||
-rw-r--r-- | src/radeon_probe.c | 5 | ||||
-rw-r--r-- | src/radeon_probe.h | 16 | ||||
-rw-r--r-- | src/radeon_video.c | 2 |
30 files changed, 1601 insertions, 1186 deletions
diff --git a/Makefile.am b/Makefile.am index f0e2c3ce..b8d99f32 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,8 @@ SUBDIRS = src man conf MAINTAINERCLEANFILES = ChangeLog INSTALL +ACLOCAL_AMFLAGS = -I m4 + .PHONY: ChangeLog INSTALL INSTALL: @@ -1,25 +1,25 @@ -xf86-video-ati - ATI Radeon video driver for the Xorg X server +xf86-video-ati - ATI/AMD Radeon video driver for the Xorg X server -All questions regarding this software should be directed at the -Xorg mailing list: +Patches and questions regarding this software should be directed at the +amd-gfx mailing list: - http://lists.freedesktop.org/mailman/listinfo/xorg + https://lists.freedesktop.org/mailman/listinfo/amd-gfx Please submit bug reports to the Xorg bugzilla: - https://bugs.freedesktop.org/enter_bug.cgi?product=xorg + https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon The master development code repository can be found at: git://anongit.freedesktop.org/git/xorg/driver/xf86-video-ati - http://cgit.freedesktop.org/xorg/driver/xf86-video-ati + https://cgit.freedesktop.org/xorg/driver/xf86-video-ati For patch submission instructions, see: - http://www.x.org/wiki/Development/Documentation/SubmittingPatches + https://www.x.org/wiki/Development/Documentation/SubmittingPatches For more information on the git code manager, see: - http://wiki.x.org/wiki/GitPage + https://wiki.x.org/wiki/GitPage @@ -6,7 +6,7 @@ test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd "$srcdir" -autoreconf -v --install || exit 1 +autoreconf -f -v --install || exit 1 cd "$ORIGDIR" || exit $? git config --local --get format.subjectPrefix >/dev/null 2>&1 || diff --git a/configure.ac b/configure.ac index 732f7050..a11ba2a4 100644 --- a/configure.ac +++ b/configure.ac @@ -23,12 +23,13 @@ # Initialize Autoconf AC_PREREQ([2.60]) AC_INIT([xf86-video-ati], - [7.8.99], - [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], + [7.10.99], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon], [xf86-video-ati]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIRS([m4]) AC_CONFIG_AUX_DIR(.) @@ -69,11 +70,11 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Checks for libraries. -PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.60]) +PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.78]) PKG_CHECK_MODULES(LIBDRM_RADEON, [libdrm_radeon]) # Obtain compiler/linker options for the driver dependencies -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.10 xproto fontsproto xf86driproto $REQUIRED_MODULES]) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.13 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") @@ -171,12 +172,6 @@ AC_CHECK_DECL(xf86CursorResetCursor, [#include <xorg-server.h> #include <xf86Cursor.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> diff --git a/man/radeon.man b/man/radeon.man index 8990ae21..f4441c4b 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -281,10 +281,15 @@ Enable DRI2 page flipping. The default is Pageflipping is supported on all radeon hardware. .TP .BI "Option \*qTearFree\*q \*q" boolean \*q -Enable tearing prevention using the hardware page flipping mechanism. Requires allocating two -separate scanout buffers for each CRTC. Enabling this option currently disables Option -\*qEnablePageFlip\*q. The default is -.B off. +Set the default value of the per-output 'TearFree' property, which controls +tearing prevention using the hardware page flipping mechanism. TearFree is +on for any CRTC associated with one or more outputs with TearFree on. Two +separate scanout buffers need to be allocated for each CRTC with TearFree +on. If this option is set, the default value of the property is 'on' or 'off' +accordingly. If this option isn't set, the default value of the property is +.B auto, +which means that TearFree is on for rotated outputs, outputs with RandR +transforms applied and for RandR 1.4 slave outputs, otherwise off. .TP .BI "Option \*qAccelMethod\*q \*q" "string" \*q Chooses between available acceleration architectures. Valid values are @@ -385,17 +390,17 @@ __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(_ .IP " 1." 4 Wiki page: .RS 4 -http://www.x.org/wiki/radeon +https://www.x.org/wiki/radeon .RE .IP " 2." 4 Overview about radeon development code: .RS 4 -http://cgit.freedesktop.org/xorg/driver/xf86-video-ati/ +https://cgit.freedesktop.org/xorg/driver/xf86-video-ati/ .RE .IP " 3." 4 Mailing list: .RS 4 -http://lists.x.org/mailman/listinfo/xorg-driver-ati +https://lists.freedesktop.org/mailman/listinfo/amd-gfx .RE .IP " 4." 4 IRC channel: diff --git a/src/Makefile.am b/src/Makefile.am index 8f39e213..ed1bfa9e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -96,7 +96,6 @@ EXTRA_DIST = \ radeon_exa_shared.h \ radeon_glamor.h \ radeon.h \ - radeon_list.h \ radeon_probe.h \ radeon_reg.h \ radeon_version.h \ diff --git a/src/compat-api.h b/src/compat-api.h index 80a3ac46..f4e7524f 100644 --- a/src/compat-api.h +++ b/src/compat-api.h @@ -23,77 +23,15 @@ * Author: Dave Airlie <airlied@redhat.com> */ -/* this file provides API compat between server post 1.13 and pre it, - it should be reused inside as many drivers as possible */ #ifndef COMPAT_API_H #define COMPAT_API_H -#ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR -#define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum] -#define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p -#endif - -#ifndef XF86_HAS_SCRN_CONV -#define xf86ScreenToScrn(s) xf86Screens[(s)->myNum] -#define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex] -#endif - -#ifndef XF86_SCRN_INTERFACE - -#define SCRN_ARG_TYPE int -#define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = xf86Screens[(arg1)] - -#define SCREEN_ARG_TYPE int -#define SCREEN_PTR(arg1) ScreenPtr pScreen = screenInfo.screens[(arg1)] - -#define SCREEN_INIT_ARGS_DECL int i, ScreenPtr pScreen, int argc, char **argv - -#define BLOCKHANDLER_ARGS_DECL int arg, pointer blockData, pointer pTimeout, pointer pReadmask -#define BLOCKHANDLER_ARGS arg, blockData, pTimeout, pReadmask - -#define CLOSE_SCREEN_ARGS_DECL int scrnIndex, ScreenPtr pScreen -#define CLOSE_SCREEN_ARGS scrnIndex, pScreen - -#define ADJUST_FRAME_ARGS_DECL int arg, int x, int y, int flags - -#define SWITCH_MODE_ARGS_DECL int arg, DisplayModePtr mode, int flags - -#define FREE_SCREEN_ARGS_DECL int arg, int flags - -#define VT_FUNC_ARGS_DECL int arg, int flags -#define VT_FUNC_ARGS(flags) pScrn->scrnIndex, (flags) - -#define XF86_ENABLEDISABLEFB_ARG(x) ((x)->scrnIndex) -#else -#define SCRN_ARG_TYPE ScrnInfoPtr -#define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = (arg1) - -#define SCREEN_ARG_TYPE ScreenPtr -#define SCREEN_PTR(arg1) ScreenPtr pScreen = (arg1) - -#define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv - #if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) -#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout -#define BLOCKHANDLER_ARGS arg, pTimeout +#define BLOCKHANDLER_ARGS_DECL ScreenPtr pScreen, pointer pTimeout +#define BLOCKHANDLER_ARGS pScreen, pTimeout #else -#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask -#define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask -#endif - -#define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen -#define CLOSE_SCREEN_ARGS pScreen - -#define ADJUST_FRAME_ARGS_DECL ScrnInfoPtr arg, int x, int y -#define SWITCH_MODE_ARGS_DECL ScrnInfoPtr arg, DisplayModePtr mode - -#define FREE_SCREEN_ARGS_DECL ScrnInfoPtr arg - -#define VT_FUNC_ARGS_DECL ScrnInfoPtr arg -#define VT_FUNC_ARGS(flags) pScrn - -#define XF86_ENABLEDISABLEFB_ARG(x) (x) - +#define BLOCKHANDLER_ARGS_DECL ScreenPtr pScreen, pointer pTimeout, pointer pReadmask +#define BLOCKHANDLER_ARGS pScreen, pTimeout, pReadmask #endif #endif diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 2258e7a6..369c1efc 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -34,18 +34,16 @@ #include <time.h> #include "cursorstr.h" #include "damagestr.h" +#include "list.h" #include "micmap.h" #include "xf86cmap.h" #include "xf86Priv.h" #include "radeon.h" #include "radeon_bo_helper.h" #include "radeon_glamor.h" -#include "radeon_list.h" #include "radeon_reg.h" -#ifdef RADEON_PIXMAP_SHARING #include <dri.h> -#endif #include "drmmode_display.h" @@ -99,6 +97,14 @@ RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name) return FALSE; } + +/* Wait for the boolean condition to be FALSE */ +#define drmmode_crtc_wait_pending_event(drmmode_crtc, fd, condition) \ + do {} while ((condition) && \ + drmHandleEvent(fd, &drmmode_crtc->drmmode->event_context) \ + > 0); + + static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, int width, int height, int depth, int bpp, @@ -243,6 +249,41 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn, } /* + * Utility helper for drmWaitVBlank + */ +Bool +drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, + uint32_t target_seq, unsigned long signal, uint64_t *ust, + uint32_t *result_seq) +{ + int crtc_id = drmmode_get_crtc_id(crtc); + ScrnInfoPtr scrn = crtc->scrn; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + drmVBlank vbl; + + if (crtc_id == 1) + type |= DRM_VBLANK_SECONDARY; + else if (crtc_id > 1) + type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & + DRM_VBLANK_HIGH_CRTC_MASK; + + vbl.request.type = type; + vbl.request.sequence = target_seq; + vbl.request.signal = signal; + + if (drmWaitVBlank(pRADEONEnt->fd, &vbl) != 0) + return FALSE; + + if (ust) + *ust = (uint64_t)vbl.reply.tval_sec * 1000000 + + vbl.reply.tval_usec; + if (result_seq) + *result_seq = vbl.reply.sequence; + + return TRUE; +} + +/* * Retrieves present time in microseconds that is compatible * with units used by vblank timestamps. Depending on the kernel * version and DRM kernel module configuration, the vblank @@ -272,23 +313,15 @@ int drmmode_get_current_ust(int drm_fd, CARD64 *ust) int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) { ScrnInfoPtr scrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(scrn); - drmVBlank vbl; - int ret; + uint32_t seq; - 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) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); - return ret; + return -1; } - *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; - *msc = vbl.reply.sequence; + *msc = seq; return Success; } @@ -298,37 +331,28 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ScrnInfoPtr scrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(scrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); CARD64 ust; int ret; - drmmode_crtc->pending_dpms_mode = mode; - if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { - drmVBlank vbl; + uint32_t seq; - /* Wait for any pending flip to finish */ - if (drmmode_crtc->flip_pending) - return; + drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, + drmmode_crtc->flip_pending); /* * On->Off transition: record the last vblank time, * sequence number and frame period. */ - 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) + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust, + &seq)) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get last vblank counter\n", __func__); else { - CARD64 seq = (CARD64)vbl.reply.sequence; CARD64 nominal_frame_rate, pix_in_frame; - ust = ((CARD64)vbl.reply.tval_sec * 1000000) + - vbl.reply.tval_usec; drmmode_crtc->dpms_last_ust = ust; drmmode_crtc->dpms_last_seq = seq; nominal_frame_rate = crtc->mode.Clock; @@ -345,7 +369,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) * Off->On transition: calculate and accumulate the * number of interpolated vblanks while we were in Off state */ - ret = drmmode_get_current_ust(info->dri2.drm_fd, &ust); + ret = drmmode_get_current_ust(pRADEONEnt->fd, &ust); if (ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); @@ -365,16 +389,15 @@ static void drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); /* Disable unused CRTCs */ if (!crtc->enabled || mode != DPMSModeOn) { - /* Wait for any pending flip to finish */ - if (drmmode_crtc->flip_pending) - return; - - drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, + drmmode_crtc->flip_pending); + drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, NULL, 0, NULL); + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); } else if (drmmode_crtc->dpms_mode != DPMSModeOn) crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); @@ -384,6 +407,7 @@ static PixmapPtr create_pixmap_for_fbcon(drmmode_ptr drmmode, ScrnInfoPtr pScrn, int fbcon_id) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); PixmapPtr pixmap = info->fbcon_pixmap; struct radeon_bo *bo; @@ -393,7 +417,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, if (pixmap) return pixmap; - fbcon = drmModeGetFB(drmmode->fd, fbcon_id); + fbcon = drmModeGetFB(pRADEONEnt->fd, fbcon_id); if (fbcon == NULL) return NULL; @@ -403,7 +427,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, goto out_free_fb; flink.handle = fbcon->handle; - if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { + if (ioctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't flink fbcon handle\n"); goto out_free_fb; @@ -447,8 +471,9 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); - PixmapPtr src, dst; ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr src, dst = pScreen->GetScreenPixmap(pScreen); + struct drmmode_fb *fb = radeon_pixmap_get_fb(dst); int fbcon_id = 0; Bool force; GCPtr gc; @@ -464,7 +489,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) if (!fbcon_id) return; - if (fbcon_id == drmmode->fb_id) { + if (fbcon_id == fb->handle) { /* in some rare case there might be no fbcon and we might already * be the one with the current fb to avoid a false deadlck in * kernel ttm code just do nothing as anyway there is nothing @@ -477,8 +502,6 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) if (!src) return; - dst = pScreen->GetScreenPixmap(pScreen); - gc = GetScratchGC(pScrn->depth, pScreen); ValidateGC(&dst->drawable, gc); @@ -490,15 +513,12 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) FreeScratchGC(gc); - radeon_cs_flush_indirect(pScrn); - radeon_bo_wait(info->front_bo); - pScreen->canDoBGNoneRoot = TRUE; destroy_pixmap_for_fbcon(pScrn); return; } -static void +void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, struct drmmode_scanout *scanout) { @@ -508,52 +528,27 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, } 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; } } -static void +void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc) { - if (drmmode_crtc->flip_pending) { - drmmode_crtc->scanout_destroy[0] = drmmode_crtc->scanout[0]; - drmmode_crtc->scanout[0].pixmap = NULL; - drmmode_crtc->scanout[0].bo = NULL; - drmmode_crtc->scanout_destroy[1] = drmmode_crtc->scanout[1]; - drmmode_crtc->scanout[1].pixmap = NULL; - drmmode_crtc->scanout[1].bo = NULL; - } else { - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout[0]); - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout[1]); - } + drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, + &drmmode_crtc->scanout[0]); + drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, + &drmmode_crtc->scanout[1]); - if (drmmode_crtc->scanout_damage) { + if (drmmode_crtc->scanout_damage) DamageDestroy(drmmode_crtc->scanout_damage); - drmmode_crtc->scanout_damage = NULL; - RegionUninit(&drmmode_crtc->scanout_last_region); - } } -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_scanout_free(xf86_config->crtc[c]->driver_private); -} - -static void * -drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, - struct drmmode_scanout *scanout, - int width, int height, int *pitch) +PixmapPtr +drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, + int width, int height) { ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -561,11 +556,11 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, drmmode_ptr drmmode = drmmode_crtc->drmmode; struct radeon_surface surface; uint32_t tiling = RADEON_CREATE_PIXMAP_TILING_MACRO; - int ret; + int pitch; - if (scanout->bo) { + if (scanout->pixmap) { if (scanout->width == width && scanout->height == height) - return scanout->bo->ptr; + return scanout->pixmap; drmmode_crtc_scanout_destroy(drmmode, scanout); } @@ -574,48 +569,10 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, tiling |= RADEON_CREATE_PIXMAP_TILING_MICRO; scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth, tiling, pScrn->bitsPerPixel, - pitch, &surface, &tiling); - if (scanout->bo == NULL) - return NULL; - - radeon_bo_map(scanout->bo, 1); - - ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth, - pScrn->bitsPerPixel, *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; - int pitch; - - if (scanout->pixmap) { - if (scanout->width == width && scanout->height == height) - return scanout->pixmap; - - drmmode_crtc_scanout_destroy(drmmode, scanout); - } - + &pitch, &surface, &tiling); if (!scanout->bo) { - if (!drmmode_crtc_scanout_allocate(crtc, scanout, width, height, - &pitch)) - return NULL; + ErrorF("failed to create CRTC scanout BO\n"); + return NULL; } scanout->pixmap = drmmode_create_bo_pixmap(pScrn, @@ -623,9 +580,19 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, pScrn->depth, pScrn->bitsPerPixel, pitch, scanout->bo, NULL); - if (scanout->pixmap == NULL) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't allocate scanout pixmap for CRTC\n"); + if (!scanout->pixmap) { + ErrorF("failed to create CRTC scanout pixmap\n"); + goto error; + } + + if (radeon_pixmap_get_fb(scanout->pixmap)) { + scanout->width = width; + scanout->height = height; + } else { + ErrorF("failed to create CRTC scanout FB\n"); +error: + drmmode_crtc_scanout_destroy(drmmode, scanout); + } return scanout->pixmap; } @@ -633,11 +600,28 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, static void radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure) { + drmmode_crtc_private_ptr drmmode_crtc = closure; + + if (drmmode_crtc->ignore_damage) { + RegionEmpty(&damage->damage); + drmmode_crtc->ignore_damage = FALSE; + return; + } + /* Only keep track of the extents */ RegionUninit(&damage->damage); damage->damage.data = NULL; } +static void +drmmode_screen_damage_destroy(DamagePtr damage, void *closure) +{ + drmmode_crtc_private_ptr drmmode_crtc = closure; + + drmmode_crtc->scanout_damage = NULL; + RegionUninit(&drmmode_crtc->scanout_last_region); +} + static Bool drmmode_can_use_hw_cursor(xf86CrtcPtr crtc) { @@ -651,7 +635,7 @@ drmmode_can_use_hw_cursor(xf86CrtcPtr crtc) if (crtc->transformPresent) return FALSE; -#if XF86_CRTC_VERSION >= 4 && XF86_CRTC_VERSION < 7 +#if XF86_CRTC_VERSION < 7 /* Xorg doesn't correctly handle cursor position transform in the * rotation case */ @@ -660,33 +644,61 @@ drmmode_can_use_hw_cursor(xf86CrtcPtr crtc) return FALSE; #endif -#if defined(RADEON_PIXMAP_SHARING) /* HW cursor not supported with RandR 1.4 multihead up to 1.18.99.901 */ if (xorgGetVersion() <= XORG_VERSION_NUMERIC(1,18,99,901,0) && !xorg_list_is_empty(&crtc->scrn->pScreen->pixmap_dirty_list)) return FALSE; -#endif return TRUE; } -#if XF86_CRTC_VERSION >= 4 +static void +drmmode_crtc_update_tear_free(xf86CrtcPtr crtc) +{ + RADEONInfoPtr info = RADEONPTR(crtc->scrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + int i; + + drmmode_crtc->tear_free = FALSE; + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + drmmode_output_private_ptr drmmode_output = output->driver_private; + + if (output->crtc != crtc) + continue; + + if (drmmode_output->tear_free == 1 || + (drmmode_output->tear_free == 2 && + (crtc->scrn->pScreen->isGPU || + info->shadow_primary || + crtc->transformPresent || crtc->rotation != RR_Rotate_0))) { + drmmode_crtc->tear_free = TRUE; + return; + } + } +} + +#if XF86_CRTC_VERSION < 7 +#define XF86DriverTransformOutput TRUE +#define XF86DriverTransformNone FALSE +#endif static Bool drmmode_handle_transform(xf86CrtcPtr crtc) { Bool ret; -#if XF86_CRTC_VERSION >= 7 +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) if (crtc->transformPresent || crtc->rotation != RR_Rotate_0) crtc->driverIsPerformingTransform = XF86DriverTransformOutput; else crtc->driverIsPerformingTransform = XF86DriverTransformNone; #else - RADEONInfoPtr info = RADEONPTR(crtc->scrn); - - crtc->driverIsPerformingTransform = crtc->transformPresent || - (info->tear_free && crtc->rotation != RR_Rotate_0); + crtc->driverIsPerformingTransform = !crtc->transformPresent && + crtc->rotation != RR_Rotate_0 && + (crtc->rotation & 0xf) == RR_Rotate_0; #endif ret = xf86CrtcRotate(crtc); @@ -696,15 +708,175 @@ drmmode_handle_transform(xf86CrtcPtr crtc) return ret; } -#else -static Bool -drmmode_handle_transform(xf86CrtcPtr crtc) +static void +drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, + unsigned scanout_id, struct drmmode_fb **fb, + int *x, int *y) { - return xf86CrtcRotate(crtc); + ScrnInfoPtr scrn = crtc->scrn; + ScreenPtr screen = scrn->pScreen; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + if (drmmode_crtc->tear_free && + !drmmode_crtc->scanout[1].pixmap) { + RegionPtr region; + BoxPtr box; + + drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], + mode->HDisplay, + mode->VDisplay); + region = &drmmode_crtc->scanout_last_region; + RegionUninit(region); + region->data = NULL; + box = RegionExtents(region); + box->x1 = crtc->x; + box->y1 = crtc->y; + box->x2 = crtc->x + mode->HDisplay; + box->y2 = crtc->y + mode->VDisplay; + } + + if (scanout_id != drmmode_crtc->scanout_id) { + PixmapDirtyUpdatePtr dirty = NULL; + + xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, + ent) { + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { + dirty->slave_dst = + drmmode_crtc->scanout[scanout_id].pixmap; + break; + } + } + + if (!drmmode_crtc->tear_free) { + GCPtr gc = GetScratchGC(scrn->depth, screen); + + ValidateGC(&drmmode_crtc->scanout[0].pixmap->drawable, gc); + gc->ops->CopyArea(&drmmode_crtc->scanout[1].pixmap->drawable, + &drmmode_crtc->scanout[0].pixmap->drawable, + gc, 0, 0, mode->HDisplay, mode->VDisplay, + 0, 0); + FreeScratchGC(gc); + radeon_cs_flush_indirect(scrn); + radeon_bo_wait(drmmode_crtc->scanout[0].bo); + } + } + + *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + *x = *y = 0; + drmmode_crtc->scanout_id = scanout_id; } + -#endif +static void +drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, + unsigned scanout_id, struct drmmode_fb **fb, int *x, + int *y) +{ + ScrnInfoPtr scrn = crtc->scrn; + ScreenPtr screen = scrn->pScreen; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[scanout_id], + mode->HDisplay, mode->VDisplay); + if (drmmode_crtc->tear_free) { + drmmode_crtc_scanout_create(crtc, + &drmmode_crtc->scanout[scanout_id ^ 1], + mode->HDisplay, mode->VDisplay); + } + + if (drmmode_crtc->scanout[scanout_id].pixmap && + (!drmmode_crtc->tear_free || + drmmode_crtc->scanout[scanout_id ^ 1].pixmap)) { + RegionPtr region; + BoxPtr box; + + if (!drmmode_crtc->scanout_damage) { + drmmode_crtc->scanout_damage = + DamageCreate(radeon_screen_damage_report, + drmmode_screen_damage_destroy, + DamageReportRawRegion, + TRUE, screen, drmmode_crtc); + DamageRegister(&screen->root->drawable, + drmmode_crtc->scanout_damage); + } + + region = DamageRegion(drmmode_crtc->scanout_damage); + RegionUninit(region); + region->data = NULL; + box = RegionExtents(region); + box->x1 = 0; + box->y1 = 0; + box->x2 = max(box->x2, scrn->virtualX); + box->y2 = max(box->y2, scrn->virtualY); + + *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + *x = *y = 0; + + radeon_scanout_do_update(crtc, scanout_id, + screen->GetWindowPixmap(screen->root), + box); + radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo); + } +} + +static void +drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, + uint16_t *blue, int size) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); + + drmModeCrtcSetGamma(pRADEONEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, size, red, green, + blue); +} + +Bool +drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb, DisplayModePtr mode, + int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + uint32_t *output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); + int output_count = 0; + drmModeModeInfo kmode; + Bool ret; + int i; + + if (!output_ids) + return FALSE; + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + drmmode_output_private_ptr drmmode_output = output->driver_private; + + if (output->crtc != crtc) + continue; + + output_ids[output_count] = drmmode_output->mode_output->connector_id; + output_count++; + } + + drmmode_ConvertToKMode(scrn, &kmode, mode); + + ret = drmModeSetCrtc(pRADEONEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, + fb->handle, x, y, output_ids, + output_count, &kmode) == 0; + + if (ret) { + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb); + } else { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "failed to set mode: %s\n", strerror(errno)); + } + + free(output_ids); + return ret; +} static Bool drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, @@ -713,19 +885,23 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, ScrnInfoPtr pScrn = crtc->scrn; ScreenPtr pScreen = pScrn->pScreen; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - unsigned scanout_id = drmmode_crtc->scanout_id ^ info->tear_free; + unsigned scanout_id = 0; drmmode_ptr drmmode = drmmode_crtc->drmmode; int saved_x, saved_y; Rotation saved_rotation; DisplayModeRec saved_mode; - uint32_t *output_ids = NULL; - int output_count = 0; Bool ret = FALSE; int i; - int fb_id; - drmModeModeInfo kmode; + struct drmmode_fb *fb = NULL; + + /* The root window contents may be undefined before the WindowExposures + * hook is called for it, so bail if we get here before that + */ + if (pScreen->WindowExposures == RADEONWindowExposures_oneshot) + return FALSE; saved_mode = crtc->mode; saved_x = crtc->x; @@ -738,114 +914,55 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, crtc->y = y; crtc->rotation = rotation; - output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); - if (!output_ids) - goto done; - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - drmmode_output_private_ptr drmmode_output; - - if (output->crtc != crtc) - continue; - - drmmode_output = output->driver_private; - output_ids[output_count] = drmmode_output->mode_output->connector_id; - output_count++; - } - if (!drmmode_handle_transform(crtc)) goto done; - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); + drmmode_crtc_update_tear_free(crtc); + if (drmmode_crtc->tear_free) + scanout_id = drmmode_crtc->scanout_id; - drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); + drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); - fb_id = drmmode->fb_id; -#ifdef RADEON_PIXMAP_SHARING - if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) { - fb_id = drmmode_crtc->scanout[scanout_id].fb_id; - x = y = 0; - } else -#endif - if (drmmode_crtc->rotate.fb_id) { - fb_id = drmmode_crtc->rotate.fb_id; + if (drmmode_crtc->prime_scanout_pixmap) { + drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id, + &fb, &x, &y); + } else if (drmmode_crtc->rotate.pixmap) { + fb = radeon_pixmap_get_fb(drmmode_crtc->rotate.pixmap); x = y = 0; - } else if (!radeon_is_gpu_screen(pScreen) && - (info->tear_free || -#if XF86_CRTC_VERSION >= 4 + } else if (!pScreen->isGPU && + (drmmode_crtc->tear_free || crtc->driverIsPerformingTransform || -#endif 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[0].pixmap && - (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) { - RegionPtr pRegion; - BoxPtr pBox; - - if (!drmmode_crtc->scanout_damage) { - drmmode_crtc->scanout_damage = - DamageCreate(radeon_screen_damage_report, - NULL, DamageReportRawRegion, - TRUE, pScreen, NULL); - DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable, - drmmode_crtc->scanout_damage); - } - - pRegion = DamageRegion(drmmode_crtc->scanout_damage); - RegionUninit(pRegion); - pRegion->data = NULL; - pBox = RegionExtents(pRegion); - pBox->x1 = 0; - pBox->y1 = 0; - pBox->x2 = max(pBox->x2, pScrn->virtualX); - pBox->y2 = max(pBox->y2, pScrn->virtualY); - - fb_id = drmmode_crtc->scanout[scanout_id].fb_id; - x = y = 0; - - radeon_scanout_do_update(crtc, scanout_id); - radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo); - } + drmmode_crtc_scanout_update(crtc, mode, scanout_id, + &fb, &x, &y); } - if (fb_id == 0) { - if (drmModeAddFB(drmmode->fd, - pScrn->virtualX, - pScrn->virtualY, - pScrn->depth, pScrn->bitsPerPixel, - pScrn->displayWidth * info->pixel_bytes, - info->front_bo->handle, - &drmmode->fb_id) < 0) { - ErrorF("failed to add fb\n"); - goto done; - } - - fb_id = drmmode->fb_id; + if (!fb) + fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root)); + if (!fb) { + fb = radeon_fb_create(pRADEONEnt->fd, pScrn->virtualX, + pScrn->virtualY, pScrn->depth, + pScrn->bitsPerPixel, + pScrn->displayWidth * info->pixel_bytes, + info->front_bo->handle); + /* Prevent refcnt of ad-hoc FBs from reaching 2 */ + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); + drmmode_crtc->fb = fb; } + if (!fb) { + ErrorF("failed to add FB for modeset\n"); + goto done; + } + + drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, + drmmode_crtc->flip_pending); - /* Wait for any pending flip to finish */ - do {} while (drmmode_crtc->flip_pending && - drmHandleEvent(drmmode->fd, - &drmmode->event_context) > 0); - - 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\n", strerror(errno)); + if (!drmmode_set_mode(crtc, fb, mode, x, y)) goto done; - } else - ret = TRUE; + + ret = TRUE; if (pScreen) xf86CrtcSetScreenSubpixelOrder(pScreen); @@ -890,12 +1007,16 @@ done: } else { crtc->active = TRUE; - if (fb_id != drmmode_crtc->scanout[scanout_id].fb_id) + if (drmmode_crtc->scanout[scanout_id].pixmap && + fb != radeon_pixmap_get_fb(drmmode_crtc-> + scanout[scanout_id].pixmap)) drmmode_crtc_scanout_free(drmmode_crtc); + else if (!drmmode_crtc->tear_free) { + drmmode_crtc_scanout_destroy(drmmode, + &drmmode_crtc->scanout[1]); + } } - free(output_ids); - return ret; } @@ -909,9 +1030,9 @@ static void drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); -#if XF86_CRTC_VERSION >= 4 && XF86_CRTC_VERSION < 7 +#if XF86_CRTC_VERSION < 7 if (crtc->driverIsPerformingTransform) { x += crtc->x; y += crtc->y; @@ -919,10 +1040,10 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) } #endif - drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); + drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); } -#if XF86_CRTC_VERSION >= 4 && XF86_CRTC_VERSION < 7 +#if XF86_CRTC_VERSION < 7 static int drmmode_cursor_src_offset(Rotation rotation, int width, int height, @@ -957,6 +1078,31 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height, #endif +static uint32_t +drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb) +{ + uint32_t alpha = argb >> 24; + uint32_t rgb[3]; + int i; + + if (!alpha) + return 0; + + if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) + return argb; + + /* Un-premultiply alpha */ + for (i = 0; i < 3; i++) + rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha; + + /* Apply gamma correction and pre-multiply alpha */ + rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff; + rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff; + rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff; + + return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; +} + static void drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { @@ -968,7 +1114,7 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) /* cursor should be mapped already */ ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); -#if XF86_CRTC_VERSION >= 4 && XF86_CRTC_VERSION < 7 +#if XF86_CRTC_VERSION < 7 if (crtc->driverIsPerformingTransform) { uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h; int dstx, dsty; @@ -982,7 +1128,8 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) dstx, dsty); ptr[dsty * info->cursor_w + dstx] = - cpu_to_le32(image[srcoffset]); + cpu_to_le32(drmmode_cursor_gamma(crtc, + image[srcoffset])); } } } else @@ -992,7 +1139,7 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) int i; for (i = 0; i < cursor_size; i++) - ptr[i] = cpu_to_le32(image[i]); + ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i])); } } @@ -1015,9 +1162,9 @@ drmmode_hide_cursor (xf86CrtcPtr crtc) ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, + drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, info->cursor_w, info->cursor_h); } @@ -1028,7 +1175,7 @@ drmmode_show_cursor (xf86CrtcPtr crtc) ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); uint32_t handle = drmmode_crtc->cursor_bo->handle; static Bool use_set_cursor2 = TRUE; @@ -1068,7 +1215,7 @@ drmmode_show_cursor (xf86CrtcPtr crtc) } ret = - drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + drmModeSetCursor2(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle, info->cursor_w, info->cursor_h, xhot, yhot); if (ret == -EINVAL) @@ -1077,18 +1224,24 @@ drmmode_show_cursor (xf86CrtcPtr crtc) return; } - drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, + drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle, info->cursor_w, info->cursor_h); } +/* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and + * passes that back to drmmode_crtc_scanout_create; it doesn't use it for + * anything else. + */ static void * drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - int pitch; - return drmmode_crtc_scanout_allocate(crtc, &drmmode_crtc->rotate, - width, height, &pitch); + if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width, + height)) + return NULL; + + return (void*)~0UL; } static PixmapPtr @@ -1096,11 +1249,12 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - /* 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); + if (!data) { + drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width, + height); + } + + return drmmode_crtc->rotate.pixmap; } static void @@ -1116,32 +1270,44 @@ static void drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size) { - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; + ScrnInfoPtr scrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + RADEONInfoPtr info = RADEONPTR(scrn); + int i; + + drmmode_crtc_gamma_do_set(crtc, red, green, blue, size); + + /* Compute index of this CRTC into xf86_config->crtc */ + for (i = 0; xf86_config->crtc[i] != crtc; i++) {} + + if (info->hwcursor_disabled & (1 << i)) + return; - drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - size, red, green, blue); +#ifdef HAVE_XF86_CURSOR_RESET_CURSOR + xf86CursorResetCursor(scrn->pScreen); +#else + xf86_reload_cursors(scrn->pScreen); +#endif } -#ifdef RADEON_PIXMAP_SHARING static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; unsigned scanout_id = drmmode_crtc->scanout_id; - RADEONInfoPtr info = RADEONPTR(crtc->scrn); ScreenPtr screen = crtc->scrn->pScreen; PixmapDirtyUpdatePtr dirty; xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { - if (dirty->slave_dst != drmmode_crtc->scanout[scanout_id].pixmap) - continue; - - PixmapStopDirtyTracking(dirty->src, dirty->slave_dst); - drmmode_crtc_scanout_free(drmmode_crtc); - break; + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { + PixmapStopDirtyTracking(dirty->src, dirty->slave_dst); + break; + } } + drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc->prime_scanout_pixmap = NULL; + if (!ppix) return TRUE; @@ -1150,7 +1316,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) ppix->drawable.height)) return FALSE; - if (info->tear_free && + if (drmmode_crtc->tear_free && !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], ppix->drawable.width, ppix->drawable.height)) { @@ -1158,7 +1324,13 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) return FALSE; } -#ifdef HAS_DIRTYTRACKING_ROTATION + drmmode_crtc->prime_scanout_pixmap = ppix; + +#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC + PixmapStartDirtyTracking(&ppix->drawable, + drmmode_crtc->scanout[scanout_id].pixmap, + 0, 0, 0, 0, RR_Rotate_0); +#elif defined(HAS_DIRTYTRACKING_ROTATION) PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 0, 0, 0, 0, RR_Rotate_0); #elif defined(HAS_DIRTYTRACKING2) @@ -1169,7 +1341,6 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) #endif return TRUE; } -#endif static xf86CrtcFuncsRec drmmode_crtc_funcs = { .dpms = drmmode_crtc_dpms, @@ -1188,9 +1359,7 @@ static xf86CrtcFuncsRec drmmode_crtc_funcs = { .shadow_allocate = drmmode_crtc_shadow_allocate, .shadow_destroy = drmmode_crtc_shadow_destroy, .destroy = NULL, /* XXX */ -#ifdef RADEON_PIXMAP_SHARING .set_scanout_pixmap = drmmode_set_scanout_pixmap, -#endif }; int drmmode_get_crtc_id(xf86CrtcPtr crtc) @@ -1202,8 +1371,7 @@ int drmmode_get_crtc_id(xf86CrtcPtr crtc) void drmmode_crtc_hw_id(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); struct drm_radeon_info ginfo; int r; uint32_t tmp; @@ -1212,7 +1380,7 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc) ginfo.request = 0x4; tmp = drmmode_crtc->mode_crtc->crtc_id; ginfo.value = (uintptr_t)&tmp; - r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); + r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); if (r) { drmmode_crtc->hw_id = -1; return; @@ -1232,10 +1400,9 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res return 0; drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); - drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]); + drmmode_crtc->mode_crtc = drmModeGetCrtc(pRADEONEnt->fd, mode_res->crtcs[num]); drmmode_crtc->drmmode = drmmode; drmmode_crtc->dpms_mode = DPMSModeOff; - drmmode_crtc->pending_dpms_mode = DPMSModeOff; crtc->driver_private = drmmode_crtc; drmmode_crtc_hw_id(crtc); @@ -1252,11 +1419,11 @@ drmmode_output_detect(xf86OutputPtr output) { /* go to the hw and retrieve a new output struct */ drmmode_output_private_ptr drmmode_output = output->driver_private; - drmmode_ptr drmmode = drmmode_output->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); xf86OutputStatus status; drmModeFreeConnector(drmmode_output->mode_output); - drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id); + drmmode_output->mode_output = drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id); if (!drmmode_output->mode_output) return XF86OutputStatusDisconnected; @@ -1286,7 +1453,7 @@ drmmode_output_get_modes(xf86OutputPtr output) { drmmode_output_private_ptr drmmode_output = output->driver_private; drmModeConnectorPtr koutput = drmmode_output->mode_output; - drmmode_ptr drmmode = drmmode_output->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); int i; DisplayModePtr Modes = NULL, Mode; drmModePropertyPtr props; @@ -1297,12 +1464,12 @@ drmmode_output_get_modes(xf86OutputPtr output) /* look for an EDID property */ for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); if (props && (props->flags & DRM_MODE_PROP_BLOB)) { if (!strcmp(props->name, "EDID")) { if (drmmode_output->edid_blob) drmModeFreePropertyBlob(drmmode_output->edid_blob); - drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); + drmmode_output->edid_blob = drmModeGetPropertyBlob(pRADEONEnt->fd, koutput->prop_values[i]); } } if (props) @@ -1356,22 +1523,15 @@ 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; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); if (!koutput) return; - if (mode != DPMSModeOn && crtc) { - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - + if (mode != DPMSModeOn && crtc) drmmode_do_crtc_dpms(crtc, mode); - /* Wait for any pending flip to finish */ - if (drmmode_crtc->flip_pending) - return; - } - - drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, + drmModeConnectorSetProperty(pRADEONEnt->fd, koutput->connector_id, drmmode_output->dpms_enum_id, mode); if (mode == DPMSModeOn && crtc) { @@ -1405,19 +1565,20 @@ drmmode_property_ignore(drmModePropertyPtr prop) static void drmmode_output_create_resources(xf86OutputPtr output) { + RADEONInfoPtr info = RADEONPTR(output->scrn); drmmode_output_private_ptr drmmode_output = output->driver_private; drmModeConnectorPtr mode_output = drmmode_output->mode_output; - drmmode_ptr drmmode = drmmode_output->drmmode; - drmModePropertyPtr drmmode_prop; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); + drmModePropertyPtr drmmode_prop, tearfree_prop; int i, j, err; - drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec)); + drmmode_output->props = calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec)); if (!drmmode_output->props) return; drmmode_output->num_props = 0; for (i = 0, j = 0; i < mode_output->count_props; i++) { - drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]); + drmmode_prop = drmModeGetProperty(pRADEONEnt->fd, mode_output->props[i]); if (drmmode_property_ignore(drmmode_prop)) { drmModeFreeProperty(drmmode_prop); continue; @@ -1428,6 +1589,23 @@ drmmode_output_create_resources(xf86OutputPtr output) j++; } + /* Userspace-only property for TearFree */ + tearfree_prop = calloc(1, sizeof(*tearfree_prop)); + tearfree_prop->flags = DRM_MODE_PROP_ENUM; + strncpy(tearfree_prop->name, "TearFree", 8); + tearfree_prop->count_enums = 3; + tearfree_prop->enums = calloc(tearfree_prop->count_enums, + sizeof(*tearfree_prop->enums)); + strncpy(tearfree_prop->enums[0].name, "off", 3); + strncpy(tearfree_prop->enums[1].name, "on", 2); + tearfree_prop->enums[1].value = 1; + strncpy(tearfree_prop->enums[2].name, "auto", 4); + tearfree_prop->enums[2].value = 2; + drmmode_output->props[j].mode_prop = tearfree_prop; + drmmode_output->props[j].value = info->tear_free; + drmmode_output->tear_free = info->tear_free; + drmmode_output->num_props++; + for (i = 0; i < drmmode_output->num_props; i++) { drmmode_prop_ptr p = &drmmode_output->props[i]; drmmode_prop = p->mode_prop; @@ -1494,7 +1672,7 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value) { drmmode_output_private_ptr drmmode_output = output->driver_private; - drmmode_ptr drmmode = drmmode_output->drmmode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); int i; for (i = 0; i < drmmode_output->num_props; i++) { @@ -1511,7 +1689,7 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property, return FALSE; val = *(uint32_t *)value->data; - drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, + drmModeConnectorSetProperty(pRADEONEnt->fd, drmmode_output->output_id, p->mode_prop->prop_id, (uint64_t)val); return TRUE; } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { @@ -1522,13 +1700,30 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property, if (value->type != XA_ATOM || value->format != 32 || value->size != 1) return FALSE; memcpy(&atom, value->data, 4); - name = NameForAtom(atom); + if (!(name = NameForAtom(atom))) + return FALSE; /* search for matching name string, then set its value down */ for (j = 0; j < p->mode_prop->count_enums; j++) { if (!strcmp(p->mode_prop->enums[j].name, name)) { - drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, - p->mode_prop->prop_id, p->mode_prop->enums[j].value); + if (i == (drmmode_output->num_props - 1)) { + if (drmmode_output->tear_free != j) { + xf86CrtcPtr crtc = output->crtc; + + drmmode_output->tear_free = j; + if (crtc) { + drmmode_set_mode_major(crtc, &crtc->mode, + crtc->rotation, + crtc->x, crtc->y); + } + } + } else { + drmModeConnectorSetProperty(pRADEONEnt->fd, + drmmode_output->output_id, + p->mode_prop->prop_id, + p->mode_prop->enums[j].value); + } + return TRUE; } } @@ -1651,16 +1846,14 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name, if (output) { snprintf(name, 32, "%s-%s", output->name, extra_path); } else { - if (koutput->connector_type >= NUM_OUTPUT_NAMES) + 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) + } 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 { + } else { /* need to do smart conversion here for compat with non-kms ATI driver */ if (koutput->connector_type_id == 1) { switch(koutput->connector_type) { @@ -1696,6 +1889,7 @@ 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); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); xf86OutputPtr output; drmModeConnectorPtr koutput; @@ -1707,15 +1901,15 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r int i; const char *s; - koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]); + koutput = drmModeGetConnector(pRADEONEnt->fd, mode_res->connectors[num]); if (!koutput) return 0; for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + props = drmModeGetProperty(pRADEONEnt->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]); + path_blob = drmModeGetPropertyBlob(pRADEONEnt->fd, koutput->prop_values[i]); drmModeFreeProperty(props); break; } @@ -1729,7 +1923,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r } for (i = 0; i < koutput->count_encoders; i++) { - kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]); + kencoders[i] = drmModeGetEncoder(pRADEONEnt->fd, koutput->encoders[i]); if (!kencoders[i]) { goto out_free_encoders; } @@ -1802,7 +1996,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r output->possible_clones = 0; for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); if (props && (props->flags & DRM_MODE_PROP_ENUM)) { if (!strcmp(props->name, "DPMS")) { drmmode_output->dpms_enum_id = koutput->props[i]; @@ -1981,13 +2175,9 @@ static Bool drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) { 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; RADEONInfoPtr info = RADEONPTR(scrn); struct radeon_bo *old_front = NULL; 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; @@ -1998,9 +2188,6 @@ 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; @@ -2087,8 +2274,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) old_width = scrn->virtualX; old_height = scrn->virtualY; old_pitch = scrn->displayWidth; - old_fb_id = drmmode->fb_id; - drmmode->fb_id = 0; old_front = info->front_bo; scrn->virtualX = width; @@ -2145,18 +2330,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) goto fail; } - /* 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_pixmap_clear(ppix); radeon_cs_flush_indirect(scrn); radeon_bo_wait(info->front_bo); @@ -2170,8 +2344,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) crtc->rotation, crtc->x, crtc->y); } - if (old_fb_id) - drmModeRmFB(drmmode->fd, old_fb_id); if (old_front) radeon_bo_unref(old_front); @@ -2185,7 +2357,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) scrn->virtualX = old_width; scrn->virtualY = old_height; scrn->displayWidth = old_pitch; - drmmode->fb_id = old_fb_id; return FALSE; } @@ -2194,56 +2365,30 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { drmmode_xf86crtc_resize }; -void -drmmode_clear_pending_flip(xf86CrtcPtr crtc) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - - drmmode_crtc->flip_pending = FALSE; - - if (!crtc->enabled || - (drmmode_crtc->pending_dpms_mode != DPMSModeOn && - drmmode_crtc->dpms_mode != drmmode_crtc->pending_dpms_mode)) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - int o; - - for (o = 0; o < xf86_config->num_output; o++) { - xf86OutputPtr output = xf86_config->output[o]; - - if (output->crtc != crtc) - continue; - - drmmode_output_dpms(output, drmmode_crtc->pending_dpms_mode); - } - - drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode); - } - - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout_destroy[0]); - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout_destroy[1]); -} - static void drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_flipdata_ptr flipdata = event_data; if (--flipdata->flip_count == 0) { if (!flipdata->fe_crtc) flipdata->fe_crtc = crtc; flipdata->abort(flipdata->fe_crtc, flipdata->event_data); + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } - drmmode_clear_pending_flip(crtc); + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + NULL); } static void drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data) { - RADEONInfoPtr info = RADEONPTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_flipdata_ptr flipdata = event_data; /* Is this the event whose info shall be delivered to higher level? */ @@ -2253,6 +2398,14 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even flipdata->fe_usec = usec; } + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, + flipdata->fb); + if (drmmode_crtc->tear_free || + drmmode_crtc->flip_pending == flipdata->fb) { + drmmode_fb_reference(pRADEONEnt->fd, + &drmmode_crtc->flip_pending, NULL); + } + if (--flipdata->flip_count == 0) { /* Deliver MSC & UST from reference/current CRTC to flip event * handler @@ -2263,13 +2416,9 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even else flipdata->handler(crtc, frame, usec, flipdata->event_data); - /* Release framebuffer */ - drmModeRmFB(info->drmmode.fd, flipdata->old_fb_id); - + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } - - drmmode_clear_pending_flip(crtc); } @@ -2281,23 +2430,26 @@ static void drm_wakeup_handler(pointer data, int err, pointer p) #endif { - drmmode_ptr drmmode = data; + ScrnInfoPtr scrn = data; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + RADEONInfoPtr info = RADEONPTR(scrn); + #if !HAVE_NOTIFY_FD fd_set *read_mask = p; - if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) + if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask)) #endif { - drmHandleEvent(drmmode->fd, &drmmode->event_context); + drmHandleEvent(pRADEONEnt->fd, &info->drmmode.event_context); } } -static Bool drmmode_probe_page_flip_target(drmmode_ptr drmmode) +static Bool drmmode_probe_page_flip_target(RADEONEntPtr pRADEONEnt) { #ifdef DRM_CAP_PAGE_FLIP_TARGET uint64_t cap_value; - return drmGetCap(drmmode->fd, DRM_CAP_PAGE_FLIP_TARGET, + return drmGetCap(pRADEONEnt->fd, DRM_CAP_PAGE_FLIP_TARGET, &cap_value) == 0 && cap_value != 0; #else return FALSE; @@ -2305,13 +2457,12 @@ static Bool drmmode_probe_page_flip_target(drmmode_ptr drmmode) } static int -drmmode_page_flip(drmmode_crtc_private_ptr drmmode_crtc, int fb_id, +drmmode_page_flip(RADEONEntPtr pRADEONEnt, + drmmode_crtc_private_ptr drmmode_crtc, int fb_id, uint32_t flags, uintptr_t drm_queue_seq) { - drmmode_ptr drmmode = drmmode_crtc->drmmode; - flags |= DRM_MODE_PAGE_FLIP_EVENT; - return drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + return drmModePageFlip(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, fb_id, flags, (void*)drm_queue_seq); } @@ -2323,17 +2474,16 @@ drmmode_page_flip_target_absolute(RADEONEntPtr pRADEONEnt, { #ifdef DRM_MODE_PAGE_FLIP_TARGET if (pRADEONEnt->has_page_flip_target) { - drmmode_ptr drmmode = drmmode_crtc->drmmode; - flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE; - return drmModePageFlipTarget(drmmode->fd, + return drmModePageFlipTarget(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, fb_id, flags, (void*)drm_queue_seq, target_msc); } #endif - return drmmode_page_flip(drmmode_crtc, fb_id, flags, drm_queue_seq); + return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags, + drm_queue_seq); } int @@ -2344,17 +2494,16 @@ drmmode_page_flip_target_relative(RADEONEntPtr pRADEONEnt, { #ifdef DRM_MODE_PAGE_FLIP_TARGET if (pRADEONEnt->has_page_flip_target) { - drmmode_ptr drmmode = drmmode_crtc->drmmode; - flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_RELATIVE; - return drmModePageFlipTarget(drmmode->fd, + return drmModePageFlipTarget(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, fb_id, flags, (void*)drm_queue_seq, target_msc); } #endif - return drmmode_page_flip(drmmode_crtc, fb_id, flags, drm_queue_seq); + return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags, + drm_queue_seq); } Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) @@ -2364,15 +2513,12 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) int i, num_dvi = 0, num_hdmi = 0; drmModeResPtr mode_res; unsigned int crtcs_needed = 0; -#ifdef RADEON_PIXMAP_SHARING char *bus_id_string, *provider_name; -#endif xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); drmmode->scrn = pScrn; - drmmode->cpp = cpp; - mode_res = drmModeGetResources(drmmode->fd); + mode_res = drmModeGetResources(pRADEONEnt->fd); if (!mode_res) return FALSE; @@ -2408,21 +2554,19 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) /* workout clones */ drmmode_clones_init(pScrn, drmmode, mode_res); -#ifdef RADEON_PIXMAP_SHARING bus_id_string = DRICreatePCIBusID(info->PciInfo); XNFasprintf(&provider_name, "%s @ %s", pScrn->chipset, bus_id_string); free(bus_id_string); xf86ProviderSetup(pScrn, NULL, provider_name); free(provider_name); -#endif xf86InitialConfiguration(pScrn, TRUE); - drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; + drmmode->event_context.version = 2; drmmode->event_context.vblank_handler = radeon_drm_queue_handler; drmmode->event_context.page_flip_handler = radeon_drm_queue_handler; - pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(drmmode); + pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt); drmModeFreeResources(mode_res); return TRUE; @@ -2439,11 +2583,11 @@ void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) info->drmmode_inited = TRUE; if (pRADEONEnt->fd_wakeup_registered != serverGeneration) { #if HAVE_NOTIFY_FD - SetNotifyFd(drmmode->fd, drm_notify_fd, X_NOTIFY_READ, drmmode); + SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, pScrn); #else - AddGeneralSocket(drmmode->fd); + AddGeneralSocket(pRADEONEnt->fd); RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - drm_wakeup_handler, drmmode); + drm_wakeup_handler, pScrn); #endif pRADEONEnt->fd_wakeup_registered = serverGeneration; pRADEONEnt->fd_wakeup_ref = 1; @@ -2464,21 +2608,16 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) if (pRADEONEnt->fd_wakeup_registered == serverGeneration && !--pRADEONEnt->fd_wakeup_ref) { #if HAVE_NOTIFY_FD - RemoveNotifyFd(drmmode->fd); + RemoveNotifyFd(pRADEONEnt->fd); #else - RemoveGeneralSocket(drmmode->fd); + RemoveGeneralSocket(pRADEONEnt->fd); RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - drm_wakeup_handler, drmmode); + drm_wakeup_handler, pScrn); #endif } - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - - drmmode_crtc_scanout_destroy(&info->drmmode, &drmmode_crtc->scanout[0]); - drmmode_crtc_scanout_destroy(&info->drmmode, &drmmode_crtc->scanout[1]); - } + for (c = 0; c < config->num_crtc; c++) + drmmode_crtc_scanout_free(config->crtc[c]->driver_private); } @@ -2515,6 +2654,7 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); int c; for (c = 0; c < config->num_crtc; c++) { @@ -2527,9 +2667,11 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, if (!crtc->enabled) { if (set_hw) { drmmode_do_crtc_dpms(crtc, DPMSModeOff); - drmModeSetCrtc(drmmode->fd, + drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, NULL, 0, NULL); + drmmode_fb_reference(pRADEONEnt->fd, + &drmmode_crtc->fb, NULL); } continue; } @@ -2643,7 +2785,50 @@ radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode) Bool changed = FALSE; int num_dvi = 0, num_hdmi = 0; - mode_res = drmModeGetResources(drmmode->fd); + /* Try to re-set the mode on all the connectors with a BAD link-state: + * This may happen if a link degrades and a new modeset is necessary, using + * different link-training parameters. If the kernel found that the current + * mode is not achievable anymore, it should have pruned the mode before + * sending the hotplug event. Try to re-set the currently-set mode to keep + * the display alive, this will fail if the mode has been pruned. + * In any case, we will send randr events for the Desktop Environment to + * deal with it, if it wants to. + */ + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + drmmode_output_private_ptr drmmode_output = output->driver_private; + uint32_t con_id = drmmode_output->mode_output->connector_id; + drmModeConnectorPtr koutput; + + /* Get an updated view of the properties for the current connector and + * look for the link-status property + */ + koutput = drmModeGetConnectorCurrent(pRADEONEnt->fd, con_id); + for (j = 0; koutput && j < koutput->count_props; j++) { + drmModePropertyPtr props; + props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[j]); + if (props && props->flags & DRM_MODE_PROP_ENUM && + !strcmp(props->name, "link-status") && + koutput->prop_values[j] == DRM_MODE_LINK_STATUS_BAD) { + xf86CrtcPtr crtc = output->crtc; + if (!crtc) + continue; + + /* the connector got a link failure, re-set the current mode */ + drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, + crtc->x, crtc->y); + + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "hotplug event: connector %u's link-state is BAD, " + "tried resetting the current mode. You may be left " + "with a black screen if this fails...\n", con_id); + } + drmModeFreeProperty(props); + } + drmModeFreeConnector(koutput); + } + + mode_res = drmModeGetResources(pRADEONEnt->fd); if (!mode_res) goto out; @@ -2779,38 +2964,21 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) } 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, + PixmapPtr new_front, uint64_t id, void *data, + xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler, radeon_drm_abort_proc abort, enum drmmode_flip_sync flip_sync, uint32_t target_msc) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); - RADEONInfoPtr info = RADEONPTR(scrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcPtr crtc = NULL; drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - unsigned int pitch; int i; - uint32_t tiling_flags = 0; uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; drmmode_flipdata_ptr flipdata; uintptr_t drm_queue_seq = 0; - if (info->allowColorTiling) { - if (info->ChipFamily >= CHIP_FAMILY_R600) - tiling_flags |= RADEON_TILING_MICRO; - else - tiling_flags |= RADEON_TILING_MACRO; - } - - pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->pixel_bytes, tiling_flags)) * - info->pixel_bytes; - if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { - pitch = info->front_surface.level[0].pitch_bytes; - } - flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); if (!flipdata) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -2818,14 +2986,12 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, 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)) + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, + radeon_pixmap_get_fb(new_front)); + if (!flipdata->fb) { + ErrorF("Failed to get FB for flip\n"); goto error; + } /* * Queue flips on all enabled CRTCs @@ -2840,21 +3006,19 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, flipdata->event_data = data; flipdata->handler = handler; flipdata->abort = abort; + flipdata->fe_crtc = ref_crtc; for (i = 0; i < config->num_crtc; i++) { + struct drmmode_fb *fb = flipdata->fb; + crtc = config->crtc[i]; + drmmode_crtc = crtc->driver_private; - if (!crtc->enabled) + if (!drmmode_crtc_can_flip(crtc) || + (drmmode_crtc->tear_free && crtc != ref_crtc)) continue; flipdata->flip_count++; - drmmode_crtc = crtc->driver_private; - - /* Only the reference crtc will finally deliver its page flip - * completion event. All other crtc's events will be discarded. - */ - if (drmmode_crtc->hw_id == ref_crtc_hw_id) - flipdata->fe_crtc = crtc; drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, flipdata, @@ -2866,10 +3030,39 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto error; } - if (drmmode_crtc->hw_id == ref_crtc_hw_id) { + if (drmmode_crtc->tear_free) { + BoxRec extents = { .x1 = 0, .y1 = 0, + .x2 = new_front->drawable.width, + .y2 = new_front->drawable.height }; + int scanout_id = drmmode_crtc->scanout_id ^ 1; + + if (flip_sync == FLIP_ASYNC) { + if (!drmmode_wait_vblank(crtc, + DRM_VBLANK_RELATIVE | + DRM_VBLANK_EVENT, + 0, drm_queue_seq, + NULL, NULL)) + goto flip_error; + goto next; + } + + fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + ErrorF("Failed to get FB for TearFree flip\n"); + goto error; + } + + radeon_scanout_do_update(crtc, scanout_id, new_front, + &extents); + + drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, + drmmode_crtc->scanout_update_pending); + } + + if (crtc == ref_crtc) { if (drmmode_page_flip_target_absolute(pRADEONEnt, drmmode_crtc, - drmmode->fb_id, + fb->handle, flip_flags, drm_queue_seq, target_msc) != 0) @@ -2877,13 +3070,20 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } else { if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode->fb_id, + fb->handle, flip_flags, drm_queue_seq, 0) != 0) goto flip_error; } - drmmode_crtc->flip_pending = TRUE; + if (drmmode_crtc->tear_free) { + drmmode_crtc->scanout_id ^= 1; + drmmode_crtc->ignore_damage = TRUE; + } + + next: + drmmode_fb_reference(pRADEONEnt->fd, + &drmmode_crtc->flip_pending, fb); drm_queue_seq = 0; } @@ -2895,18 +3095,13 @@ flip_error: strerror(errno)); error: - if (flipdata && flipdata->flip_count <= 1 && - drmmode->fb_id != flipdata->old_fb_id) { - drmModeRmFB(drmmode->fd, drmmode->fb_id); - drmmode->fb_id = flipdata->old_fb_id; - } - if (drm_queue_seq) radeon_drm_abort_entry(drm_queue_seq); else if (crtc) drmmode_flip_abort(crtc, flipdata); else { abort(NULL, data); + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 6bbf71c1..8387279f 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -40,10 +40,6 @@ #endif typedef struct { - int fd; - unsigned fb_id; - drmModeFBPtr mode_fb; - int cpp; struct radeon_bo_manager *bufmgr; ScrnInfoPtr scrn; #ifdef HAVE_LIBUDEV @@ -60,9 +56,9 @@ typedef struct { } drmmode_rec, *drmmode_ptr; typedef struct { - unsigned old_fb_id; - int flip_count; + struct drmmode_fb *fb; void *event_data; + int flip_count; unsigned int fe_frame; uint64_t fe_usec; xf86CrtcPtr fe_crtc; @@ -70,10 +66,14 @@ typedef struct { radeon_drm_abort_proc abort; } drmmode_flipdata_rec, *drmmode_flipdata_ptr; +struct drmmode_fb { + int refcnt; + uint32_t handle; +}; + struct drmmode_scanout { struct radeon_bo *bo; PixmapPtr pixmap; - unsigned fb_id; int width, height; }; @@ -84,14 +84,16 @@ typedef struct { struct radeon_bo *cursor_bo; struct drmmode_scanout rotate; struct drmmode_scanout scanout[2]; - struct drmmode_scanout scanout_destroy[2]; DamagePtr scanout_damage; + Bool ignore_damage; RegionRec scanout_last_region; unsigned scanout_id; Bool scanout_update_pending; + Bool tear_free; + + PixmapPtr prime_scanout_pixmap; + int dpms_mode; - /* For when a flip is pending when DPMS off requested */ - int pending_dpms_mode; CARD64 dpms_last_ust; uint32_t dpms_last_seq; int dpms_last_fps; @@ -101,8 +103,18 @@ typedef struct { * modeset) */ Bool need_modeset; - /* A flip is pending for this CRTC */ - Bool flip_pending; + /* A flip to this FB is pending for this CRTC */ + struct drmmode_fb *flip_pending; + /* The FB currently being scanned out by this CRTC, if any */ + struct drmmode_fb *fb; + +#ifdef HAVE_PRESENT_H + /* Deferred processing of Present vblank event */ + uint64_t present_vblank_event_id; + uint64_t present_vblank_usec; + unsigned present_vblank_msc; + Bool present_flip_expected; +#endif } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -124,6 +136,7 @@ typedef struct { drmmode_prop_ptr props; int enc_mask; int enc_clone_mask; + int tear_free; } drmmode_output_private_rec, *drmmode_output_private_ptr; @@ -133,6 +146,52 @@ enum drmmode_flip_sync { }; +/* Can the page flip ioctl be used for this CRTC? */ +static inline Bool +drmmode_crtc_can_flip(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + return crtc->enabled && + drmmode_crtc->dpms_mode == DPMSModeOn && + !drmmode_crtc->rotate.bo && + (drmmode_crtc->tear_free || + !drmmode_crtc->scanout[drmmode_crtc->scanout_id].bo); +} + + +static inline void +drmmode_fb_reference_loc(int drm_fd, struct drmmode_fb **old, struct drmmode_fb *new, + const char *caller, unsigned line) +{ + if (new) { + if (new->refcnt <= 0) { + FatalError("New FB's refcnt was %d at %s:%u", + new->refcnt, caller, line); + } + + new->refcnt++; + } + + if (*old) { + if ((*old)->refcnt <= 0) { + FatalError("Old FB's refcnt was %d at %s:%u", + (*old)->refcnt, caller, line); + } + + if (--(*old)->refcnt == 0) { + drmModeRmFB(drm_fd, (*old)->handle); + free(*old); + } + } + + *old = new; +} + +#define drmmode_fb_reference(fd, old, new) \ + drmmode_fb_reference_loc(fd, old, new, __func__, __LINE__) + + extern int drmmode_page_flip_target_absolute(RADEONEntPtr pRADEONEnt, drmmode_crtc_private_ptr drmmode_crtc, int fb_id, uint32_t flags, @@ -154,25 +213,37 @@ extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn); -extern void drmmode_scanout_free(ScrnInfoPtr scrn); +extern void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, + struct drmmode_scanout *scanout); +void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc); +PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc, + struct drmmode_scanout *scanout, + int width, int height); extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode); extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode); +Bool drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb, + DisplayModePtr mode, int x, int y); + 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); -extern void drmmode_clear_pending_flip(xf86CrtcPtr crtc); 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, + PixmapPtr new_front, uint64_t id, void *data, + xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler, radeon_drm_abort_proc abort, enum drmmode_flip_sync flip_sync, uint32_t target_msc); int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc); int drmmode_get_current_ust(int drm_fd, CARD64 *ust); +Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, + uint32_t target_seq, unsigned long signal, + uint64_t *ust, uint32_t *result_seq); + + #endif diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c index d788bfc7..90c9b6d9 100644 --- a/src/evergreen_exa.c +++ b/src/evergreen_exa.c @@ -2055,10 +2055,8 @@ EVERGREENDrawInit(ScreenPtr pScreen) info->accel_state->exa->UploadToScreen = EVERGREENUploadToScreen; info->accel_state->exa->DownloadFromScreen = EVERGREENDownloadFromScreen; info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2; -#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 6) info->accel_state->exa->SharePixmapBacking = RADEONEXASharePixmapBacking; info->accel_state->exa->SetSharedPixmapBacking = RADEONEXASetSharedPixmapBacking; -#endif info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX | EXA_HANDLES_PIXMAPS | EXA_MIXED_PIXMAPS; info->accel_state->exa->pixmapOffsetAlign = 256; diff --git a/src/r600_exa.c b/src/r600_exa.c index e9ac721d..22d4b316 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -2034,10 +2034,8 @@ R600DrawInit(ScreenPtr pScreen) info->accel_state->exa->UploadToScreen = R600UploadToScreenCS; info->accel_state->exa->DownloadFromScreen = R600DownloadFromScreenCS; info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2; -#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 6) info->accel_state->exa->SharePixmapBacking = RADEONEXASharePixmapBacking; info->accel_state->exa->SetSharedPixmapBacking = RADEONEXASetSharedPixmapBacking; -#endif info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX | EXA_HANDLES_PIXMAPS | EXA_MIXED_PIXMAPS; info->accel_state->exa->pixmapOffsetAlign = 256; diff --git a/src/radeon.h b/src/radeon.h index 039a620b..d54e4990 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -180,12 +180,37 @@ typedef enum { } RADEONOpts; -#if XF86_CRTC_VERSION >= 5 -#define RADEON_PIXMAP_SHARING 1 -#define radeon_is_gpu_screen(screen) (screen)->isGPU +static inline ScreenPtr +radeon_master_screen(ScreenPtr screen) +{ + if (screen->current_master) + return screen->current_master; + + return screen; +} + +static inline ScreenPtr +radeon_dirty_master(PixmapDirtyUpdatePtr dirty) +{ +#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC + ScreenPtr screen = dirty->src->pScreen; +#else + ScreenPtr screen = dirty->src->drawable.pScreen; +#endif + + return radeon_master_screen(screen); +} + +static inline Bool +radeon_dirty_src_equals(PixmapDirtyUpdatePtr dirty, PixmapPtr pixmap) +{ +#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC + return dirty->src == &pixmap->drawable; #else -#define radeon_is_gpu_screen(screen) 0 + return dirty->src == pixmap; #endif +} + #define RADEON_VSYNC_TIMEOUT 20000 /* Maximum wait for VSYNC (in usecs) */ @@ -202,7 +227,6 @@ typedef enum { #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) /* Other macros */ -#define RADEON_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) @@ -286,6 +310,7 @@ struct radeon_pixmap { uint_fast32_t gpu_write; struct radeon_bo *bo; + struct drmmode_fb *fb; uint32_t tiling_flags; @@ -311,6 +336,7 @@ static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pix struct radeon_exa_pixmap_priv { struct radeon_bo *bo; + struct drmmode_fb *fb; uint32_t tiling_flags; struct radeon_surface surface; Bool bo_mapped; @@ -480,7 +506,7 @@ typedef struct { int Chipset; RADEONChipFamily ChipFamily; - Bool (*CloseScreen)(CLOSE_SCREEN_ARGS_DECL); + Bool (*CloseScreen)(ScreenPtr pScreen); void (*BlockHandler)(BLOCKHANDLER_ARGS_DECL); @@ -507,7 +533,7 @@ typedef struct { Bool accelOn; Bool use_glamor; Bool shadow_primary; - Bool tear_free; + int tear_free; Bool exa_pixmaps; Bool exa_force_create; XF86ModReqInfo exaReq; @@ -523,6 +549,7 @@ typedef struct { CreateScreenResourcesProcPtr CreateScreenResources; CreateWindowProcPtr CreateWindow; + WindowExposuresProcPtr WindowExposures; Bool IsSecondary; @@ -591,10 +618,8 @@ typedef struct { AddTrapsProcPtr SavedAddTraps; UnrealizeGlyphProcPtr SavedUnrealizeGlyph; #endif -#ifdef RADEON_PIXMAP_SHARING SharePixmapBackingProcPtr SavedSharePixmapBacking; SetSharedPixmapBackingProcPtr SavedSetSharedPixmapBacking; -#endif } glamor; #endif /* USE_GLAMOR */ } RADEONInfoRec, *RADEONInfoPtr; @@ -606,6 +631,9 @@ extern void RADEONCopySwap(uint8_t *dst, uint8_t *src, unsigned int size, int s extern void RADEONInit3DEngine(ScrnInfoPtr pScrn); extern int radeon_cs_space_remaining(ScrnInfoPtr pScrn); +/* radeon_bo_helper.c */ +extern Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle); + /* radeon_commonfuncs.c */ extern void RADEONWaitForVLine(ScrnInfoPtr pScrn, PixmapPtr pPix, xf86CrtcPtr crtc, int start, int stop); @@ -630,7 +658,13 @@ extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, Bool radeon_dri3_screen_init(ScreenPtr screen); /* radeon_kms.c */ -Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id); +Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, + PixmapPtr src_pix, BoxPtr extents); +void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) + , RegionPtr pBSRegion +#endif + ); /* radeon_present.c */ Bool radeon_present_screen_init(ScreenPtr screen); @@ -654,8 +688,6 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn, void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size); extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn); -drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc); - static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix) { #ifdef USE_GLAMOR @@ -681,7 +713,9 @@ uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix); static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) { #ifdef USE_GLAMOR - RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); + ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + RADEONInfoPtr info = RADEONPTR(scrn); if (info->use_glamor) { struct radeon_pixmap *priv; @@ -698,6 +732,8 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) radeon_bo_unref(priv->bo); } + drmmode_fb_reference(pRADEONEnt->fd, &priv->fb, NULL); + if (!bo) { free(priv); priv = NULL; @@ -733,6 +769,8 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) if (driver_priv->bo) radeon_bo_unref(driver_priv->bo); + drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL); + radeon_bo_ref(bo); driver_priv->bo = bo; @@ -782,6 +820,79 @@ static inline Bool radeon_get_pixmap_shared(PixmapPtr pPix) return FALSE; } +static inline struct drmmode_fb* +radeon_fb_create(int drm_fd, uint32_t width, uint32_t height, uint8_t depth, + uint8_t bpp, uint32_t pitch, uint32_t handle) +{ + struct drmmode_fb *fb = malloc(sizeof(*fb)); + + if (!fb) + return NULL; + + fb->refcnt = 1; + if (drmModeAddFB(drm_fd, width, height, depth, bpp, pitch, handle, + &fb->handle) == 0) + return fb; + + free(fb); + return NULL; +} + +static inline struct drmmode_fb** +radeon_pixmap_get_fb_ptr(PixmapPtr pix) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + +#ifdef USE_GLAMOR + if (info->use_glamor) { + struct radeon_pixmap *priv = radeon_get_pixmap_private(pix); + + if (!priv) + return NULL; + + return &priv->fb; + } else +#endif + if (info->accelOn) + { + struct radeon_exa_pixmap_priv *driver_priv = + exaGetPixmapDriverPrivate(pix); + + if (!driver_priv) + return NULL; + + return &driver_priv->fb; + } + + return NULL; +} + +static inline struct drmmode_fb* +radeon_pixmap_get_fb(PixmapPtr pix) +{ + struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pix); + + if (!fb_ptr) + return NULL; + + if (!*fb_ptr) { + uint32_t handle; + + if (radeon_get_pixmap_handle(pix, &handle)) { + ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + + *fb_ptr = radeon_fb_create(pRADEONEnt->fd, pix->drawable.width, + pix->drawable.height, pix->drawable.depth, + pix->drawable.bitsPerPixel, pix->devKind, + handle); + } + } + + return *fb_ptr; +} + #define CP_PACKET0(reg, n) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET1(reg0, reg1) \ diff --git a/src/radeon_accel.c b/src/radeon_accel.c index 1def2a3f..fc80ed74 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -94,11 +94,11 @@ static int RADEONDRMGetNumPipes(ScrnInfoPtr pScrn, int *num_pipes) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); struct drm_radeon_info np2; np2.value = (unsigned long)num_pipes; np2.request = RADEON_INFO_NUM_GB_PIPES; - return drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &np2, sizeof(np2)); + return drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &np2, sizeof(np2)); } /* Initialize the acceleration hardware */ diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c index 933dc7b3..0366f613 100644 --- a/src/radeon_bo_helper.c +++ b/src/radeon_bo_helper.c @@ -26,10 +26,7 @@ #include "radeon.h" #include "radeon_glamor.h" - -#ifdef RADEON_PIXMAP_SHARING #include "radeon_bo_gem.h" -#endif static const unsigned MicroBlockTable[5][3][2] = { /*linear tiled square-tiled */ @@ -89,11 +86,8 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && - info->shadow_primary) -#ifdef CREATE_PIXMAP_USAGE_SHARED - || (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED -#endif - ) { + info->shadow_primary) || + (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) { tiling = 0; domain = RADEON_GEM_DOMAIN_GTT; } @@ -195,13 +189,36 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, return bo; } +/* Clear the pixmap contents to black */ +void +radeon_pixmap_clear(PixmapPtr pixmap) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen)); + GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); + Bool force = info->accel_state->force; + xRectangle rect; + + info->accel_state->force = TRUE; + ValidateGC(&pixmap->drawable, gc); + rect.x = 0; + rect.y = 0; + rect.width = pixmap->drawable.width; + rect.height = pixmap->drawable.height; + gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect); + FreeScratchGC(gc); + info->accel_state->force = force; +} + /* 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)); + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + RADEONInfoPtr info = RADEONPTR(scrn); #endif if (bo) { @@ -230,7 +247,7 @@ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) if (fd < 0) return FALSE; - r = drmPrimeFDToHandle(info->dri2.drm_fd, fd, &priv->handle); + r = drmPrimeFDToHandle(pRADEONEnt->fd, fd, &priv->handle); close(fd); if (r == 0) { struct drm_radeon_gem_set_tiling args = { .handle = priv->handle }; @@ -238,7 +255,7 @@ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) priv->handle_valid = TRUE; *handle = priv->handle; - if (drmCommandWriteRead(info->dri2.drm_fd, + if (drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_GEM_GET_TILING, &args, sizeof(args)) == 0) priv->tiling_flags = args.tiling_flags; @@ -276,7 +293,6 @@ uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix) } } -#ifdef RADEON_PIXMAP_SHARING Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p) { @@ -383,5 +399,3 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, radeon_bo_unref(bo); return ret; } - -#endif /* RADEON_PIXMAP_SHARING */ diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h index f1aed551..e1856adb 100644 --- a/src/radeon_bo_helper.h +++ b/src/radeon_bo_helper.h @@ -28,8 +28,8 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch, struct radeon_surface *new_surface, uint32_t *new_tiling); -extern Bool -radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle); +extern void +radeon_pixmap_clear(PixmapPtr pixmap); extern uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix); diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index d0dcf890..b569bb4f 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -42,15 +42,12 @@ #include "radeon_bo_helper.h" #include "radeon_version.h" -#include "radeon_list.h" #include "radeon_bo_gem.h" +#include <list.h> #include <xf86Priv.h> - -#if DRI2INFOREC_VERSION >= 9 -#define USE_DRI2_PRIME -#endif +#include <X11/extensions/dpmsconst.h> #define FALLBACK_SWAP_DELAY 16 @@ -80,7 +77,7 @@ static DevPrivateKeyRec dri2_window_private_key_rec; /* Get GEM flink name for a pixmap */ static Bool -radeon_get_flink_name(RADEONInfoPtr info, PixmapPtr pixmap, uint32_t *name) +radeon_get_flink_name(RADEONEntPtr pRADEONEnt, PixmapPtr pixmap, uint32_t *name) { struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap); struct drm_gem_flink flink; @@ -89,7 +86,7 @@ radeon_get_flink_name(RADEONInfoPtr info, PixmapPtr pixmap, uint32_t *name) 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) + if (drmIoctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) return FALSE; *name = flink.name; @@ -106,6 +103,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, unsigned int format) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); BufferPtr buffers; struct dri2_buffer_priv *privates; @@ -252,7 +250,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, pixmap->refcnt++; } - if (!radeon_get_flink_name(info, pixmap, &buffers->name)) + if (!radeon_get_flink_name(pRADEONEnt, pixmap, &buffers->name)) goto error; } @@ -281,14 +279,6 @@ error: return NULL; } -DRI2BufferPtr -radeon_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, - unsigned int format) -{ - return radeon_dri2_create_buffer2(pDraw->pScreen, pDraw, - attachment, format); -} - static void radeon_dri2_destroy_buffer2(ScreenPtr pScreen, DrawablePtr drawable, BufferPtr buffers) @@ -319,12 +309,6 @@ radeon_dri2_destroy_buffer2(ScreenPtr pScreen, } } -void -radeon_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) -{ - radeon_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf); -} - static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable) { @@ -360,17 +344,14 @@ radeon_dri2_copy_region2(ScreenPtr pScreen, dst_drawable = &dst_private->pixmap->drawable; if (src_private->attachment == DRI2BufferFrontLeft) { -#ifdef USE_DRI2_PRIME if (drawable->pScreen != pScreen) { src_drawable = DRI2UpdatePrime(drawable, src_buffer); if (!src_drawable) return; } else -#endif src_drawable = drawable; } if (dst_private->attachment == DRI2BufferFrontLeft) { -#ifdef USE_DRI2_PRIME if (drawable->pScreen != pScreen) { dst_drawable = DRI2UpdatePrime(drawable, dest_buffer); if (!dst_drawable) @@ -379,7 +360,6 @@ radeon_dri2_copy_region2(ScreenPtr pScreen, if (dst_drawable != drawable) translate = TRUE; } else -#endif dst_drawable = drawable; } @@ -433,14 +413,6 @@ radeon_dri2_copy_region2(ScreenPtr pScreen, FreeScratchGC(gc); } -void -radeon_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, - DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) -{ - return radeon_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion, - pDstBuffer, pSrcBuffer); -} - enum DRI2FrameEventType { DRI2_SWAP, DRI2_FLIP, @@ -477,7 +449,9 @@ radeon_dri2_unref_buffer(BufferPtr buffer) { if (buffer) { struct dri2_buffer_priv *private = buffer->driverPrivate; - radeon_dri2_destroy_buffer(&(private->pixmap->drawable), buffer); + DrawablePtr draw = &private->pixmap->drawable; + + radeon_dri2_destroy_buffer2(draw->pScreen, draw, buffer); } } @@ -522,13 +496,13 @@ static Bool radeon_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) { /* CRTC is not running, extrapolate MSC and timestamp */ ScrnInfoPtr scrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(scrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(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) { + if (drmmode_get_current_ust(pRADEONEnt->fd, &now) != 0) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); return FALSE; @@ -651,9 +625,7 @@ radeon_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client, ScrnInfoPtr scrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(scrn); struct dri2_buffer_priv *back_priv; - struct radeon_bo *bo; DRI2FrameEventPtr flip_info; - int ref_crtc_hw_id = drmmode_get_crtc_id(crtc); flip_info = calloc(1, sizeof(DRI2FrameEventRec)); if (!flip_info) @@ -672,11 +644,8 @@ radeon_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client, /* Page flip the full screen buffer */ back_priv = back->driverPrivate; - bo = radeon_get_pixmap_bo(back_priv->pixmap); - - if (radeon_do_pageflip(scrn, client, bo->handle, - RADEON_DRM_QUEUE_ID_DEFAULT, flip_info, - ref_crtc_hw_id, + if (radeon_do_pageflip(scrn, client, back_priv->pixmap, + RADEON_DRM_QUEUE_ID_DEFAULT, flip_info, crtc, radeon_dri2_flip_event_handler, radeon_dri2_flip_event_abort, FLIP_VSYNC, target_msc - radeon_get_msc_delta(draw, crtc))) { @@ -691,7 +660,9 @@ static Bool update_front(DrawablePtr draw, DRI2BufferPtr front) { PixmapPtr pixmap; - RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(draw->pScreen)); + ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + RADEONInfoPtr info = RADEONPTR(scrn); struct dri2_buffer_priv *priv = front->driverPrivate; pixmap = get_drawable_pixmap(draw); @@ -699,7 +670,7 @@ update_front(DrawablePtr draw, DRI2BufferPtr front) if (!info->use_glamor) exaMoveInPixmap(pixmap); - if (!radeon_get_flink_name(info, pixmap, &front->name)) { + if (!radeon_get_flink_name(pRADEONEnt, pixmap, &front->name)) { (*draw->pScreen->DestroyPixmap)(pixmap); return FALSE; } @@ -719,17 +690,6 @@ can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw, struct dri2_buffer_priv *back_priv = back->driverPrivate; PixmapPtr front_pixmap; PixmapPtr back_pixmap = back_priv->pixmap; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - - for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - - if (crtc->enabled && - (crtc->rotatedData || drmmode_crtc->scanout[0].bo)) - return FALSE; - } if (!update_front(draw, front)) return FALSE; @@ -752,18 +712,29 @@ can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw, } static Bool -can_flip(ScrnInfoPtr pScrn, DrawablePtr draw, +can_flip(xf86CrtcPtr crtc, DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back) { + ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int num_crtcs_on; + int i; + + if (draw->type != DRAWABLE_WINDOW || + !info->allowPageFlip || + info->hwcursor_disabled || + info->drmmode.present_flipping || + !pScrn->vtSema || + !DRI2CanFlip(draw)) + return FALSE; - return draw->type == DRAWABLE_WINDOW && - info->allowPageFlip && - !info->hwcursor_disabled && - !info->drmmode.present_flipping && - pScrn->vtSema && - DRI2CanFlip(draw) && - can_exchange(pScrn, draw, front, back); + for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { + if (drmmode_crtc_can_flip(config->crtc[i])) + num_crtcs_on++; + } + + return num_crtcs_on > 0 && can_exchange(pScrn, draw, front, back); } static void @@ -840,7 +811,7 @@ static void radeon_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq, switch (event->type) { case DRI2_FLIP: - if (can_flip(scrn, drawable, event->front, event->back) && + if (can_flip(crtc, drawable, event->front, event->back) && radeon_dri2_schedule_flip(crtc, event->client, drawable, @@ -864,7 +835,8 @@ static void radeon_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq, box.x2 = drawable->width; box.y2 = drawable->height; REGION_INIT(pScreen, ®ion, &box, 0); - radeon_dri2_copy_region(drawable, ®ion, event->front, event->back); + radeon_dri2_copy_region2(drawable->pScreen, drawable, ®ion, + event->front, event->back); swap_type = DRI2_BLIT_COMPLETE; } @@ -888,26 +860,6 @@ cleanup: radeon_dri2_frame_event_abort(crtc, event_data); } -drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc) -{ - drmVBlankSeqType type = 0; - int crtc_id = drmmode_get_crtc_id(crtc); - - if (crtc_id == 1) - type |= DRM_VBLANK_SECONDARY; - else if (crtc_id > 1) -#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT - type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & - DRM_VBLANK_HIGH_CRTC_MASK; -#else - ErrorF("radeon driver bug: %s called for CRTC %d > 1, but " - "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n", - __func__, crtc_id); -#endif - - return type; -} - /* * This function should be called on a disabled CRTC only (i.e., CRTC * in DPMS-off state). It will calculate the delay necessary to reach @@ -919,7 +871,7 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc, { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 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; @@ -932,7 +884,7 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc, *target_msc = 0; return FALLBACK_SWAP_DELAY; } - ret = drmmode_get_current_ust(info->dri2.drm_fd, &now); + ret = drmmode_get_current_ust(pRADEONEnt->fd, &now); if (ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); @@ -1010,7 +962,7 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) DRI2FrameEventPtr event_info = (DRI2FrameEventPtr)data; xf86CrtcPtr crtc = event_info->crtc; ScrnInfoPtr scrn; - RADEONInfoPtr info; + RADEONEntPtr pRADEONEnt; CARD64 drm_now; int ret; CARD64 delta_t, delta_seq, frame; @@ -1033,13 +985,13 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) } scrn = crtc->scrn; - info = RADEONPTR(scrn); - ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now); + pRADEONEnt = RADEONEntPriv(scrn); + ret = drmmode_get_current_ust(pRADEONEnt->fd, &drm_now); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); if (event_info->drm_queue_seq) - radeon_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0, + radeon_drm_queue_handler(pRADEONEnt->fd, 0, 0, 0, (void*)event_info->drm_queue_seq); else radeon_dri2_frame_event_handler(crtc, 0, 0, data); @@ -1055,7 +1007,7 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) delta_seq /= 1000000; frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq; if (event_info->drm_queue_seq) - radeon_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000, + radeon_drm_queue_handler(pRADEONEnt->fd, frame, drm_now / 1000000, drm_now % 1000000, (void*)event_info->drm_queue_seq); else @@ -1086,13 +1038,11 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONInfoPtr info = RADEONPTR(scrn); DRI2FrameEventPtr wait_info = NULL; uintptr_t drm_queue_seq = 0; xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); uint32_t msc_delta; - drmVBlank vbl; - int ret; + uint32_t seq; CARD64 current_msc; /* Truncate to match kernel interfaces; means occasional overflow @@ -1131,17 +1081,13 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, } /* Get current count */ - 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) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); goto out_complete; } - current_msc = vbl.reply.sequence + msc_delta; + current_msc = seq + msc_delta; current_msc &= 0xffffffff; drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, @@ -1168,12 +1114,9 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, */ if (current_msc >= target_msc) 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 - msc_delta; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, + target_msc - msc_delta, drm_queue_seq, NULL, + NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); goto out_complete; @@ -1187,11 +1130,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, * If we get here, target_msc has already passed or we don't have one, * so we queue an event that will satisfy the divisor/remainder equation. */ - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - - vbl.request.sequence = current_msc - (current_msc % divisor) + - remainder - msc_delta; + target_msc = current_msc - (current_msc % divisor) + remainder - msc_delta; /* * If calculated remainder is larger than requested remainder, @@ -1200,11 +1139,10 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, * that will happen. */ if ((current_msc % divisor) >= remainder) - vbl.request.sequence += divisor; + target_msc += divisor; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, + target_msc, drm_queue_seq, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); goto out_complete; @@ -1248,14 +1186,14 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; 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; + drmVBlankSeqType type; + uint32_t seq; + int flip = 0; DRI2FrameEventPtr swap_info = NULL; uintptr_t drm_queue_seq; - CARD64 current_msc; + CARD64 current_msc, event_msc; BoxRec box; RegionRec region; @@ -1318,22 +1256,18 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, } /* Get current count */ - 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) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "first get vblank counter failed: %s\n", strerror(errno)); goto blit_fallback; } - current_msc = vbl.reply.sequence + msc_delta; + current_msc = seq + msc_delta; current_msc &= 0xffffffff; /* Flips need to be submitted one frame before */ - if (can_flip(scrn, draw, front, back)) { + if (can_flip(crtc, draw, front, back)) { swap_info->type = DRI2_FLIP; flip = 1; } @@ -1351,14 +1285,13 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, * the swap. */ if (divisor == 0 || current_msc < *target_msc) { - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; /* If non-pageflipping, but blitting/exchanging, we need to use * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later * on. */ if (flip == 0) - vbl.request.type |= DRM_VBLANK_NEXTONMISS; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); + type |= DRM_VBLANK_NEXTONMISS; /* If target_msc already reached or passed, set it to * current_msc to ensure we return a reasonable value back @@ -1367,17 +1300,15 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, if (current_msc >= *target_msc) *target_msc = current_msc; - vbl.request.sequence = *target_msc - msc_delta; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, type, *target_msc - msc_delta, + drm_queue_seq, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "divisor 0 get vblank counter failed: %s\n", strerror(errno)); goto blit_fallback; } - *target_msc = vbl.reply.sequence + flip + msc_delta; + *target_msc = seq + flip + msc_delta; swap_info->frame = *target_msc; return TRUE; @@ -1388,13 +1319,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, * and we need to queue an event that will satisfy the divisor/remainder * equation. */ - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; if (flip == 0) - vbl.request.type |= DRM_VBLANK_NEXTONMISS; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); + type |= DRM_VBLANK_NEXTONMISS; - vbl.request.sequence = current_msc - (current_msc % divisor) + - remainder - msc_delta; + event_msc = current_msc - (current_msc % divisor) + remainder - msc_delta; /* * If the calculated deadline vbl.request.sequence is smaller than @@ -1407,15 +1336,13 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay * if we are blitting/exchanging instead of flipping. */ - if (vbl.request.sequence <= current_msc) - vbl.request.sequence += divisor; + if (event_msc <= current_msc) + event_msc += divisor; /* Account for 1 frame extra pageflip delay if flip > 0 */ - vbl.request.sequence -= flip; + event_msc -= flip; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, type, event_msc, drm_queue_seq, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "final get vblank counter failed: %s\n", strerror(errno)); @@ -1423,7 +1350,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, } /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ - *target_msc = vbl.reply.sequence + flip + msc_delta; + *target_msc = seq + flip + msc_delta; *target_msc &= 0xffffffff; swap_info->frame = *target_msc; @@ -1440,7 +1367,7 @@ blit_fallback: box.y2 = draw->height; REGION_INIT(pScreen, ®ion, &box, 0); - radeon_dri2_copy_region(draw, ®ion, front, back); + radeon_dri2_copy_region2(draw->pScreen, draw, ®ion, front, back); DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); @@ -1457,6 +1384,7 @@ Bool radeon_dri2_screen_init(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); DRI2InfoRec dri2_info = { 0 }; const char *driverNames[2]; @@ -1465,7 +1393,7 @@ radeon_dri2_screen_init(ScreenPtr pScreen) if (!info->dri2.available) return FALSE; - info->dri2.device_name = drmGetDeviceNameFromFd(info->dri2.drm_fd); + info->dri2.device_name = drmGetDeviceNameFromFd(pRADEONEnt->fd); if ( (info->ChipFamily >= CHIP_FAMILY_TAHITI) ) { dri2_info.driverName = SI_DRIVER_NAME; @@ -1478,12 +1406,8 @@ radeon_dri2_screen_init(ScreenPtr pScreen) } else { dri2_info.driverName = RADEON_DRIVER_NAME; } - dri2_info.fd = info->dri2.drm_fd; + dri2_info.fd = pRADEONEnt->fd; dri2_info.deviceName = info->dri2.device_name; - dri2_info.version = DRI2INFOREC_VERSION; - dri2_info.CreateBuffer = radeon_dri2_create_buffer; - dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer; - dri2_info.CopyRegion = radeon_dri2_copy_region; if (info->dri2.pKernelDRMVersion->version_minor < 4) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for " @@ -1495,7 +1419,7 @@ radeon_dri2_screen_init(ScreenPtr pScreen) #ifdef DRM_CAP_VBLANK_HIGH_CRTC uint64_t cap_value; - if (drmGetCap(info->dri2.drm_fd, DRM_CAP_VBLANK_HIGH_CRTC, &cap_value)) { + if (drmGetCap(pRADEONEnt->fd, DRM_CAP_VBLANK_HIGH_CRTC, &cap_value)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel " "for VBLANKs on CRTC > 1\n"); scheduling_works = FALSE; @@ -1512,11 +1436,10 @@ radeon_dri2_screen_init(ScreenPtr pScreen) } if (scheduling_works) { - dri2_info.version = 4; dri2_info.ScheduleSwap = radeon_dri2_schedule_swap; dri2_info.GetMSC = radeon_dri2_get_msc; dri2_info.ScheduleWaitMSC = radeon_dri2_schedule_wait_msc; - dri2_info.numDrivers = RADEON_ARRAY_SIZE(driverNames); + dri2_info.numDrivers = ARRAY_SIZE(driverNames); dri2_info.driverNames = driverNames; driverNames[0] = dri2_info.driverName; @@ -1540,12 +1463,10 @@ radeon_dri2_screen_init(ScreenPtr pScreen) DRI2InfoCnt++; } -#if DRI2INFOREC_VERSION >= 9 dri2_info.version = 9; dri2_info.CreateBuffer2 = radeon_dri2_create_buffer2; dri2_info.DestroyBuffer2 = radeon_dri2_destroy_buffer2; dri2_info.CopyRegion2 = radeon_dri2_copy_region2; -#endif info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info); return info->dri2.enabled; diff --git a/src/radeon_dri2.h b/src/radeon_dri2.h index 9ba47c78..4d3f377b 100644 --- a/src/radeon_dri2.h +++ b/src/radeon_dri2.h @@ -31,7 +31,6 @@ struct radeon_dri2 { drmVersionPtr pKernelDRMVersion; - int drm_fd; Bool available; Bool enabled; char *device_name; diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c index fa24abae..3e689ffd 100644 --- a/src/radeon_dri3.c +++ b/src/radeon_dri3.c @@ -43,6 +43,7 @@ static int open_master_node(ScreenPtr screen, int *out) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); RADEONInfoPtr info = RADEONPTR(scrn); drm_magic_t magic; int fd; @@ -76,7 +77,7 @@ static int open_master_node(ScreenPtr screen, int *out) } } - if (drmAuthMagic(info->dri2.drm_fd, magic) < 0) { + if (drmAuthMagic(pRADEONEnt->fd, magic) < 0) { close(fd); return BadMatch; } diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c index 31f24350..869f95c3 100644 --- a/src/radeon_drm_queue.c +++ b/src/radeon_drm_queue.c @@ -31,10 +31,11 @@ #endif #include <xorg-server.h> +#include <X11/Xdefs.h> +#include <list.h> #include "radeon.h" #include "radeon_drm_queue.h" -#include "radeon_list.h" struct radeon_drm_queue_entry { @@ -105,7 +106,7 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, e->handler = handler; e->abort = abort; - xorg_list_add(&e->list, &radeon_drm_queue); + xorg_list_append(&e->list, &radeon_drm_queue); return e->seq; } diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 1e457a8b..9106d5c6 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -300,6 +300,7 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(xf86ScreenToScrn(pScreen)); struct radeon_exa_pixmap_priv *driver_priv = driverPriv; if (!driverPriv) @@ -307,10 +308,10 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) if (driver_priv->bo) radeon_bo_unref(driver_priv->bo); + drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL); free(driverPriv); } -#ifdef RADEON_PIXMAP_SHARING Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) { struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); @@ -332,7 +333,6 @@ Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) driver_priv->shared = TRUE; return TRUE; } -#endif uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix) { diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index d9013057..da0524ed 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -644,10 +644,8 @@ Bool RADEONDrawInit(ScreenPtr pScreen) info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS; info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2; -#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 6) info->accel_state->exa->SharePixmapBacking = RADEONEXASharePixmapBacking; info->accel_state->exa->SetSharedPixmapBacking = RADEONEXASetSharedPixmapBacking; -#endif info->accel_state->exa->maxPitchBytes = 16320; diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c index 590c9f0c..5f378743 100644 --- a/src/radeon_glamor.c +++ b/src/radeon_glamor.c @@ -61,11 +61,10 @@ radeon_glamor_create_screen_resources(ScreenPtr screen) return FALSE; #endif - if (!glamor_egl_create_textured_screen_ext(screen, - info->front_bo->handle, - scrn->displayWidth * - info->pixel_bytes, - NULL)) + if (!glamor_egl_create_textured_screen(screen, + info->front_bo->handle, + scrn->displayWidth * + info->pixel_bytes)) return FALSE; return TRUE; @@ -75,6 +74,7 @@ radeon_glamor_create_screen_resources(ScreenPtr screen) Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); RADEONInfoPtr info = RADEONPTR(scrn); pointer glamor_module; CARD32 version; @@ -136,7 +136,7 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn) "Incompatible glamor version, required >= 0.3.0.\n"); return FALSE; } else { - if (glamor_egl_init(scrn, info->dri2.drm_fd)) { + if (glamor_egl_init(scrn, pRADEONEnt->fd)) { xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor detected, initialising EGL layer.\n"); } else { @@ -337,7 +337,6 @@ radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap) return old; } -#ifdef RADEON_PIXMAP_SHARING static Bool radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, @@ -404,7 +403,6 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle) return TRUE; } -#endif /* RADEON_PIXMAP_SHARING */ Bool radeon_glamor_init(ScreenPtr screen) @@ -463,12 +461,10 @@ radeon_glamor_init(ScreenPtr screen) screen->CreatePixmap = radeon_glamor_create_pixmap; info->glamor.SavedDestroyPixmap = screen->DestroyPixmap; screen->DestroyPixmap = radeon_glamor_destroy_pixmap; -#ifdef RADEON_PIXMAP_SHARING info->glamor.SavedSharePixmapBacking = screen->SharePixmapBacking; screen->SharePixmapBacking = radeon_glamor_share_pixmap_backing; info->glamor.SavedSetSharedPixmapBacking = screen->SetSharedPixmapBacking; screen->SetSharedPixmapBacking = radeon_glamor_set_shared_pixmap_backing; -#endif xf86DrvMsg(scrn->scrnIndex, X_INFO, "Use GLAMOR acceleration.\n"); @@ -485,10 +481,8 @@ radeon_glamor_fini(ScreenPtr screen) screen->CreatePixmap = info->glamor.SavedCreatePixmap; screen->DestroyPixmap = info->glamor.SavedDestroyPixmap; -#ifdef RADEON_PIXMAP_SHARING screen->SharePixmapBacking = info->glamor.SavedSharePixmapBacking; screen->SetSharedPixmapBacking = info->glamor.SavedSetSharedPixmapBacking; -#endif } XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt) diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h index fdc4e577..ec42df1f 100644 --- a/src/radeon_glamor.h +++ b/src/radeon_glamor.h @@ -38,10 +38,6 @@ struct radeon_pixmap; #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) diff --git a/src/radeon_glamor_wrappers.c b/src/radeon_glamor_wrappers.c index 5f165ebe..d7374252 100644 --- a/src/radeon_glamor_wrappers.c +++ b/src/radeon_glamor_wrappers.c @@ -889,7 +889,7 @@ radeon_glamor_triangles(CARD8 op, PicturePtr src, PicturePtr dst, * down our screen private, before calling down to the next CloseScreen. */ static Bool -radeon_glamor_close_screen(CLOSE_SCREEN_ARGS_DECL) +radeon_glamor_close_screen(ScreenPtr pScreen) { RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pScreen)); #ifdef RENDER @@ -917,7 +917,7 @@ radeon_glamor_close_screen(CLOSE_SCREEN_ARGS_DECL) } #endif - return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); + return pScreen->CloseScreen(pScreen); } /** diff --git a/src/radeon_kms.c b/src/radeon_kms.c index a95b51ab..9ef51693 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -32,6 +32,7 @@ #include <sys/ioctl.h> /* Driver data structures */ #include "radeon.h" +#include "radeon_bo_helper.h" #include "radeon_drm_queue.h" #include "radeon_glamor.h" #include "radeon_reg.h" @@ -44,6 +45,10 @@ #include "atipciids.h" +#if HAVE_PRESENT_H +#include <present.h> +#endif + /* DPMS */ #ifdef HAVE_XEXTPROTO_71 #include <X11/extensions/dpmsconst.h> @@ -187,6 +192,7 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn) /* Free our private RADEONInfoRec */ static void RADEONFreeRec(ScrnInfoPtr pScrn) { + RADEONEntPtr pRADEONEnt; RADEONInfoPtr info; if (!pScrn || !pScrn->driverPrivate) return; @@ -196,7 +202,9 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn) if (info->fbcon_pixmap) pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); - if (info->dri2.drm_fd > 0) { + pRADEONEnt = RADEONEntPriv(pScrn); + + if (pRADEONEnt->fd > 0) { DevUnion *pPriv; RADEONEntPtr pRADEONEnt; pPriv = xf86GetEntityPrivate(pScrn->entityList[0], @@ -317,9 +325,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) if (dixPrivateKeyRegistered(rrPrivKey)) { rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen); - if (!radeon_is_gpu_screen(pScreen) && - !rrScrPriv->primaryOutput) - { + if (!pScreen->isGPU && !rrScrPriv->primaryOutput) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output; @@ -328,7 +334,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) } } - if (!drmmode_set_desired_modes(pScrn, &info->drmmode, FALSE)) + if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU)) return FALSE; drmmode_uevent_init(pScrn, &info->drmmode); @@ -357,8 +363,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) radeon_glamor_create_screen_resources(pScreen); info->callback_event_type = -1; - if (!radeon_is_gpu_screen(pScreen) && - (damage_ext = CheckExtension("DAMAGE"))) { + if (!pScreen->isGPU && (damage_ext = CheckExtension("DAMAGE"))) { info->callback_event_type = damage_ext->eventBase + XDamageNotify; if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn)) @@ -383,15 +388,12 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) static Bool radeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents) { -#ifdef RADEON_PIXMAP_SHARING if (xf86_crtc->scrn->is_gpu) { extents->x1 -= xf86_crtc->x; extents->y1 -= xf86_crtc->y; extents->x2 -= xf86_crtc->x; extents->y2 -= xf86_crtc->y; - } else -#endif - { + } else { extents->x1 -= xf86_crtc->filter_width >> 1; extents->x2 += xf86_crtc->filter_width >> 1; extents->y1 -= xf86_crtc->filter_height >> 1; @@ -407,8 +409,6 @@ radeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents) return (extents->x1 < extents->x2 && extents->y1 < extents->y2); } -#if XF86_CRTC_VERSION >= 4 - static RegionPtr transform_region(RegionPtr region, struct pict_f_transform *transform, int w, int h) @@ -447,8 +447,6 @@ transform_region(RegionPtr region, struct pict_f_transform *transform, return transformed; } -#endif - static void radeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, int scanout_id) @@ -478,14 +476,11 @@ radeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, if (!radeon_scanout_extents_intersect(xf86_crtc, &extents)) goto uninit; -#if XF86_CRTC_VERSION >= 4 if (xf86_crtc->driverIsPerformingTransform) { sync_region = transform_region(&remaining, &xf86_crtc->f_framebuffer_to_crtc, dst->width, dst->height); - } else -#endif /* XF86_CRTC_VERSION >= 4 */ - { + } else { sync_region = RegionDuplicate(&remaining); RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y); } @@ -510,7 +505,38 @@ radeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, RegionUninit(&remaining); } -#ifdef RADEON_PIXMAP_SHARING +static void +radeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + drmmode_crtc->scanout_update_pending = FALSE; + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + NULL); +} + +static void +radeon_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec, + void *event_data) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, + drmmode_crtc->flip_pending); + radeon_scanout_flip_abort(crtc, event_data); + +#ifdef HAVE_PRESENT_H + if (drmmode_crtc->present_vblank_event_id) { + present_event_notify(drmmode_crtc->present_vblank_event_id, + drmmode_crtc->present_vblank_usec, + drmmode_crtc->present_vblank_msc); + drmmode_crtc->present_vblank_event_id = 0; + } +#endif +} + static RegionPtr dirty_region(PixmapDirtyUpdatePtr dirty) @@ -542,7 +568,7 @@ dirty_region(PixmapDirtyUpdatePtr dirty) static void redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) { - ScrnInfoPtr pScrn = xf86ScreenToScrn(dirty->src->drawable.pScreen); + ScrnInfoPtr pScrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen); if (RegionNil(region)) goto out; @@ -575,12 +601,12 @@ radeon_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) void radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) { - ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen; + ScreenPtr master_screen = radeon_dirty_master(dirty); PixmapDirtyUpdatePtr ent; RegionPtr region; xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) { - if (ent->slave_dst != dirty->src) + if (!radeon_dirty_src_equals(dirty, ent->slave_dst)) continue; region = dirty_region(ent); @@ -595,7 +621,7 @@ radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) static Bool master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) { - ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen; + ScreenPtr master_screen = radeon_dirty_master(dirty); return master_screen->SyncSharedPixmap != NULL; } @@ -611,7 +637,7 @@ slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) static void call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) { - ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen; + ScreenPtr master_screen = radeon_dirty_master(dirty); master_screen->SyncSharedPixmap(dirty); } @@ -621,7 +647,7 @@ call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) static Bool master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) { - ScrnInfoPtr master_scrn = xf86ScreenToScrn(dirty->src->master_pixmap->drawable.pScreen); + ScrnInfoPtr master_scrn = xf86ScreenToScrn(radeon_dirty_master(dirty)); return master_scrn->driverName == scrn->driverName; } @@ -643,20 +669,37 @@ call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) #endif /* HAS_SYNC_SHARED_PIXMAPS */ +static xf86CrtcPtr +radeon_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty) +{ + ScreenPtr screen = dirty->slave_dst->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + /* Find the CRTC which is scanning out from this slave pixmap */ + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr xf86_crtc = xf86_config->crtc[c]; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) + return xf86_crtc; + } + + return NULL; +} + static Bool radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) { ScrnInfoPtr scrn = crtc->scrn; ScreenPtr screen = scrn->pScreen; - RADEONInfoPtr info = RADEONPTR(scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap; PixmapDirtyUpdatePtr dirty; Bool ret = FALSE; xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { - if (dirty->src == scanoutpix && dirty->slave_dst == - drmmode_crtc->scanout[scanout_id ^ info->tear_free].pixmap) { + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { RegionPtr region; if (master_has_sync_shared_pixmap(scrn, dirty)) @@ -666,7 +709,7 @@ radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) if (RegionNil(region)) goto destroy; - if (info->tear_free) { + if (drmmode_crtc->tear_free) { RegionTranslate(region, crtc->x, crtc->y); radeon_sync_scanout_pixmaps(crtc, region, scanout_id); radeon_cs_flush_indirect(scrn); @@ -701,26 +744,17 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) { ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr xf86_crtc = NULL; - drmmode_crtc_private_ptr drmmode_crtc = NULL; + xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty); + drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; - drmVBlank vbl; - int c; - /* Find the CRTC which is scanning out from this slave pixmap */ - for (c = 0; c < xf86_config->num_crtc; c++) { - xf86_crtc = xf86_config->crtc[c]; - drmmode_crtc = xf86_crtc->driver_private; - if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst) - break; - } + if (!xf86_crtc || !xf86_crtc->enabled) + return; - if (c == xf86_config->num_crtc || - !xf86_crtc->enabled || - drmmode_crtc->scanout_update_pending || - !drmmode_crtc->scanout[0].pixmap || - drmmode_crtc->pending_dpms_mode != DPMSModeOn) + drmmode_crtc = xf86_crtc->driver_private; + if (drmmode_crtc->scanout_update_pending || + !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || + drmmode_crtc->dpms_mode != DPMSModeOn) return; drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, @@ -734,13 +768,10 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) 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 = drm_queue_seq; - if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) { + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + 1, drm_queue_seq, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmWaitVBlank failed for PRIME update: %s\n", + "drmmode_wait_vblank failed for PRIME update: %s\n", strerror(errno)); radeon_drm_abort_entry(drm_queue_seq); return; @@ -750,41 +781,23 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) } static void -radeon_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) -{ - drmmode_crtc_private_ptr drmmode_crtc = event_data; - - drmmode_crtc->scanout_update_pending = FALSE; - drmmode_clear_pending_flip(crtc); -} - -static void radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent) { ScreenPtr screen = ent->slave_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = NULL; - drmmode_crtc_private_ptr drmmode_crtc = NULL; + xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent); + drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; unsigned scanout_id; - int c; - /* Find the CRTC which is scanning out from this slave pixmap */ - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - drmmode_crtc = crtc->driver_private; - scanout_id = drmmode_crtc->scanout_id; - if (drmmode_crtc->scanout[scanout_id].pixmap == ent->slave_dst) - break; - } + if (!crtc || !crtc->enabled) + return; - if (c == xf86_config->num_crtc || - !crtc->enabled || - drmmode_crtc->scanout_update_pending || + drmmode_crtc = crtc->driver_private; + if (drmmode_crtc->scanout_update_pending || !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || - drmmode_crtc->pending_dpms_mode != DPMSModeOn) + drmmode_crtc->dpms_mode != DPMSModeOn) return; scanout_id = drmmode_crtc->scanout_id ^ 1; @@ -794,16 +807,26 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent) drm_queue_seq = radeon_drm_queue_alloc(crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, - drmmode_crtc, NULL, - radeon_prime_scanout_flip_abort); + NULL, + radeon_scanout_flip_handler, + radeon_scanout_flip_abort); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM event queue entry failed for PRIME flip.\n"); return; } + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); + if (!drmmode_crtc->flip_pending) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for PRIME flip.\n"); + radeon_drm_abort_entry(drm_queue_seq); + return; + } + if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode_crtc->scanout[scanout_id].fb_id, + drmmode_crtc->flip_pending->handle, 0, drm_queue_seq, 0) != 0) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", __func__, strerror(errno)); @@ -813,13 +836,11 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent) drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = TRUE; - drmmode_crtc->flip_pending = TRUE; } static void radeon_dirty_update(ScrnInfoPtr scrn) { - RADEONInfoPtr info = RADEONPTR(scrn); ScreenPtr screen = scrn->pScreen; PixmapDirtyUpdatePtr ent; RegionPtr region; @@ -829,10 +850,10 @@ radeon_dirty_update(ScrnInfoPtr scrn) PixmapDirtyUpdatePtr region_ent = ent; if (master_has_sync_shared_pixmap(scrn, ent)) { - ScreenPtr master_screen = ent->src->master_pixmap->drawable.pScreen; + ScreenPtr master_screen = radeon_dirty_master(ent); xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) { - if (region_ent->slave_dst == ent->src) + if (radeon_dirty_src_equals(ent, region_ent->slave_dst)) break; } } @@ -840,7 +861,13 @@ radeon_dirty_update(ScrnInfoPtr scrn) region = dirty_region(region_ent); if (RegionNotEmpty(region)) { - if (info->tear_free) + xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent); + drmmode_crtc_private_ptr drmmode_crtc = NULL; + + if (crtc) + drmmode_crtc = crtc->driver_private; + + if (drmmode_crtc && drmmode_crtc->tear_free) radeon_prime_scanout_flip(ent); else radeon_prime_scanout_update(ent); @@ -859,55 +886,45 @@ radeon_dirty_update(ScrnInfoPtr scrn) } } } -#endif + Bool -radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) +radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, + PixmapPtr src_pix, BoxPtr extents) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; - RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage); + RegionRec region = { .extents = *extents, .data = NULL }; ScrnInfoPtr scrn = xf86_crtc->scrn; ScreenPtr pScreen = scrn->pScreen; RADEONInfoPtr info = RADEONPTR(scrn); DrawablePtr pDraw; - BoxRec extents; Bool force; if (!xf86_crtc->enabled || - drmmode_crtc->pending_dpms_mode != DPMSModeOn || - !drmmode_crtc->scanout[scanout_id].pixmap) - return FALSE; - - if (!RegionNotEmpty(pRegion)) + !drmmode_crtc->scanout[scanout_id].pixmap || + extents->x1 >= extents->x2 || extents->y1 >= extents->y2) return FALSE; pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; - extents = *RegionExtents(pRegion); - if (!radeon_scanout_extents_intersect(xf86_crtc, &extents)) + if (!radeon_scanout_extents_intersect(xf86_crtc, extents)) return FALSE; - if (info->tear_free) { - radeon_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id); - RegionCopy(&drmmode_crtc->scanout_last_region, pRegion); + if (drmmode_crtc->tear_free) { + radeon_sync_scanout_pixmaps(xf86_crtc, ®ion, scanout_id); + RegionCopy(&drmmode_crtc->scanout_last_region, ®ion); } - RegionEmpty(pRegion); force = info->accel_state->force; info->accel_state->force = TRUE; -#if XF86_CRTC_VERSION >= 4 if (xf86_crtc->driverIsPerformingTransform) { SourceValidateProcPtr SourceValidate = pScreen->SourceValidate; PictFormatPtr format = PictureWindowFormat(pScreen->root); int error; PicturePtr src, dst; - XID include_inferiors = IncludeInferiors; - src = CreatePicture(None, - &pScreen->root->drawable, - format, - CPSubwindowMode, - &include_inferiors, serverClient, &error); + src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL, + serverClient, &error); if (!src) { ErrorF("Failed to create source picture for transformed scanout " "update\n"); @@ -935,9 +952,9 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) pScreen->SourceValidate = NULL; CompositePicture(PictOpSrc, src, NULL, dst, - extents.x1, extents.y1, 0, 0, extents.x1, - extents.y1, extents.x2 - extents.x1, - extents.y2 - extents.y1); + extents->x1, extents->y1, 0, 0, extents->x1, + extents->y1, extents->x2 - extents->x1, + extents->y2 - extents->y1); pScreen->SourceValidate = SourceValidate; free_dst: @@ -946,16 +963,14 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) FreePicture(src, None); } else out: -#endif /* XF86_CRTC_VERSION >= 4 */ { GCPtr gc = GetScratchGC(pDraw->depth, pScreen); 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); + (*gc->ops->CopyArea)(&src_pix->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); } @@ -978,7 +993,18 @@ static void radeon_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data) { - radeon_scanout_do_update(crtc, 0); + drmmode_crtc_private_ptr drmmode_crtc = event_data; + ScreenPtr screen = crtc->scrn->pScreen; + RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage); + + if (crtc->enabled && + !drmmode_crtc->flip_pending && + drmmode_crtc->dpms_mode == DPMSModeOn) { + if (radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id, + screen->GetWindowPixmap(screen->root), + ®ion->extents)) + RegionEmpty(region); + } radeon_scanout_update_abort(crtc, event_data); } @@ -989,15 +1015,14 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; uintptr_t drm_queue_seq; ScrnInfoPtr scrn; - drmVBlank vbl; DamagePtr pDamage; RegionPtr pRegion; BoxRec extents; if (!xf86_crtc->enabled || drmmode_crtc->scanout_update_pending || - !drmmode_crtc->scanout[0].pixmap || - drmmode_crtc->pending_dpms_mode != DPMSModeOn) + drmmode_crtc->flip_pending || + drmmode_crtc->dpms_mode != DPMSModeOn) return; pDamage = drmmode_crtc->scanout_damage; @@ -1027,13 +1052,10 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) 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 = drm_queue_seq; - if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) { + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + 1, drm_queue_seq, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmWaitVBlank failed for scanout update: %s\n", + "drmmode_wait_vblank failed for scanout update: %s\n", strerror(errno)); radeon_drm_abort_entry(drm_queue_seq); return; @@ -1043,35 +1065,33 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) } static void -radeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) -{ - drmmode_crtc_private_ptr drmmode_crtc = event_data; - - drmmode_crtc->scanout_update_pending = FALSE; - drmmode_clear_pending_flip(crtc); -} - -static void radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, xf86CrtcPtr xf86_crtc) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage); ScrnInfoPtr scrn = xf86_crtc->scrn; RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); uintptr_t drm_queue_seq; unsigned scanout_id; - if (drmmode_crtc->scanout_update_pending) + if (drmmode_crtc->scanout_update_pending || + drmmode_crtc->flip_pending || + drmmode_crtc->dpms_mode != DPMSModeOn) return; scanout_id = drmmode_crtc->scanout_id ^ 1; - if (!radeon_scanout_do_update(xf86_crtc, scanout_id)) + if (!radeon_scanout_do_update(xf86_crtc, scanout_id, + pScreen->GetWindowPixmap(pScreen->root), + ®ion->extents)) return; + RegionEmpty(region); drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, - drmmode_crtc, NULL, + NULL, + radeon_scanout_flip_handler, radeon_scanout_flip_abort); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1079,23 +1099,38 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, return; } + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); + if (!drmmode_crtc->flip_pending) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for scanout flip.\n"); + radeon_drm_abort_entry(drm_queue_seq); + return; + } + if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode_crtc->scanout[scanout_id].fb_id, + drmmode_crtc->flip_pending->handle, 0, drm_queue_seq, 0) != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, " + "TearFree inactive until next modeset\n", __func__, strerror(errno)); radeon_drm_abort_entry(drm_queue_seq); + RegionCopy(DamageRegion(drmmode_crtc->scanout_damage), + &drmmode_crtc->scanout_last_region); + RegionEmpty(&drmmode_crtc->scanout_last_region); + radeon_scanout_update(xf86_crtc); + drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, + &drmmode_crtc->scanout[scanout_id]); + drmmode_crtc->tear_free = FALSE; return; } drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = TRUE; - drmmode_crtc->flip_pending = TRUE; } static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) { - SCREEN_PTR(arg); ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -1105,41 +1140,30 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); pScreen->BlockHandler = RADEONBlockHandler_KMS; - if (!radeon_is_gpu_screen(pScreen)) + if (!xf86ScreenToScrn(radeon_master_screen(pScreen))->vtSema) + return; + + if (!pScreen->isGPU) { for (c = 0; c < xf86_config->num_crtc; c++) { - if (info->tear_free) - radeon_scanout_flip(pScreen, info, xf86_config->crtc[c]); - else if (info->shadow_primary -#if XF86_CRTC_VERSION >= 4 - || xf86_config->crtc[c]->driverIsPerformingTransform -#endif - ) - radeon_scanout_update(xf86_config->crtc[c]); + xf86CrtcPtr crtc = xf86_config->crtc[c]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + if (drmmode_crtc->tear_free) + radeon_scanout_flip(pScreen, info, crtc); + else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap) + radeon_scanout_update(crtc); } } radeon_cs_flush_indirect(pScrn); -#ifdef RADEON_PIXMAP_SHARING radeon_dirty_update(pScrn); -#endif -} - -static void RADEONBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL) -{ - SCREEN_PTR(arg); - ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - RADEONInfoPtr info = RADEONPTR(pScrn); - - RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS); - - drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); } static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); struct drm_radeon_info ginfo; int r; uint32_t tmp = 0; @@ -1147,7 +1171,7 @@ static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn) memset(&ginfo, 0, sizeof(ginfo)); ginfo.request = RADEON_INFO_FASTFB_WORKING; ginfo.value = (uintptr_t)&tmp; - r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); + r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); if (r) { return FALSE; } @@ -1158,7 +1182,7 @@ static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn) static Bool RADEONIsFusionGARTWorking(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); struct drm_radeon_info ginfo; int r; uint32_t tmp; @@ -1166,7 +1190,7 @@ static Bool RADEONIsFusionGARTWorking(ScrnInfoPtr pScrn) memset(&ginfo, 0, sizeof(ginfo)); ginfo.request = RADEON_INFO_FUSION_GART_WORKING; ginfo.value = (uintptr_t)&tmp; - r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); + r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); if (r) { return FALSE; } @@ -1177,6 +1201,7 @@ static Bool RADEONIsFusionGARTWorking(ScrnInfoPtr pScrn) static Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); struct drm_radeon_info ginfo; int r; @@ -1188,7 +1213,7 @@ static Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn) else ginfo.request = RADEON_INFO_ACCEL_WORKING; ginfo.value = (uintptr_t)&tmp; - r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); + r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); if (r) { /* If kernel is too old before 2.6.32 than assume accel is working */ if (r == -EINVAL) { @@ -1306,9 +1331,10 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GPU accel disabled or not working, using shadowfb for KMS\n"); shadowfb: - info->r600_shadow_fb = TRUE; if (!xf86LoadSubModule(pScrn, "shadow")) - info->r600_shadow_fb = FALSE; + return FALSE; + + info->r600_shadow_fb = TRUE; return TRUE; } @@ -1426,7 +1452,6 @@ static int radeon_get_drm_master_fd(ScrnInfoPtr pScrn) static Bool radeon_open_drm_master(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); drmSetVersion sv; int err; @@ -1434,14 +1459,12 @@ static Bool radeon_open_drm_master(ScrnInfoPtr pScrn) if (pRADEONEnt->fd) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, " reusing fd for second head\n"); - - info->drmmode.fd = info->dri2.drm_fd = pRADEONEnt->fd; pRADEONEnt->fd_ref++; return TRUE; } - info->dri2.drm_fd = radeon_get_drm_master_fd(pScrn); - if (info->dri2.drm_fd == -1) + pRADEONEnt->fd = radeon_get_drm_master_fd(pScrn); + if (pRADEONEnt->fd == -1) return FALSE; /* Check that what we opened was a master or a master-capable FD, @@ -1452,24 +1475,23 @@ static Bool radeon_open_drm_master(ScrnInfoPtr pScrn) sv.drm_di_minor = 1; sv.drm_dd_major = -1; sv.drm_dd_minor = -1; - err = drmSetInterfaceVersion(info->dri2.drm_fd, &sv); + err = drmSetInterfaceVersion(pRADEONEnt->fd, &sv); if (err != 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failed to set drm interface version.\n"); - drmClose(info->dri2.drm_fd); - info->dri2.drm_fd = -1; + drmClose(pRADEONEnt->fd); + pRADEONEnt->fd = -1; return FALSE; } - pRADEONEnt->fd = info->dri2.drm_fd; pRADEONEnt->fd_ref = 1; - info->drmmode.fd = info->dri2.drm_fd; return TRUE; } static Bool r600_get_tile_config(ScrnInfoPtr pScrn) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); struct drm_radeon_info ginfo; int r; @@ -1481,7 +1503,7 @@ static Bool r600_get_tile_config(ScrnInfoPtr pScrn) memset(&ginfo, 0, sizeof(ginfo)); ginfo.request = RADEON_INFO_TILING_CONFIG; ginfo.value = (uintptr_t)&tmp; - r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); + r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); if (r) return FALSE; @@ -1577,7 +1599,7 @@ static Bool r600_get_tile_config(ScrnInfoPtr pScrn) static void RADEONSetupCapabilities(ScrnInfoPtr pScrn) { -#ifdef RADEON_PIXMAP_SHARING + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); uint64_t value; int ret; @@ -1588,7 +1610,7 @@ static void RADEONSetupCapabilities(ScrnInfoPtr pScrn) if (info->r600_shadow_fb) return; - ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_PRIME, &value); + ret = drmGetCap(pRADEONEnt->fd, DRM_CAP_PRIME, &value); if (ret == 0) { if (value & DRM_PRIME_CAP_EXPORT) pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; @@ -1598,7 +1620,6 @@ static void RADEONSetupCapabilities(ScrnInfoPtr pScrn) pScrn->capabilities |= RR_Capability_SinkOutput; } } -#endif } /* When the root window is created, initialize the screen contents from @@ -1625,10 +1646,37 @@ static Bool RADEONCreateWindow_oneshot(WindowPtr pWin) return ret; } +/* When the root window is mapped, set the initial modes */ +void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) + , RegionPtr pBSRegion +#endif + ) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (pWin != pScreen->root) + ErrorF("%s called for non-root window %p\n", __func__, pWin); + + pScreen->WindowExposures = info->WindowExposures; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) + pScreen->WindowExposures(pWin, pRegion, pBSRegion); +#else + pScreen->WindowExposures(pWin, pRegion); +#endif + + radeon_cs_flush_indirect(pScrn); + radeon_bo_wait(info->front_bo); + drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); +} + Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) { RADEONInfoPtr info; RADEONEntPtr pRADEONEnt; + MessageType from; DevUnion* pPriv; Gamma zeros = { 0.0, 0.0, 0.0 }; uint32_t tiling = 0; @@ -1699,7 +1747,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) info->dri2.available = FALSE; info->dri2.enabled = FALSE; - info->dri2.pKernelDRMVersion = drmGetVersion(info->dri2.drm_fd); + info->dri2.pKernelDRMVersion = drmGetVersion(pRADEONEnt->fd); if (info->dri2.pKernelDRMVersion == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RADEONDRIGetVersion failed to get the DRM version\n"); @@ -1774,41 +1822,48 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) #endif if (!info->r600_shadow_fb) { - info->tear_free = xf86ReturnOptValBool(info->Options, OPTION_TEAR_FREE, - FALSE); - - if (info->tear_free) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TearFree enabled\n"); - } + from = X_DEFAULT; - if (info->dri2.pKernelDRMVersion->version_minor >= 8) { - Bool sw_cursor = xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE); - - info->allowPageFlip = xf86ReturnOptValBool(info->Options, - OPTION_PAGE_FLIP, TRUE); + info->tear_free = 2; + if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE, + &info->tear_free)) + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n", + info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off")); + } + + if (!pScrn->is_gpu) { + if (info->dri2.pKernelDRMVersion->version_minor >= 8) { + Bool sw_cursor = xf86ReturnOptValBool(info->Options, + OPTION_SW_CURSOR, FALSE); + + info->allowPageFlip = xf86ReturnOptValBool(info->Options, + OPTION_PAGE_FLIP, TRUE); + + if (sw_cursor || info->shadow_primary) { + xf86DrvMsg(pScrn->scrnIndex, + info->allowPageFlip ? X_WARNING : X_DEFAULT, + "KMS Pageflipping: disabled%s\n", + info->allowPageFlip ? + (sw_cursor ? " because of SWcursor" : + " because of ShadowPrimary") : ""); + info->allowPageFlip = FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "KMS Pageflipping: %sabled\n", + info->allowPageFlip ? "en" : "dis"); + } + } - if (sw_cursor || info->tear_free || info->shadow_primary) { - xf86DrvMsg(pScrn->scrnIndex, - info->allowPageFlip ? X_WARNING : X_DEFAULT, - "KMS Pageflipping: disabled%s\n", - info->allowPageFlip ? - (sw_cursor ? " because of SWcursor" : - " because of ShadowPrimary/TearFree") : ""); - info->allowPageFlip = FALSE; - } else { + if (!info->use_glamor) { + info->swapBuffersWait = + xf86ReturnOptValBool(info->Options, OPTION_SWAPBUFFERS_WAIT, TRUE); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis"); + "SwapBuffers wait for vsync: %sabled\n", + info->swapBuffersWait ? "en" : "dis"); } } - if (!info->use_glamor) { - info->swapBuffersWait = - xf86ReturnOptValBool(info->Options, OPTION_SWAPBUFFERS_WAIT, TRUE); - 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; } @@ -1857,7 +1912,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) { struct drm_radeon_gem_info mminfo; - if (!drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) + if (!drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) { info->vram_size = mminfo.vram_visible; info->gart_size = mminfo.gart_size; @@ -1997,10 +2052,7 @@ static Bool RADEONSaveScreen_KMS(ScreenPtr pScreen, int mode) static Bool radeon_set_drm_master(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); -#ifdef XF86_PDEV_SERVER_FD RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); -#endif int err; #ifdef XF86_PDEV_SERVER_FD @@ -2009,7 +2061,7 @@ static Bool radeon_set_drm_master(ScrnInfoPtr pScrn) return TRUE; #endif - err = drmSetMaster(info->dri2.drm_fd); + err = drmSetMaster(pRADEONEnt->fd); if (err) ErrorF("Unable to retrieve master\n"); @@ -2018,23 +2070,22 @@ static Bool radeon_set_drm_master(ScrnInfoPtr pScrn) static void radeon_drop_drm_master(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); -#ifdef XF86_PDEV_SERVER_FD RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); +#ifdef XF86_PDEV_SERVER_FD if (pRADEONEnt->platform_dev && (pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) return; #endif - drmDropMaster(info->dri2.drm_fd); + drmDropMaster(pRADEONEnt->fd); } /* Called at the end of each server generation. Restore the original * text mode, unmap video memory, and unwrap and call the saved * CloseScreen function. */ -static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL) +static Bool RADEONCloseScreen_KMS(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); @@ -2078,13 +2129,12 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL) xf86ClearPrimInitDone(info->pEnt->index); pScreen->BlockHandler = info->BlockHandler; pScreen->CloseScreen = info->CloseScreen; - return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); + return pScreen->CloseScreen(pScreen); } -void RADEONFreeScreen_KMS(FREE_SCREEN_ARGS_DECL) +void RADEONFreeScreen_KMS(ScrnInfoPtr pScrn) { - SCRN_INFO_PTR(arg); RADEONInfoPtr info = RADEONPTR(pScrn); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, @@ -2096,9 +2146,10 @@ void RADEONFreeScreen_KMS(FREE_SCREEN_ARGS_DECL) RADEONFreeRec(pScrn); } -Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) +Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); int subPixelOrder = SubPixelUnknown; MessageType from; @@ -2123,9 +2174,9 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) if (info->r600_shadow_fb == FALSE) info->directRenderingEnabled = radeon_dri2_screen_init(pScreen); - info->surf_man = radeon_surface_manager_new(info->dri2.drm_fd); + info->surf_man = radeon_surface_manager_new(pRADEONEnt->fd); if (!info->bufmgr) - info->bufmgr = radeon_bo_manager_gem_ctor(info->dri2.drm_fd); + info->bufmgr = radeon_bo_manager_gem_ctor(pRADEONEnt->fd); if (!info->bufmgr) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to initialise GEM buffer manager"); @@ -2134,7 +2185,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr); if (!info->csm) - info->csm = radeon_cs_manager_gem_ctor(info->dri2.drm_fd); + info->csm = radeon_cs_manager_gem_ctor(pRADEONEnt->fd); if (!info->csm) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to initialise command submission manager"); @@ -2165,7 +2216,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) if (info->fb_shadow == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate shadow framebuffer\n"); - info->r600_shadow_fb = FALSE; + return FALSE; } else { if (!fbScreenInit(pScreen, info->fb_shadow, pScrn->virtualX, pScrn->virtualY, @@ -2214,33 +2265,35 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) } #endif - if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0)) - value = info->use_glamor; - else - value = FALSE; - from = X_DEFAULT; + if (!pScreen->isGPU) { + if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0)) + value = info->use_glamor; + else + value = FALSE; + from = X_DEFAULT; - if (!info->r600_shadow_fb) { - if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value)) - from = X_CONFIG; + if (!info->r600_shadow_fb) { + 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 (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) { + value = radeon_sync_init(pScreen) && + radeon_present_screen_init(pScreen) && + radeon_dri3_screen_init(pScreen); - if (!value) - from = X_WARNING; - } + if (!value) + from = X_WARNING; + } - xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis"); + xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis"); + } pScrn->vtSema = TRUE; xf86SetBackingStore(pScreen); @@ -2295,7 +2348,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) */ /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */ #endif - if (info->r600_shadow_fb == FALSE) { + if (info->r600_shadow_fb == FALSE && !pScreen->isGPU) { /* Init Xv */ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Initializing Xv\n"); @@ -2311,9 +2364,13 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) } pScrn->pScreen = pScreen; - if (serverGeneration == 1 && bgNoneRoot && info->accelOn) { - info->CreateWindow = pScreen->CreateWindow; - pScreen->CreateWindow = RADEONCreateWindow_oneshot; + if (!pScreen->isGPU) { + if (serverGeneration == 1 && bgNoneRoot && info->accelOn) { + info->CreateWindow = pScreen->CreateWindow; + pScreen->CreateWindow = RADEONCreateWindow_oneshot; + } + info->WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = RADEONWindowExposures_oneshot; } /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ @@ -2322,18 +2379,16 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) pScreen->CloseScreen = RADEONCloseScreen_KMS; pScreen->SaveScreen = RADEONSaveScreen_KMS; info->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = RADEONBlockHandler_oneshot; + pScreen->BlockHandler = RADEONBlockHandler_KMS; info->CreateScreenResources = pScreen->CreateScreenResources; pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS; -#ifdef RADEON_PIXMAP_SHARING pScreen->StartPixmapTracking = PixmapStartDirtyTracking; pScreen->StopPixmapTracking = PixmapStopDirtyTracking; #if HAS_SYNC_SHARED_PIXMAP pScreen->SyncSharedPixmap = radeon_sync_shared_pixmap; #endif -#endif if (!xf86CrtcScreenInit (pScreen)) return FALSE; @@ -2360,9 +2415,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL) return TRUE; } -Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL) +Bool RADEONEnterVT_KMS(ScrnInfoPtr pScrn) { - SCRN_INFO_PTR(arg); RADEONInfoPtr info = RADEONPTR(pScrn); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, @@ -2370,6 +2424,31 @@ Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL) radeon_set_drm_master(pScrn); + if (info->r600_shadow_fb) { + int base_align = drmmode_get_base_align(pScrn, info->pixel_bytes, 0); + struct radeon_bo *front_bo = radeon_bo_open(info->bufmgr, 0, + info->front_bo->size, + base_align, + RADEON_GEM_DOMAIN_VRAM, 0); + + if (front_bo) { + if (radeon_bo_map(front_bo, 1) == 0) { + memset(front_bo->ptr, 0, front_bo->size); + radeon_bo_unref(info->front_bo); + info->front_bo = front_bo; + } else { + radeon_bo_unref(front_bo); + front_bo = NULL; + } + } + + if (!front_bo) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to allocate new scanout BO after VT switch, " + "other DRM masters may see screen contents\n"); + } + } + info->accel_state->XInited3D = FALSE; info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; @@ -2381,21 +2460,137 @@ Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL) return TRUE; } +static +CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) +{ + ScreenPtr screen = data; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + if (xf86ScreenToScrn(radeon_master_screen(screen))->vtSema) + return 0; + + /* Unreference the all-black FB created by RADEONLeaveVT_KMS. After + * this, there should be no FB left created by this driver. + */ + for (c = 0; c < xf86_config->num_crtc; c++) { + drmmode_crtc_private_ptr drmmode_crtc = + xf86_config->crtc[c]->driver_private; + + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); + } + + return 0; +} + +static void +pixmap_unref_fb(void *value, XID id, void *cdata) +{ + PixmapPtr pixmap = value; + RADEONEntPtr pRADEONEnt = cdata; + struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pixmap); + + if (fb_ptr) + drmmode_fb_reference(pRADEONEnt->fd, fb_ptr, NULL); +} -void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL) +void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) { - SCRN_INFO_PTR(arg); RADEONInfoPtr info = RADEONPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONLeaveVT_KMS\n"); - radeon_drop_drm_master(pScrn); + if (!info->r600_shadow_fb) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + struct drmmode_scanout black_scanout = { .pixmap = NULL, .bo = NULL }; + xf86CrtcPtr crtc; + drmmode_crtc_private_ptr drmmode_crtc; + unsigned w = 0, h = 0; + int i; + + /* Compute maximum scanout dimensions of active CRTCs */ + for (i = 0; i < xf86_config->num_crtc; i++) { + crtc = xf86_config->crtc[i]; + drmmode_crtc = crtc->driver_private; + + if (!drmmode_crtc->fb) + continue; + + w = max(w, crtc->mode.HDisplay); + h = max(h, crtc->mode.VDisplay); + } + + /* Make all active CRTCs scan out from an all-black framebuffer */ + if (w > 0 && h > 0) { + if (drmmode_crtc_scanout_create(crtc, &black_scanout, w, h)) { + struct drmmode_fb *black_fb = + radeon_pixmap_get_fb(black_scanout.pixmap); + + radeon_pixmap_clear(black_scanout.pixmap); + radeon_cs_flush_indirect(pScrn); + radeon_bo_wait(black_scanout.bo); - xf86RotateFreeShadow(pScrn); - drmmode_scanout_free(pScrn); + for (i = 0; i < xf86_config->num_crtc; i++) { + crtc = xf86_config->crtc[i]; + drmmode_crtc = crtc->driver_private; + + if (drmmode_crtc->fb) { + if (black_fb) { + drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0); + } else { + drmModeSetCrtc(pRADEONEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, 0, + 0, 0, NULL, 0, NULL); + drmmode_fb_reference(pRADEONEnt->fd, + &drmmode_crtc->fb, NULL); + } + + if (pScrn->is_gpu) { + if (drmmode_crtc->scanout[0].pixmap) + pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap, + None, pRADEONEnt); + if (drmmode_crtc->scanout[1].pixmap) + pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, + None, pRADEONEnt); + } else { + drmmode_crtc_scanout_free(drmmode_crtc); + } + } + } + } + } + + xf86RotateFreeShadow(pScrn); + drmmode_crtc_scanout_destroy(&info->drmmode, &black_scanout); + + /* Unreference FBs of all pixmaps. After this, the only FB remaining + * should be the all-black one being scanned out by active CRTCs + */ + for (i = 0; i < currentMaxClients; i++) { + if (i > 0 && + (!clients[i] || clients[i]->clientState != ClientStateRunning)) + continue; + + FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb, + pRADEONEnt); + } + + pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pRADEONEnt); + } else { + memset(info->front_bo->ptr, 0, info->front_bo->size); + } + + TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); xf86_hide_cursors (pScrn); + + radeon_drop_drm_master(pScrn); + info->accel_state->XInited3D = FALSE; info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; @@ -2404,18 +2599,16 @@ void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL) } -Bool RADEONSwitchMode_KMS(SWITCH_MODE_ARGS_DECL) +Bool RADEONSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode) { - SCRN_INFO_PTR(arg); Bool ret; ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0); return ret; } -void RADEONAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL) +void RADEONAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y) { - SCRN_INFO_PTR(arg); RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_adjust_frame(pScrn, &info->drmmode, x, y); return; @@ -2608,10 +2801,9 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size) } /* Used to disallow modes that are not supported by the hardware */ -ModeStatus RADEONValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, +ModeStatus RADEONValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool verbose, int flag) { - SCRN_INFO_PTR(arg); RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); diff --git a/src/radeon_list.h b/src/radeon_list.h deleted file mode 100644 index a0038c96..00000000 --- a/src/radeon_list.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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_is_empty list_is_empty -#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/src/radeon_present.c b/src/radeon_present.c index 29800fec..176853d9 100644 --- a/src/radeon_present.c +++ b/src/radeon_present.c @@ -48,21 +48,14 @@ #include "present.h" +static present_screen_info_rec radeon_present_screen_info; + struct radeon_present_vblank_event { uint64_t event_id; + Bool vblank_for_flip; Bool unflip; }; -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) { @@ -103,10 +96,11 @@ static Bool radeon_present_flush_drm_events(ScreenPtr screen) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 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 }; + struct pollfd p = { .fd = pRADEONEnt->fd, .events = POLLIN }; int r; do { @@ -116,7 +110,7 @@ radeon_present_flush_drm_events(ScreenPtr screen) if (r <= 0) return 0; - return drmHandleEvent(drmmode->fd, &drmmode->event_context) >= 0; + return drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) >= 0; } /* @@ -126,9 +120,26 @@ static void radeon_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc, uint64_t usec, void *data) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; struct radeon_present_vblank_event *event = data; - present_event_notify(event->event_id, usec, msc); + if (event->vblank_for_flip && + drmmode_crtc->tear_free && + drmmode_crtc->scanout_update_pending) { + if (drmmode_crtc->present_vblank_event_id != 0) { + xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING, + "Need to handle previously deferred vblank event\n"); + present_event_notify(drmmode_crtc->present_vblank_event_id, + drmmode_crtc->present_vblank_usec, + drmmode_crtc->present_vblank_msc); + } + + drmmode_crtc->present_vblank_event_id = event->event_id; + drmmode_crtc->present_vblank_msc = msc; + drmmode_crtc->present_vblank_usec = usec; + } else + present_event_notify(event->event_id, usec, msc); + free(event); } @@ -151,19 +162,18 @@ static int radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) { xf86CrtcPtr xf86_crtc = crtc->devPrivate; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 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; uintptr_t drm_queue_seq; - drmVBlank vbl; - int ret; event = calloc(sizeof(struct radeon_present_vblank_event), 1); if (!event) return BadAlloc; event->event_id = event_id; + event->vblank_for_flip = drmmode_crtc->present_flip_expected; + drmmode_crtc->present_flip_expected = FALSE; + drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, event_id, event, @@ -174,12 +184,10 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) return BadAlloc; } - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id); - vbl.request.sequence = msc; - vbl.request.signal = drm_queue_seq; for (;;) { - ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); - if (!ret) + if (drmmode_wait_vblank(xf86_crtc, + DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, msc, + drm_queue_seq, NULL, NULL)) break; if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) { radeon_drm_abort_entry(drm_queue_seq); @@ -240,17 +248,17 @@ radeon_present_check_unflip(ScrnInfoPtr scrn) 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; + xf86CrtcPtr crtc = config->crtc[i]; - if (!config->crtc[i]->enabled) - continue; + if (drmmode_crtc_can_flip(crtc)) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - if (!drmmode_crtc || drmmode_crtc->rotate.bo || - drmmode_crtc->scanout[0].bo) - return FALSE; + if (drmmode_crtc->flip_pending) + return FALSE; - if (drmmode_crtc->pending_dpms_mode == DPMSModeOn) - num_crtcs_on++; + if (!drmmode_crtc->tear_free) + num_crtcs_on++; + } } return num_crtcs_on > 0; @@ -263,10 +271,20 @@ static Bool radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip) { + xf86CrtcPtr xf86_crtc = crtc->devPrivate; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; ScreenPtr screen = window->drawable.pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + ScrnInfoPtr scrn = xf86_crtc->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); RADEONInfoPtr info = RADEONPTR(scrn); PixmapPtr screen_pixmap; + int num_crtcs_on; + int i; + + drmmode_crtc->present_flip_expected = FALSE; + + if (!scrn->vtSema) + return FALSE; if (!info->allowPageFlip) return FALSE; @@ -285,7 +303,18 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) return FALSE; - return radeon_present_check_unflip(scrn); + for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { + if (drmmode_crtc_can_flip(config->crtc[i])) + num_crtcs_on++; + else if (config->crtc[i] == crtc->devPrivate) + return FALSE; + } + + if (num_crtcs_on == 0) + return FALSE; + + drmmode_crtc->present_flip_expected = TRUE; + return TRUE; } /* @@ -324,29 +353,27 @@ static Bool radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, PixmapPtr pixmap, Bool sync_flip) { + xf86CrtcPtr xf86_crtc = crtc->devPrivate; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; ScreenPtr screen = crtc->pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + ScrnInfoPtr scrn = xf86_crtc->scrn; 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; + Bool ret = FALSE; if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) - return FALSE; - - if (!radeon_get_pixmap_handle(pixmap, &handle)) - return FALSE; + goto out; event = calloc(1, sizeof(struct radeon_present_vblank_event)); if (!event) - return FALSE; + goto out; event->event_id = event_id; - ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, - event_id, event, crtc_id, + radeon_cs_flush_indirect(scrn); + + ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap, + event_id, event, crtc->devPrivate, radeon_present_flip_event, radeon_present_flip_abort, sync_flip ? FLIP_VSYNC : FLIP_ASYNC, @@ -356,6 +383,8 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, else info->drmmode.present_flipping = TRUE; + out: + drmmode_crtc->present_flip_expected = FALSE; return ret; } @@ -370,17 +399,15 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id) xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); struct radeon_present_vblank_event *event; PixmapPtr pixmap = screen->GetScreenPixmap(screen); - uint32_t handle; + enum drmmode_flip_sync flip_sync = + (radeon_present_screen_info.capabilities & PresentCapabilityAsync) ? + FLIP_ASYNC : FLIP_VSYNC; int i; - if (!radeon_present_check_unflip(scrn)) - goto modeset; + radeon_cs_flush_indirect(scrn); - if (!radeon_get_pixmap_handle(pixmap, &handle)) { - ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n", - __func__); + if (!radeon_present_check_unflip(scrn)) goto modeset; - } event = calloc(1, sizeof(struct radeon_present_vblank_event)); if (!event) { @@ -391,26 +418,21 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id) event->event_id = event_id; event->unflip = TRUE; - if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, - event_id, event, -1, radeon_present_flip_event, - radeon_present_flip_abort, FLIP_VSYNC, 0)) + if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap, + event_id, event, NULL, radeon_present_flip_event, + radeon_present_flip_abort, flip_sync, 0)) return; modeset: - /* info->drmmode.fb_id still points to the FB for the last flipped BO. - * Clear it, drmmode_set_mode_major will re-create it - */ - drmModeRmFB(info->drmmode.fd, info->drmmode.fb_id); - info->drmmode.fb_id = 0; - + radeon_bo_wait(info->front_bo); 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) + if (!crtc->enabled || drmmode_crtc->tear_free) continue; - if (drmmode_crtc->pending_dpms_mode == DPMSModeOn) + if (drmmode_crtc->dpms_mode == DPMSModeOn) crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); else @@ -442,11 +464,11 @@ radeon_present_has_async_flip(ScreenPtr screen) { #ifdef DRM_CAP_ASYNC_PAGE_FLIP ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONInfoPtr info = RADEONPTR(scrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); int ret; uint64_t value; - ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); + ret = drmGetCap(pRADEONEnt->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); if (ret == 0) return value == 1; #endif diff --git a/src/radeon_probe.c b/src/radeon_probe.c index aaace2b5..19295f00 100644 --- a/src/radeon_probe.c +++ b/src/radeon_probe.c @@ -48,7 +48,12 @@ #include "xf86.h" #include "xf86drmMode.h" + +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,19,99,1,0) +#include <xf86Pci.h> +#else #include "dri.h" +#endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include <xf86_OSproc.h> diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 9e50c811..be82f9ae 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -151,13 +151,13 @@ typedef struct extern const OptionInfoRec *RADEONOptionsWeak(void); extern Bool RADEONPreInit_KMS(ScrnInfoPtr, int); -extern Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL); -extern Bool RADEONSwitchMode_KMS(SWITCH_MODE_ARGS_DECL); -extern void RADEONAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL); -extern Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL); -extern void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL); -extern void RADEONFreeScreen_KMS(FREE_SCREEN_ARGS_DECL); +extern Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv); +extern Bool RADEONSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode); +extern void RADEONAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y); +extern Bool RADEONEnterVT_KMS(ScrnInfoPtr pScrn); +extern void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn); +extern void RADEONFreeScreen_KMS(ScrnInfoPtr pScrn); -extern ModeStatus RADEONValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, - Bool verbose, int flag); +extern ModeStatus RADEONValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, + Bool verbose, int flag); #endif /* _RADEON_PROBE_H_ */ diff --git a/src/radeon_video.c b/src/radeon_video.c index d058986a..e08d8e00 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -71,7 +71,7 @@ radeon_box_area(BoxPtr box) Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - return drmmode_crtc->pending_dpms_mode == DPMSModeOn; + return drmmode_crtc->dpms_mode == DPMSModeOn; } xf86CrtcPtr |