Module Name:    xsrc
Committed By:   mrg
Date:           Sun Mar 11 19:44:00 UTC 2018

Modified Files:
        xsrc/external/mit/xf86-video-ati-kms/dist/src: radeon_kms.c
        xsrc/external/mit/xf86-video-ati-kms/include: config.h
Removed Files:
        xsrc/external/mit/xf86-video-ati-kms/dist/src: radeon_list.h

Log Message:
merge xf86-video-ati 18.0.0.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 \
    xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_kms.c
cvs rdiff -u -r1.1.1.1 -r0 \
    xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_list.h
cvs rdiff -u -r1.5 -r1.6 \
    xsrc/external/mit/xf86-video-ati-kms/include/config.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_kms.c
diff -u xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_kms.c:1.5 xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_kms.c:1.6
--- xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_kms.c:1.5	Tue Aug 29 04:43:42 2017
+++ xsrc/external/mit/xf86-video-ati-kms/dist/src/radeon_kms.c	Sun Mar 11 19:43:59 2018
@@ -32,11 +32,13 @@
 #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"
 #include "radeon_probe.h"
 #include "micmap.h"
+#include "mipointrst.h"
 
 #include "radeon_version.h"
 #include "shadow.h"
@@ -44,6 +46,10 @@
 
 #include "atipciids.h"
 
+#if HAVE_PRESENT_H
+#include <present.h>
+#endif
+
 /* DPMS */
 #ifdef HAVE_XEXTPROTO_71
 #include <X11/extensions/dpmsconst.h>
@@ -61,6 +67,7 @@
 #include "radeon_vbo.h"
 
 static DevScreenPrivateKeyRec radeon_client_private_key;
+DevScreenPrivateKeyRec radeon_device_private_key;
 
 extern SymTabRec RADEONChipsets[];
 static Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
@@ -187,16 +194,34 @@ static Bool RADEONGetRec(ScrnInfoPtr pSc
 /* Free our private RADEONInfoRec */
 static void RADEONFreeRec(ScrnInfoPtr pScrn)
 {
+    DevUnion *pPriv;
+    RADEONEntPtr pRADEONEnt;
     RADEONInfoPtr  info;
+    EntityInfoPtr pEnt;
 
-    if (!pScrn || !pScrn->driverPrivate) return;
+    if (!pScrn)
+	return;
 
     info = RADEONPTR(pScrn);
+    if (info) {
+	if (info->fbcon_pixmap)
+	    pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+
+	if (info->accel_state) {
+	    free(info->accel_state);
+	    info->accel_state = NULL;
+	}
 
-    if (info->fbcon_pixmap)
-	pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+	pEnt = info->pEnt;
+	free(pScrn->driverPrivate);
+	pScrn->driverPrivate = NULL;
+    } else {
+	pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
+    }
 
-    if (info->dri2.drm_fd > 0) {
+    pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex);
+    pRADEONEnt = pPriv->ptr;
+    if (pRADEONEnt->fd > 0) {
         DevUnion *pPriv;
         RADEONEntPtr pRADEONEnt;
         pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
@@ -210,17 +235,12 @@ static void RADEONFreeRec(ScrnInfoPtr pS
                     pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
 #endif
                 drmClose(pRADEONEnt->fd);
-            pRADEONEnt->fd = 0;
+            free(pPriv->ptr);
+            pPriv->ptr = NULL;
         }
     }
 
-    if (info->accel_state) {
-	free(info->accel_state);
-	info->accel_state = NULL;
-    }
-
-    free(pScrn->driverPrivate);
-    pScrn->driverPrivate = NULL;
+    free(pEnt);
 }
 
 static void *
@@ -317,9 +337,7 @@ static Bool RADEONCreateScreenResources_
     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,8 +346,7 @@ static Bool RADEONCreateScreenResources_
 	}
     }
 
-    if (!drmmode_set_desired_modes(pScrn, &info->drmmode,
-				   radeon_is_gpu_screen(pScreen)))
+    if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU))
 	return FALSE;
 
     drmmode_uevent_init(pScrn, &info->drmmode);
@@ -358,8 +375,7 @@ static Bool RADEONCreateScreenResources_
 	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))
@@ -384,15 +400,12 @@ static Bool RADEONCreateScreenResources_
 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;
@@ -408,8 +421,6 @@ radeon_scanout_extents_intersect(xf86Crt
     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)
@@ -448,8 +459,6 @@ transform_region(RegionPtr region, struc
 	return transformed;
 }
 
-#endif
-
 static void
 radeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
 			    int scanout_id)
@@ -479,14 +488,11 @@ radeon_sync_scanout_pixmaps(xf86CrtcPtr 
     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);
     }
@@ -511,7 +517,38 @@ radeon_sync_scanout_pixmaps(xf86CrtcPtr 
     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)
@@ -543,7 +580,8 @@ dirty_region(PixmapDirtyUpdatePtr dirty)
 static void
 redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
 {
-	ScrnInfoPtr pScrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
+	ScrnInfoPtr src_scrn =
+		xf86ScreenToScrn(radeon_dirty_src_drawable(dirty)->pScreen);
 
 	if (RegionNil(region))
 		goto out;
@@ -557,7 +595,7 @@ redisplay_dirty(PixmapDirtyUpdatePtr dir
 	PixmapSyncDirtyHelper(dirty, region);
 #endif
 
-	radeon_cs_flush_indirect(pScrn);
+	radeon_cs_flush_indirect(src_scrn);
 	if (dirty->slave_dst->master_pixmap)
 	    DamageRegionProcessPending(&dirty->slave_dst->drawable);
 
@@ -576,12 +614,12 @@ radeon_prime_scanout_update_abort(xf86Cr
 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);
@@ -596,7 +634,7 @@ radeon_sync_shared_pixmap(PixmapDirtyUpd
 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;
 }
@@ -612,7 +650,7 @@ slave_has_sync_shared_pixmap(ScrnInfoPtr
 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);
 }
@@ -622,7 +660,7 @@ call_sync_shared_pixmap(PixmapDirtyUpdat
 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;
 }
@@ -657,8 +695,7 @@ radeon_prime_dirty_to_crtc(PixmapDirtyUp
 	xf86CrtcPtr xf86_crtc = xf86_config->crtc[c];
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 
-	if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst ||
-	    drmmode_crtc->scanout[1].pixmap == dirty->slave_dst)
+	if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap))
 	    return xf86_crtc;
     }
 
@@ -671,13 +708,11 @@ radeon_prime_scanout_do_update(xf86CrtcP
     ScrnInfoPtr scrn = crtc->scrn;
     ScreenPtr screen = scrn->pScreen;
     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 ^ drmmode_crtc->tear_free].pixmap) {
+	if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
 	    RegionPtr region;
 
 	    if (master_has_sync_shared_pixmap(scrn, dirty))
@@ -725,15 +760,14 @@ radeon_prime_scanout_update(PixmapDirtyU
     xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty);
     drmmode_crtc_private_ptr drmmode_crtc;
     uintptr_t drm_queue_seq;
-    drmVBlank vbl;
 
     if (!xf86_crtc || !xf86_crtc->enabled)
 	return;
 
     drmmode_crtc = xf86_crtc->driver_private;
     if (drmmode_crtc->scanout_update_pending ||
-	!drmmode_crtc->scanout[0].pixmap ||
-	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+	!drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
+	drmmode_crtc->dpms_mode != DPMSModeOn)
 	return;
 
     drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
@@ -747,13 +781,10 @@ radeon_prime_scanout_update(PixmapDirtyU
 	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;
@@ -763,15 +794,6 @@ radeon_prime_scanout_update(PixmapDirtyU
 }
 
 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;
@@ -788,7 +810,7 @@ radeon_prime_scanout_flip(PixmapDirtyUpd
     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;
@@ -798,16 +820,26 @@ radeon_prime_scanout_flip(PixmapDirtyUpd
     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));
@@ -817,7 +849,6 @@ radeon_prime_scanout_flip(PixmapDirtyUpd
 
     drmmode_crtc->scanout_id = scanout_id;
     drmmode_crtc->scanout_update_pending = TRUE;
-    drmmode_crtc->flip_pending = TRUE;
 }
 
 static void
@@ -832,10 +863,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;
 				}
 			}
@@ -868,54 +899,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->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 (drmmode_crtc->tear_free) {
-	radeon_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
-	RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
+	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");
@@ -943,9 +965,9 @@ radeon_scanout_do_update(xf86CrtcPtr xf8
 	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:
@@ -954,16 +976,14 @@ radeon_scanout_do_update(xf86CrtcPtr xf8
 	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);
     }
 
@@ -986,7 +1006,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);
 }
@@ -997,15 +1028,14 @@ radeon_scanout_update(xf86CrtcPtr xf86_c
     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;
@@ -1035,13 +1065,10 @@ radeon_scanout_update(xf86CrtcPtr xf86_c
 	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;
@@ -1051,36 +1078,33 @@ radeon_scanout_update(xf86CrtcPtr xf86_c
 }
 
 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 ||
-	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+	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,
@@ -1088,23 +1112,38 @@ radeon_scanout_flip(ScreenPtr pScreen, R
 	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);
@@ -1114,7 +1153,10 @@ static void RADEONBlockHandler_KMS(BLOCK
     (*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++) {
 	    xf86CrtcPtr crtc = xf86_config->crtc[c];
@@ -1122,25 +1164,19 @@ static void RADEONBlockHandler_KMS(BLOCK
 
 	    if (drmmode_crtc->tear_free)
 		radeon_scanout_flip(pScreen, info, crtc);
-	    else if (info->shadow_primary
-#if XF86_CRTC_VERSION >= 4
-		     || crtc->driverIsPerformingTransform
-#endif
-		)
+	    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 Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
 {
-    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     struct drm_radeon_info ginfo;
     int r;
     uint32_t tmp = 0;
@@ -1148,7 +1184,7 @@ static Bool RADEONIsFastFBWorking(ScrnIn
     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;
     }
@@ -1159,7 +1195,7 @@ static Bool RADEONIsFastFBWorking(ScrnIn
 
 static Bool RADEONIsFusionGARTWorking(ScrnInfoPtr pScrn)
 {
-    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     struct drm_radeon_info ginfo;
     int r;
     uint32_t tmp;
@@ -1167,7 +1203,7 @@ static Bool RADEONIsFusionGARTWorking(Sc
     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;
     }
@@ -1178,6 +1214,7 @@ static Bool RADEONIsFusionGARTWorking(Sc
 
 static Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn)
 {
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct drm_radeon_info ginfo;
     int r;
@@ -1189,7 +1226,7 @@ static Bool RADEONIsAccelWorking(ScrnInf
     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) {
@@ -1221,6 +1258,7 @@ static Bool RADEONPreInitVisual(ScrnInfo
     case 15:
     case 16:
     case 24:
+    case 30:
 	break;
 
     default:
@@ -1307,9 +1345,10 @@ static Bool RADEONPreInitAccel_KMS(ScrnI
 	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;
     }
 
@@ -1427,7 +1466,6 @@ static int radeon_get_drm_master_fd(Scrn
 
 static Bool radeon_open_drm_master(ScrnInfoPtr pScrn)
 {
-    RADEONInfoPtr  info   = RADEONPTR(pScrn);
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     drmSetVersion sv;
     int err;
@@ -1435,14 +1473,12 @@ static Bool radeon_open_drm_master(ScrnI
     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,
@@ -1453,24 +1489,23 @@ static Bool radeon_open_drm_master(ScrnI
     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;
@@ -1482,7 +1517,7 @@ static Bool r600_get_tile_config(ScrnInf
     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;
 
@@ -1578,7 +1613,7 @@ static Bool r600_get_tile_config(ScrnInf
 
 static void RADEONSetupCapabilities(ScrnInfoPtr pScrn)
 {
-#ifdef RADEON_PIXMAP_SHARING
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     RADEONInfoPtr  info = RADEONPTR(pScrn);
     uint64_t value;
     int ret;
@@ -1589,7 +1624,7 @@ static void RADEONSetupCapabilities(Scrn
     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;
@@ -1599,7 +1634,6 @@ static void RADEONSetupCapabilities(Scrn
 		pScrn->capabilities |= RR_Capability_SinkOutput;
 	}
     }
-#endif
 }
 
 /* When the root window is created, initialize the screen contents from
@@ -1627,11 +1661,11 @@ static Bool RADEONCreateWindow_oneshot(W
 }
 
 /* When the root window is mapped, set the initial modes */
-static void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
+void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
-					  , RegionPtr pBSRegion
+				   , RegionPtr pBSRegion
 #endif
-    )
+				   )
 {
     ScreenPtr pScreen = pWin->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
@@ -1678,7 +1712,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
         && info->pEnt->location.type != BUS_PLATFORM
 #endif
         )
-        goto fail;
+        return FALSE;
 
     pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
 				 getRADEONEntityIndex());
@@ -1705,40 +1739,48 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
     pScrn->monitor     = pScrn->confScreen->monitor;
 
     if (!RADEONPreInitVisual(pScrn))
-	goto fail;
+	return FALSE;
 
     xf86CollectOptions(pScrn, NULL);
     if (!(info->Options = malloc(sizeof(RADEONOptions_KMS))))
-	goto fail;
+	return FALSE;
 
     memcpy(info->Options, RADEONOptions_KMS, sizeof(RADEONOptions_KMS));
     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
 
     if (!RADEONPreInitWeight(pScrn))
-	goto fail;
+	return FALSE;
 
     if (!RADEONPreInitChipType_KMS(pScrn))
-        goto fail;
+        return FALSE;
 
     if (radeon_open_drm_master(pScrn) == FALSE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
-	goto fail;
+	return FALSE;
     }
 
     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");
-	goto fail;
+	return FALSE;
     }
 
     /* Get ScreenInit function */
     if (!xf86LoadSubModule(pScrn, "fb"))
 	return FALSE;
 
-    if (!RADEONPreInitAccel_KMS(pScrn))              goto fail;
+    if (!RADEONPreInitAccel_KMS(pScrn))
+	return FALSE;
+
+    /* Depth 30 only supported since Linux 3.16 / kms driver minor version 39 */
+    if (pScrn->depth == 30 && info->dri2.pKernelDRMVersion->version_minor < 39) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Depth 30 is not supported. Kernel too old. Needs Linux 3.16+\n");
+	return FALSE;
+    }
 
     radeon_drm_queue_init();
 
@@ -1812,7 +1854,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
 		   info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off"));
     }
 
-    if (!radeon_is_gpu_scrn(pScrn)) {
+    if (!pScrn->is_gpu) {
 	if (info->dri2.pKernelDRMVersion->version_minor >= 8) {
 	    Bool sw_cursor = xf86ReturnOptValBool(info->Options,
 						  OPTION_SW_CURSOR, FALSE);
@@ -1850,7 +1892,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
 
     if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
-	goto fail;
+	return FALSE;
     }
 
     RADEONSetupCapabilities(pScrn);
@@ -1892,7 +1934,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
     {
 	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;
@@ -1944,14 +1986,10 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn
 #endif
         ) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
-      goto fail;
-   }
+      return FALSE;
+    }
 
     return TRUE;
- fail:
-    RADEONFreeRec(pScrn);
-    return FALSE;
-
 }
 
 static Bool RADEONCursorInit_KMS(ScreenPtr pScreen)
@@ -1959,12 +1997,48 @@ static Bool RADEONCursorInit_KMS(ScreenP
     ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr  info  = RADEONPTR(pScrn);
 
-    return xf86_cursors_init (pScreen, info->cursor_w, info->cursor_h,
-			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
-			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
-			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
-			       HARDWARE_CURSOR_UPDATE_UNHIDDEN |
-			       HARDWARE_CURSOR_ARGB));
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Initializing Cursor\n");
+
+    /* Set Silken Mouse */
+    xf86SetSilkenMouse(pScreen);
+
+    /* Cursor setup */
+    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+    if (info->allowPageFlip) {
+	miPointerScreenPtr PointPriv =
+	    dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
+
+	if (!dixRegisterScreenPrivateKey(&radeon_device_private_key, pScreen,
+					 PRIVATE_DEVICE,
+					 sizeof(struct radeon_device_priv))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n");
+	    return FALSE;
+	}
+
+	if (PointPriv->spriteFuncs->SetCursor != drmmode_sprite_set_cursor) {
+	    info->SetCursor = PointPriv->spriteFuncs->SetCursor;
+	    info->MoveCursor = PointPriv->spriteFuncs->MoveCursor;
+	    PointPriv->spriteFuncs->SetCursor = drmmode_sprite_set_cursor;
+	    PointPriv->spriteFuncs->MoveCursor = drmmode_sprite_move_cursor;
+	}
+    }
+
+    if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
+	return TRUE;
+
+    if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h,
+			   HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+			   HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+			   HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
+			   HARDWARE_CURSOR_UPDATE_UNHIDDEN |
+			   HARDWARE_CURSOR_ARGB)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n");
+	return FALSE;
+    }
+
+    return TRUE;
 }
 
 void
@@ -2032,10 +2106,7 @@ static Bool RADEONSaveScreen_KMS(ScreenP
 
 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
@@ -2044,7 +2115,7 @@ static Bool radeon_set_drm_master(ScrnIn
         return TRUE;
 #endif
 
-    err = drmSetMaster(info->dri2.drm_fd);
+    err = drmSetMaster(pRADEONEnt->fd);
     if (err)
         ErrorF("Unable to retrieve master\n");
 
@@ -2053,23 +2124,22 @@ static Bool radeon_set_drm_master(ScrnIn
 
 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);
@@ -2111,29 +2181,35 @@ static Bool RADEONCloseScreen_KMS(CLOSE_
 
     pScrn->vtSema = FALSE;
     xf86ClearPrimInitDone(info->pEnt->index);
+
+    if (info->allowPageFlip) {
+	miPointerScreenPtr PointPriv =
+	    dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
+
+	if (PointPriv->spriteFuncs->SetCursor == drmmode_sprite_set_cursor) {
+	    PointPriv->spriteFuncs->SetCursor = info->SetCursor;
+	    PointPriv->spriteFuncs->MoveCursor = info->MoveCursor;
+	}
+    }
+
     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,
 		   "RADEONFreeScreen\n");
 
-    /* when server quits at PreInit, we don't need do this anymore*/
-    if (!info) return;
-
     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;
@@ -2158,9 +2234,9 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
     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");
@@ -2169,7 +2245,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
     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");
@@ -2200,7 +2276,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
 	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,
@@ -2249,7 +2325,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
     }
 #endif
 
-    if (!radeon_is_gpu_screen(pScreen)) {
+    if (!pScreen->isGPU) {
 	if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0))
 	    value = info->use_glamor;
 	else
@@ -2311,19 +2387,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
 		   "Initializing DPMS\n");
     xf86DPMSInit(pScreen, xf86DPMSSet, 0);
 
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Initializing Cursor\n");
-
-    /* Set Silken Mouse */
-    xf86SetSilkenMouse(pScreen);
-
-    /* Cursor setup */
-    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
-
-    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
-	if (RADEONCursorInit_KMS(pScreen)) {
-	}
-    }
+    if (!RADEONCursorInit_KMS(pScreen))
+	return FALSE;
 
     /* DGA setup */
 #ifdef XFreeXDGA
@@ -2332,8 +2397,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
      */
     /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
 #endif
-    if (info->r600_shadow_fb == FALSE &&
-	!radeon_is_gpu_screen(pScreen)) {
+    if (info->r600_shadow_fb == FALSE && !pScreen->isGPU) {
         /* Init Xv */
         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
                        "Initializing Xv\n");
@@ -2349,7 +2413,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
     }
     pScrn->pScreen = pScreen;
 
-    if (!radeon_is_gpu_screen(pScreen)) {
+    if (!pScreen->isGPU) {
 	if (serverGeneration == 1 && bgNoneRoot && info->accelOn) {
 	    info->CreateWindow = pScreen->CreateWindow;
 	    pScreen->CreateWindow = RADEONCreateWindow_oneshot;
@@ -2369,13 +2433,11 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
     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;
@@ -2402,9 +2464,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_AR
     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,
@@ -2412,6 +2473,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;
 
@@ -2423,21 +2509,138 @@ 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);
+    }
 
-void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL)
+    TimerFree(timer);
+    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(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);
+
+		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);
 
-    xf86RotateFreeShadow(pScrn);
-    drmmode_scanout_free(pScrn);
+	/* 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;
 
@@ -2446,18 +2649,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;
@@ -2650,10 +2851,9 @@ void radeon_kms_update_vram_limit(ScrnIn
 }
 
 /* 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);
 

Index: xsrc/external/mit/xf86-video-ati-kms/include/config.h
diff -u xsrc/external/mit/xf86-video-ati-kms/include/config.h:1.5 xsrc/external/mit/xf86-video-ati-kms/include/config.h:1.6
--- xsrc/external/mit/xf86-video-ati-kms/include/config.h:1.5	Tue Aug 29 04:43:42 2017
+++ xsrc/external/mit/xf86-video-ati-kms/include/config.h	Sun Mar 11 19:44:00 2018
@@ -70,9 +70,6 @@
 /* Have xf86CursorResetCursor API */
 #undef HAVE_XF86_CURSOR_RESET_CURSOR
 
-/* Have xorg_list API */
-/* #undef HAVE_XORG_LIST */
-
 /* Define to the sub-directory where libtool stores uninstalled libraries. */
 #define LT_OBJDIR ".libs/"
 
@@ -89,7 +86,7 @@
 #define PACKAGE_NAME "xf86-video-ati"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "xf86-video-ati 7.9.0"
+#define PACKAGE_STRING "xf86-video-ati 18.0.0"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "xf86-video-ati"
@@ -98,13 +95,13 @@
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "7.9.0"
+#define PACKAGE_VERSION "18.0.0"
 
 /* Major version of this package */
-#define PACKAGE_VERSION_MAJOR 7
+#define PACKAGE_VERSION_MAJOR 18
 
 /* Minor version of this package */
-#define PACKAGE_VERSION_MINOR 9
+#define PACKAGE_VERSION_MINOR 0
 
 /* Patch version of this package */
 #define PACKAGE_VERSION_PATCHLEVEL 0
@@ -119,7 +116,7 @@
 #define USE_SYS_ENDIAN_H 1
 
 /* Version number of package */
-#define VERSION "7.9.0"
+#define VERSION "18.0.0"
 
 /* Enable large inode numbers on Mac OS X 10.5.  */
 #ifndef _DARWIN_USE_64_BIT_INODE

Reply via email to