Blob Blame History Raw
diff --git a/src/ati.c b/src/ati.c
index e1c136f..256fbd8 100644
--- a/src/ati.c
+++ b/src/ati.c
@@ -102,6 +102,7 @@ ati_device_get_from_busid(int bus, int dev, int func)
                                    func);
 }
 
+#ifndef XSERVER_PLATFORM_BUS
 static struct pci_device*
 ati_device_get_primary(void)
 {
@@ -119,6 +120,26 @@ ati_device_get_primary(void)
 
     return device;
 }
+#else
+static struct pci_device *
+ati_device_get_indexed(int index)
+{
+    struct pci_device *device = NULL;
+    struct pci_device_iterator *device_iter;
+    int count = 0;
+
+    device_iter = pci_slot_match_iterator_create(NULL);
+
+    while ((device = pci_device_next(device_iter)) != NULL) {
+        if (device->vendor_id == PCI_VENDOR_ATI) {
+            if (count == index)
+                return device;
+            count++;
+        }
+    }
+    return NULL;
+}
+#endif
 
 #else /* XSERVER_LIBPCIACCESS */
 
@@ -197,9 +218,14 @@ ati_gdev_subdriver(pointer options)
 
             device = ati_device_get_from_busid(bus, dev, func);
         }
+#ifdef XSERVER_PLATFORM_BUS
+        else
+            device = ati_device_get_indexed(i);
+#else
         else {
             device = ati_device_get_primary();
         }
+#endif
 
         if (!device)
             continue;
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 6a35728..8f8f987 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1549,6 +1549,8 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 	/* workout clones */
 	drmmode_clones_init(pScrn, drmmode);
 
+	xf86ProviderSetup(pScrn, NULL, "radeon");
+
 	xf86InitialConfiguration(pScrn, TRUE);
 
 	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c
index f906cbf..39f7fa9 100644
--- a/src/evergreen_exa.c
+++ b/src/evergreen_exa.c
@@ -1902,7 +1902,10 @@ EVERGREENDrawInit(ScreenPtr pScreen)
 #if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5)
     info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2;
 #endif
-
+#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;
 #ifdef EXA_SUPPORTS_PREPARE_AUX
     info->accel_state->exa->flags |= EXA_SUPPORTS_PREPARE_AUX;
diff --git a/src/evergreen_state.h b/src/evergreen_state.h
index c92393e..3ce2bf2 100644
--- a/src/evergreen_state.h
+++ b/src/evergreen_state.h
@@ -350,5 +350,7 @@ extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv);
 extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
 extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix);
+extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p);
+extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle);
 
 #endif
diff --git a/src/r600_exa.c b/src/r600_exa.c
index 61b6315..21df084 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -551,7 +551,10 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     dst_obj.width = pDst->drawable.width;
     dst_obj.height = pDst->drawable.height;
     dst_obj.bpp = pDst->drawable.bitsPerPixel;
-    dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
+    if (radeon_get_pixmap_shared(pDst) == TRUE) {
+	dst_obj.domain = RADEON_GEM_DOMAIN_GTT;
+    } else
+	dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
 
     if (!R600SetAccelState(pScrn,
 			   &src_obj,
@@ -1203,7 +1206,10 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     dst_obj.width = pDst->drawable.width;
     dst_obj.height = pDst->drawable.height;
     dst_obj.bpp = pDst->drawable.bitsPerPixel;
-    dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
+    if (radeon_get_pixmap_shared(pDst) == TRUE)
+	dst_obj.domain = RADEON_GEM_DOMAIN_GTT;
+    else
+	dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
 
     if (pMaskPicture) {
 	if (!pMask) {
@@ -1882,6 +1888,10 @@ R600DrawInit(ScreenPtr pScreen)
     info->accel_state->exa->DownloadFromScreen = R600DownloadFromScreenCS;
 #if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5)
     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
 #endif
 #endif
 
diff --git a/src/r600_state.h b/src/r600_state.h
index 74b481c..fa777e8 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -321,6 +321,6 @@ extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv);
 extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
 extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix);
-
-
+extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p);
+extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle);
 #endif
diff --git a/src/radeon.h b/src/radeon.h
index 2f05249..080de77 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -249,6 +249,7 @@ struct radeon_exa_pixmap_priv {
     uint32_t tiling_flags;
     struct radeon_surface surface;
     Bool bo_mapped;
+    Bool shared;
 };
 
 #define RADEON_2D_EXA_COPY 1
@@ -266,6 +267,7 @@ struct radeon_2d_state {
     uint32_t dp_src_frgd_clr;
     uint32_t dp_src_bkgd_clr;
     uint32_t default_sc_bottom_right;
+    uint32_t dst_domain;
     struct radeon_bo *dst_bo;
     struct radeon_bo *src_bo;
 };
@@ -480,6 +482,7 @@ typedef struct {
 
     /* Perform vsync'ed SwapBuffers? */
     Bool swapBuffersWait;
+
 } RADEONInfoRec, *RADEONInfoPtr;
 
 /* radeon_accel.c */
@@ -624,6 +627,23 @@ static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
     return NULL;
 }
 
+static inline Bool radeon_get_pixmap_shared(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+    RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+    if (info->use_glamor) {
+        ErrorF("glamor sharing todo\n");
+	return FALSE:
+    } else
+#endif
+    {
+	struct radeon_exa_pixmap_priv *driver_priv;
+	driver_priv = exaGetPixmapDriverPrivate(pPix);
+	return driver_priv->shared;
+    }
+    return FALSE;
+}
 
 #define CP_PACKET0(reg, n)						\
 	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index ccdf7eb..45595ba 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -73,7 +73,7 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     uint32_t tiling = 0;
     struct radeon_surface surface;
     struct radeon_bo *bo;
-
+    int domain = RADEON_GEM_DOMAIN_VRAM;
     if (usage_hint) {
 	if (info->allowColorTiling) {
 	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
@@ -84,6 +84,12 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 	if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
 		tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
 
+	ErrorF("usage hint %08x %08x\n", usage_hint, CREATE_PIXMAP_USAGE_SHARED);
+	if ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) {
+		ErrorF("creating untiled gtt\n");
+		tiling = 0;
+		domain = RADEON_GEM_DOMAIN_GTT;
+	}
     }
 
     /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
@@ -147,6 +153,7 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 			base_align = surface.bo_alignment;
 			pitch = surface.level[0].pitch_bytes;
 			tiling = 0;
+			ErrorF("go surface level %d\n", surface.level[0].mode);
 			switch (surface.level[0].mode) {
 			case RADEON_SURF_MODE_2D:
 				tiling |= RADEON_TILING_MACRO;
@@ -166,7 +173,7 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 	}
 
     bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
-			RADEON_GEM_DOMAIN_VRAM, 0);
+			domain, 0);
 
     if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0)
 	*new_tiling = tiling;
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 92241c7..105574a 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -315,11 +315,11 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
 }
 #else
 static BufferPtr
-radeon_dri2_create_buffer(DrawablePtr drawable,
-                          unsigned int attachment,
-                          unsigned int format)
+radeon_dri2_create_buffer2(ScreenPtr pScreen,
+			   DrawablePtr drawable,
+			   unsigned int attachment,
+			   unsigned int format)
 {
-    ScreenPtr pScreen = drawable->pScreen;
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr info = RADEONPTR(pScrn);
     BufferPtr buffers;
@@ -340,7 +340,9 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 
     if (attachment == DRI2BufferFrontLeft) {
         pixmap = get_drawable_pixmap(drawable);
-	if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+	if (pScreen != pixmap->drawable.pScreen)
+	    pixmap = NULL;
+	else if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
 	    is_glamor_pixmap = TRUE;
 	    aligned_width = pixmap->drawable.width;
 	    height = pixmap->drawable.height;
@@ -352,7 +354,7 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
         pixmap->refcnt++;
     }
 
-    if (!pixmap) {
+    if (!pixmap && attachment != DRI2BufferFrontLeft) {
 	/* tile the back buffer */
 	switch(attachment) {
 	case DRI2BufferDepth:
@@ -425,9 +427,6 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 					      flags | RADEON_CREATE_PIXMAP_DRI2);
     }
 
-    if (!pixmap)
-        return NULL;
-
     buffers = calloc(1, sizeof *buffers);
     if (buffers == NULL)
         goto error;
@@ -435,24 +434,30 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
     if (attachment == DRI2BufferDepth) {
         depth_pixmap = pixmap;
     }
-    if (!info->use_glamor) {
-	info->exa_force_create = TRUE;
-	exaMoveInPixmap(pixmap);
-	info->exa_force_create = FALSE;
+
+    if (pixmap) {
+	if (!info->use_glamor) {
+	    info->exa_force_create = TRUE;
+	    exaMoveInPixmap(pixmap);
+	    info->exa_force_create = FALSE;
+	}
+
+	if (is_glamor_pixmap)
+	    pixmap = fixup_glamor(drawable, pixmap);
+	bo = radeon_get_pixmap_bo(pixmap);
+	if (!bo || radeon_gem_get_kernel_name(bo, &buffers->name) != 0)
+	    goto error;
     }
-    if (is_glamor_pixmap)
-	pixmap = fixup_glamor(drawable, pixmap);
-    bo = radeon_get_pixmap_bo(pixmap);
-    if (!bo || radeon_gem_get_kernel_name(bo, &buffers->name) != 0)
-        goto error;
 
     privates = calloc(1, sizeof(struct dri2_buffer_priv));
     if (privates == NULL)
         goto error;
 
     buffers->attachment = attachment;
-    buffers->pitch = pixmap->devKind;
-    buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
+    if (pixmap) {
+	buffers->pitch = pixmap->devKind;
+	buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
+    }
     buffers->driverPrivate = privates;
     buffers->format = format;
     buffers->flags = 0; /* not tiled */
@@ -468,6 +473,14 @@ error:
         (*pScreen->DestroyPixmap)(pixmap);
     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);
+}
 #endif
 
 #ifndef USE_DRI2_1_1_0
@@ -491,11 +504,11 @@ radeon_dri2_destroy_buffers(DrawablePtr drawable,
 }
 #else
 static void
-radeon_dri2_destroy_buffer(DrawablePtr drawable, BufferPtr buffers)
+radeon_dri2_destroy_buffer2(ScreenPtr pScreen,
+			    DrawablePtr drawable, BufferPtr buffers)
 {
     if(buffers)
     {
-        ScreenPtr pScreen = drawable->pScreen;
         struct dri2_buffer_priv *private = buffers->driverPrivate;
 
         /* Trying to free an already freed buffer is unlikely to end well */
@@ -511,24 +524,41 @@ radeon_dri2_destroy_buffer(DrawablePtr drawable, BufferPtr buffers)
         private->refcnt--;
         if (private->refcnt == 0)
         {
-            (*pScreen->DestroyPixmap)(private->pixmap);
+	    if (private->pixmap)
+                (*pScreen->DestroyPixmap)(private->pixmap);
 
             free(buffers->driverPrivate);
             free(buffers);
         }
     }
 }
+
+void
+radeon_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf)
+{
+  radeon_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf);
+}
 #endif
 
+
+static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable)
+{
+    if (drawable->type == DRAWABLE_PIXMAP)
+        return (PixmapPtr)drawable;
+    else {
+        struct _Window *pWin = (struct _Window *)drawable;
+        return drawable->pScreen->GetWindowPixmap(pWin);
+    }
+}
 static void
-radeon_dri2_copy_region(DrawablePtr drawable,
-                        RegionPtr region,
-                        BufferPtr dest_buffer,
-                        BufferPtr src_buffer)
+radeon_dri2_copy_region2(ScreenPtr pScreen,
+			 DrawablePtr drawable,
+			 RegionPtr region,
+			 BufferPtr dest_buffer,
+			 BufferPtr src_buffer)
 {
     struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
     struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
-    ScreenPtr pScreen = drawable->pScreen;
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     DrawablePtr src_drawable;
     DrawablePtr dst_drawable;
@@ -536,20 +566,42 @@ radeon_dri2_copy_region(DrawablePtr drawable,
     GCPtr gc;
     RADEONInfoPtr info = RADEONPTR(pScrn);
     Bool vsync;
+    Bool translate = FALSE;
+    int off_x = 0, off_y = 0;
+    PixmapPtr dst_ppix;
+
+    dst_ppix = dst_private->pixmap;
+    src_drawable = &src_private->pixmap->drawable;
+    dst_drawable = &dst_private->pixmap->drawable;
 
     if (src_private->attachment == DRI2BufferFrontLeft) {
         src_drawable = drawable;
-    } else {
-        src_drawable = &src_private->pixmap->drawable;
     }
     if (dst_private->attachment == DRI2BufferFrontLeft) {
-        dst_drawable = drawable;
-    } else {
-        dst_drawable = &dst_private->pixmap->drawable;
+	if (drawable->pScreen != pScreen) {
+	    dst_drawable = DRI2UpdatePrime(drawable, dest_buffer);
+	    if (!dst_drawable)
+		return;
+	    dst_ppix = (PixmapPtr)dst_drawable;
+	    if (dst_drawable != drawable)
+		translate = TRUE;
+	} else
+	    dst_drawable = drawable;
+    }
+
+    if (translate && drawable->type == DRAWABLE_WINDOW) {
+	WindowPtr pWin = (WindowPtr)drawable;
+	off_x = pWin->origin.x;
+	off_y = pWin->origin.y;
     }
     gc = GetScratchGC(dst_drawable->depth, pScreen);
     copy_clip = REGION_CREATE(pScreen, NULL, 0);
     REGION_COPY(pScreen, copy_clip, region);
+
+    if (translate) {
+	REGION_TRANSLATE(pScreen, copy_clip, off_x, off_y);
+    }
+
     (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
     ValidateGC(dst_drawable, gc);
 
@@ -563,7 +615,7 @@ radeon_dri2_copy_region(DrawablePtr drawable,
 	    if (extents->x1 == 0 && extents->y1 == 0 &&
 		extents->x2 == drawable->width &&
 		extents->y2 == drawable->height) {
-		struct radeon_bo *bo = radeon_get_pixmap_bo(dst_private->pixmap);
+		struct radeon_bo *bo = radeon_get_pixmap_bo(dst_ppix);
 
 		if (bo)
 		    radeon_bo_wait(bo);
@@ -577,13 +629,20 @@ radeon_dri2_copy_region(DrawablePtr drawable,
     info->accel_state->vsync = info->swapBuffersWait;
 
     (*gc->ops->CopyArea)(src_drawable, dst_drawable, gc,
-                         0, 0, drawable->width, drawable->height, 0, 0);
+                         0, 0, drawable->width, drawable->height, off_x, off_y);
 
     info->accel_state->vsync = vsync;
 
     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);
+}
 
 #ifdef USE_DRI2_SCHEDULING
 
@@ -1490,6 +1549,13 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
     }
 #endif
 
+#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_exa.c b/src/radeon_exa.c
index 5c5d997..cbf3231 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -41,7 +41,7 @@
 #include "radeon_probe.h"
 #include "radeon_version.h"
 #include "radeon_exa_shared.h"
-
+#include "radeon_bo_gem.h"
 #include "xf86.h"
 
 
@@ -325,6 +325,77 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
     free(driverPriv);
 }
 
+Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle)
+{
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int ret;
+    int handle;
+
+    driver_priv = exaGetPixmapDriverPrivate(ppix);
+
+    ret = radeon_gem_prime_share_bo(driver_priv->bo, &handle);
+    if (ret)
+	return FALSE;
+
+    driver_priv->shared = TRUE;
+    *fd_handle = (void *)(long)handle;
+    return TRUE;
+}
+
+Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
+{
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *bo;
+    int ihandle = (int)(long)fd_handle;
+    uint32_t size = ppix->devKind * ppix->drawable.height;
+    struct radeon_surface surface;
+
+    driver_priv = exaGetPixmapDriverPrivate(ppix);
+
+    bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size);
+    if (!bo)
+        return FALSE;
+
+    memset(&surface, 0, sizeof(struct radeon_surface));
+	
+    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+
+	surface.npix_x = ppix->drawable.width;
+	surface.npix_y = ppix->drawable.height;
+	surface.npix_z = 1;
+	surface.blk_w = 1;
+	surface.blk_h = 1;
+	surface.blk_d = 1;
+	surface.array_size = 1;
+	surface.bpe = ppix->drawable.bitsPerPixel / 8;
+	surface.nsamples = 1;
+	surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+	surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+	if (radeon_surface_best(info->surf_man, &surface)) {
+	    return FALSE;
+	}
+	if (radeon_surface_init(info->surf_man, &surface)) {
+	    return FALSE;
+	}
+	/* we have to post hack the surface to reflect the actual size
+	   of the shared pixmap */
+	surface.level[0].pitch_bytes = ppix->devKind;
+	surface.level[0].nblk_x = ppix->devKind / surface.bpe;
+    }
+    driver_priv->surface = surface;
+    driver_priv->shared = TRUE;
+    driver_priv->tiling_flags = 0;
+    radeon_set_pixmap_bo(ppix, bo);
+
+    close(ihandle);
+    /* we have a reference from the alloc and one from set pixmap bo,
+       drop one */
+    radeon_bo_unref(bo);
+    return TRUE;
+}
+
 uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
 {
     struct radeon_exa_pixmap_priv *driver_priv;
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 4c13a00..cc997c7 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -80,7 +80,7 @@ static void Emit2DState(ScrnInfoPtr pScrn, int op)
     OUT_RING_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl);
 
     OUT_RING_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
-    OUT_RING_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    OUT_RING_RELOC(info->state_2d.dst_bo, 0, info->state_2d.dst_domain);
 
     if (has_src) {
 	OUT_RING_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
@@ -145,8 +145,10 @@ RADEONPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n"));
 
     driver_priv = exaGetPixmapDriverPrivate(pPix);
-    if (driver_priv)
+    if (driver_priv) {
 	info->state_2d.dst_bo = driver_priv->bo;
+ 	info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM;
+    }
 
     info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX |
 					       RADEON_DEFAULT_SC_BOTTOM_MAX);
@@ -652,6 +654,10 @@ Bool RADEONDrawInit(ScreenPtr pScreen)
     info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS;
 #if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5)
     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
 #endif
 #endif
 
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index a4f46d7..f326b92 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -241,6 +241,38 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
     return TRUE;
 }
 
+static void
+redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
+{
+	ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
+	RegionRec pixregion;
+
+	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
+	PixmapSyncDirtyHelper(dirty, &pixregion);
+
+	radeon_cs_flush_indirect(pScrn);
+	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+	RegionUninit(&pixregion);
+}
+
+static void
+radeon_dirty_update(ScreenPtr screen)
+{
+	RegionPtr region;
+	PixmapDirtyUpdatePtr ent;
+
+	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
+		return;
+
+	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
+		region = DamageRegion(ent->damage);
+		if (RegionNotEmpty(region)) {
+			redisplay_dirty(screen, ent);
+			DamageEmpty(ent->damage);
+		}
+	}
+}
+
 static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
 {
     SCREEN_PTR(arg);
@@ -255,6 +287,7 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
 	radeon_glamor_flush(pScrn);
 
     radeon_cs_flush_indirect(pScrn);
+    radeon_dirty_update(pScreen);
 }
 
 static void
@@ -680,6 +713,22 @@ static Bool r600_get_tile_config(ScrnInfoPtr pScrn)
 
 #endif /* EXA_MIXED_PIXMAPS */
 
+static void RADEONSetupCapabilities(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    uint64_t value;
+    int ret;
+
+    pScrn->capabilities = 0;
+    ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_PRIME, &value);
+    if (ret == 0) {
+	if (value & DRM_PRIME_CAP_EXPORT)
+	    pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
+	if (value & DRM_PRIME_CAP_IMPORT)
+	    pScrn->capabilities |= RR_Capability_SourceOffload;
+    }
+}
+
 Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 {
     RADEONInfoPtr     info;
@@ -698,7 +747,9 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
     info->IsSecondary  = FALSE;
     info->IsPrimary = FALSE;
     info->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
-    if (info->pEnt->location.type != BUS_PCI) goto fail;
+    if (info->pEnt->location.type != BUS_PCI &&
+	info->pEnt->location.type != BUS_PLATFORM)
+        goto fail;
 
     pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
 				 getRADEONEntityIndex());
@@ -757,6 +808,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 
     info->allowColorTiling2D = FALSE;
 
+    RADEONSetupCapabilities(pScrn);
 #ifdef EXA_MIXED_PIXMAPS
     /* don't enable tiling if accel is not enabled */
     if (!info->r600_shadow_fb) {
@@ -1237,6 +1289,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
     info->CreateScreenResources = pScreen->CreateScreenResources;
     pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
 
+    pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
+    pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
    if (!xf86CrtcScreenInit (pScreen))
        return FALSE;
 
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index 6ddfa88..f286302 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -53,6 +53,8 @@
 #include "xf86drmMode.h"
 #include "dri.h"
 
+#include <xf86platformBus.h>
+
 #include "radeon_chipset_gen.h"
 
 #include "radeon_pci_chipset_gen.h"
@@ -255,6 +257,78 @@ RADEONDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
     }
 }
 
+#ifdef XSERVER_PLATFORM_BUS
+static Bool
+radeon_platform_probe(DriverPtr pDriver,
+		      int entity_num, int flags,
+		      struct xf86_platform_device *dev,
+		      intptr_t match_data)
+{
+    ScrnInfoPtr pScrn;
+    char *path = xf86_get_platform_device_attrib(dev, ODEV_ATTRIB_PATH);
+    int scr_flags = 0;
+    EntityInfoPtr pEnt;
+
+    if (!dev->pdev)
+	return FALSE;
+
+    if (flags & PLATFORM_PROBE_GPU_SCREEN)
+	scr_flags = XF86_ALLOCATE_GPU_SCREEN;
+
+    pScrn = xf86AllocateScreen(pDriver, scr_flags);
+    xf86AddEntityToScreen(pScrn, entity_num);
+
+    if (!radeon_kernel_mode_enabled(pScrn, dev->pdev))
+	return FALSE;
+
+    pScrn->driverVersion = RADEON_VERSION_CURRENT;
+    pScrn->driverName    = RADEON_DRIVER_NAME;
+    pScrn->name          = RADEON_NAME;
+    pScrn->Probe         = NULL;
+    pScrn->PreInit       = RADEONPreInit_KMS;
+    pScrn->ScreenInit    = RADEONScreenInit_KMS;
+    pScrn->SwitchMode    = RADEONSwitchMode_KMS;
+    pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;
+    pScrn->EnterVT       = RADEONEnterVT_KMS;
+    pScrn->LeaveVT       = RADEONLeaveVT_KMS;
+    pScrn->FreeScreen    = RADEONFreeScreen_KMS;
+    pScrn->ValidMode     = RADEONValidMode;
+
+    pEnt = xf86GetEntityInfo(entity_num);
+
+    /* Create a RADEONEntity for all chips, even with old single head
+     * Radeon, need to use pRADEONEnt for new monitor detection routines.
+     */
+    {
+        DevUnion    *pPriv;
+        RADEONEntPtr pRADEONEnt;
+
+        xf86SetEntitySharable(entity_num);
+
+        if (gRADEONEntityIndex == -1)
+            gRADEONEntityIndex = xf86AllocateEntityPrivateIndex();
+
+        pPriv = xf86GetEntityPrivate(pEnt->index,
+                                     gRADEONEntityIndex);
+
+	xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
+
+        if (!pPriv->ptr) {
+            pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
+            pRADEONEnt = pPriv->ptr;
+            pRADEONEnt->HasSecondary = FALSE;
+        } else {
+            pRADEONEnt = pPriv->ptr;
+            pRADEONEnt->HasSecondary = TRUE;
+        }
+    }
+
+    free(pEnt);
+
+    return TRUE;
+}
+#endif
+
 _X_EXPORT DriverRec RADEON =
 {
     RADEON_VERSION_CURRENT,
@@ -271,6 +345,11 @@ _X_EXPORT DriverRec RADEON =
     RADEONDriverFunc,
 #ifdef XSERVER_LIBPCIACCESS
     radeon_device_match,
-    radeon_pci_probe
+    radeon_pci_probe,
+#endif
+#ifdef XSERVER_PLATFORM_BUS
+    radeon_platform_probe
+#else
+    NULL
 #endif
 };