summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/compat-api.h70
-rw-r--r--src/drmmode_display.c1127
-rw-r--r--src/drmmode_display.h103
-rw-r--r--src/evergreen_exa.c2
-rw-r--r--src/r600_exa.c2
-rw-r--r--src/radeon.h137
-rw-r--r--src/radeon_accel.c4
-rw-r--r--src/radeon_bo_helper.c42
-rw-r--r--src/radeon_bo_helper.h4
-rw-r--r--src/radeon_dri2.c243
-rw-r--r--src/radeon_dri2.h1
-rw-r--r--src/radeon_dri3.c3
-rw-r--r--src/radeon_drm_queue.c5
-rw-r--r--src/radeon_exa.c4
-rw-r--r--src/radeon_exa_funcs.c2
-rw-r--r--src/radeon_glamor.c18
-rw-r--r--src/radeon_glamor.h4
-rw-r--r--src/radeon_glamor_wrappers.c4
-rw-r--r--src/radeon_kms.c742
-rw-r--r--src/radeon_list.h40
-rw-r--r--src/radeon_present.c152
-rw-r--r--src/radeon_probe.c5
-rw-r--r--src/radeon_probe.h16
-rw-r--r--src/radeon_video.c2
25 files changed, 1573 insertions, 1160 deletions
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, &region, &box, 0);
- radeon_dri2_copy_region(drawable, &region, event->front, event->back);
+ radeon_dri2_copy_region2(drawable->pScreen, drawable, &region,
+ 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, &region, &box, 0);
- radeon_dri2_copy_region(draw, &region, front, back);
+ radeon_dri2_copy_region2(draw->pScreen, draw, &region, 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, &region, scanout_id);
+ RegionCopy(&drmmode_crtc->scanout_last_region, &region);
}
- 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),
+ &region->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),
+ &region->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