Blob Blame History Raw
diff --git a/configure.ac b/configure.ac
index a7e954d..8b126b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,6 +123,7 @@ if test "$DRI" = yes; then
         if test "x$DRM_MODE" = xyes; then
                 AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
         fi
+	CFLAGS="$save_CFLAGS"
 fi
 
 save_CFLAGS="$CFLAGS"
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 25e6183..a22cd62 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -31,8 +31,11 @@
 
 #ifdef XF86DRM_MODE
 #include "radeon.h"
+#include "radeon_reg.h"
 #include "sarea.h"
 
+#include "dri_bufmgr.h"
+
 static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height);
 
 static Bool
@@ -119,6 +122,76 @@ drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
 
 }
 
+struct radeon_exa_pixmap_priv {
+    dri_bo *bo;
+    int flags;
+};
+
+static PixmapPtr
+create_pixmap_for_fb(drmmode_ptr drmmode, ScrnInfoPtr pScrn, drmModeFBPtr fb)
+{
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr pPixmap;
+	struct radeon_exa_pixmap_priv *driver_priv;
+	dri_bo *bo;
+
+	pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, fb->depth, 0);
+	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	if (!driver_priv) {
+		(*pScreen->DestroyPixmap)(pPixmap);
+		return NULL;
+	}
+
+	miModifyPixmapHeader(pPixmap, fb->width, fb->height, fb->depth,
+                             pScrn->bitsPerPixel, fb->pitch, NULL);
+
+	bo = radeon_bo_gem_create_from_handle(drmmode->bufmgr,
+					      fb->handle,
+					      fb->pitch * fb->height);
+	driver_priv->bo = bo;
+	if (bo == NULL) {
+		(*pScreen->DestroyPixmap)(pPixmap);
+		return NULL;
+	}
+
+    	return pPixmap;
+}
+
+static void
+copy_fb_contents (drmmode_ptr drmmode,
+		  ScrnInfoPtr pScrn,
+		  unsigned int dest_id, int x, int y, unsigned int src_id)
+{
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	drmModeFBPtr dest_fb, src_fb;
+	dri_bo *dest_bo, *src_bo;
+	PixmapPtr src_pixmap, dest_pixmap;
+	ScreenPtr pScreen = pScrn->pScreen;
+
+	dest_fb = drmModeGetFB(drmmode->fd, dest_id);
+	src_fb = drmModeGetFB(drmmode->fd, src_id);
+	if (src_fb == NULL) {
+		ErrorF("failed to get old fb, id %d\n", src_id);
+		return;
+	}
+
+	dest_pixmap = create_pixmap_for_fb(drmmode, pScrn, dest_fb);
+	src_pixmap = create_pixmap_for_fb(drmmode, pScrn, src_fb);
+
+	info->exa->PrepareCopy (src_pixmap, dest_pixmap,
+				0, 0, GXcopy, 0xffffff);
+	info->exa->Copy (dest_pixmap, 0, 0, x, y,
+			 src_fb->width, src_fb->height);
+	info->exa->DoneCopy (dest_pixmap);
+	RADEONCPFlushIndirect(pScrn, 0);
+
+	(*pScreen->DestroyPixmap)(dest_pixmap);
+	(*pScreen->DestroyPixmap)(src_pixmap);
+
+	drmFree(dest_fb);
+	drmFree(src_fb);
+}
+
 static Bool
 drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     Rotation rotation, int x, int y)
@@ -174,7 +247,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	fb_id = drmmode->fb_id;
 	if (drmmode_crtc->rotate_fb_id)
 		fb_id = drmmode_crtc->rotate_fb_id;
-	ErrorF("fb id is %d\n", fb_id);
+ 	copy_fb_contents (drmmode, crtc->scrn, fb_id, x, y,
+ 			  drmmode_crtc->mode_crtc->buffer_id);
 	drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 		       fb_id, x, y, output_ids, output_count, &kmode);
 
diff --git a/src/radeon_bufmgr.h b/src/radeon_bufmgr.h
index a16ad9a..b3034d7 100644
--- a/src/radeon_bufmgr.h
+++ b/src/radeon_bufmgr.h
@@ -16,6 +16,8 @@ struct radeon_bufmgr {
 dri_bufmgr *radeon_bufmgr_gem_init(int fd);
 dri_bo *radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
 				       unsigned int handle);
+dri_bo *radeon_bo_gem_create_from_handle(dri_bufmgr *bufmgr,
+					 uint32_t handle, unsigned long size);
 
 void radeon_bufmgr_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
 
diff --git a/src/radeon_bufmgr_gem.c b/src/radeon_bufmgr_gem.c
index db28edc..75cff8e 100644
--- a/src/radeon_bufmgr_gem.c
+++ b/src/radeon_bufmgr_gem.c
@@ -353,6 +353,27 @@ void radeon_bufmgr_gem_wait_rendering(dri_bo *buf)
 	return;
 }
 
+dri_bo *
+radeon_bo_gem_create_from_handle(dri_bufmgr *bufmgr,
+				 uint32_t handle, unsigned long size)
+{
+    dri_bo_gem *bo_gem;
+
+    bo_gem = calloc(1, sizeof(*bo_gem));
+    if (!bo_gem)
+	return NULL;
+
+    bo_gem->bo.size = size;
+    bo_gem->bo.offset = 0;
+    bo_gem->bo.virtual = NULL;
+    bo_gem->bo.bufmgr = bufmgr;
+    bo_gem->name = 0;
+    bo_gem->refcount = 1;
+    bo_gem->gem_handle = handle;
+
+    return &bo_gem->bo;
+}
+
 /**
  * Returns a dri_bo wrapping the given buffer object handle.
  *
@@ -364,32 +385,20 @@ radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
 			       unsigned int handle)
 {
     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
-    dri_bo_gem *bo_gem;
     int ret;
     struct drm_gem_open open_arg;
 
-    bo_gem = calloc(1, sizeof(*bo_gem));
-    if (!bo_gem)
-	return NULL;
-
     memset(&open_arg, 0, sizeof(open_arg));
     open_arg.name = handle;
     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
     if (ret != 0) {
 	fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
 	       name, handle, strerror(-ret));
-	free(bo_gem);
 	return NULL;
     }
-    bo_gem->bo.size = open_arg.size;
-    bo_gem->bo.offset = 0;
-    bo_gem->bo.virtual = NULL;
-    bo_gem->bo.bufmgr = bufmgr;
-    bo_gem->name = name;
-    bo_gem->refcount = 1;
-    bo_gem->gem_handle = open_arg.handle;
 
-    return &bo_gem->bo;
+    return radeon_bo_gem_create_from_handle(bufmgr,
+					    open_arg.handle, open_arg.size);
 }
 
 #define BUF_OUT_RING(x)	 do {			\
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index d5bb24d..070cc56 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -3640,6 +3640,24 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
     /* xf86CrtcRotate() accesses pScrn->pScreen */
     pScrn->pScreen = pScreen;
 
+    /* Enable aceleration */
+    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		       "Initializing Acceleration\n");
+	if (RADEONAccelInit(pScreen)) {
+	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
+	    info->accelOn = TRUE;
+	} else {
+	    xf86DrvMsg(scrnIndex, X_ERROR,
+		       "Acceleration initialization failed\n");
+	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+	    info->accelOn = FALSE;
+	}
+    } else {
+	xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+	info->accelOn = FALSE;
+    }
+
     if (!xf86SetDesiredModes (pScrn))
 	return FALSE;
 
@@ -3710,25 +3728,6 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
         RADEONChangeSurfaces(pScrn);
     }
 
-
-    /* Enable aceleration */
-    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
-	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		       "Initializing Acceleration\n");
-	if (RADEONAccelInit(pScreen)) {
-	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
-	    info->accelOn = TRUE;
-	} else {
-	    xf86DrvMsg(scrnIndex, X_ERROR,
-		       "Acceleration initialization failed\n");
-	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
-	    info->accelOn = FALSE;
-	}
-    } else {
-	xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
-	info->accelOn = FALSE;
-    }
-
     /* Init DPMS */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Initializing DPMS\n");