[Intel-gfx] [RFC] resize & rotate support for KMS

Jesse Barnes jbarnes at virtuousgeek.org
Fri Jan 30 23:22:22 CET 2009


On Thursday, January 29, 2009 2:27 pm Jesse Barnes wrote:
> This patch is intended to re-add resize and rotate support to the 2D
> driver. Rotate still doesn't work though; I don't think the set_mode_major
> call is happening after the shadow gets created (or something, still
> debugging).
>
> Anyway just posting it to get some comments, there are still bugs here so I
> wanted the extra eyes.

Ok, need some review on this now.  Resize works but rotate turns off the
display, so I'm clearly doing something wrong, but I can't see what...

-- 
Jesse Barnes, Intel Open Source Technology Center


diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 4994251..02ce610 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -35,24 +35,6 @@
 #include "i830.h"
 #include "sarea.h"
 
-static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode,
-			      int width, int height);
-
-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;
-	Bool ret;
-
-	ret = drmmode_resize_fb(scrn, drmmode, width, height);
-	scrn->virtualX = width;
-	scrn->virtualY = height;
-	return ret;
-}
-
 static void
 drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
 			 struct drm_mode_modeinfo *kmode,
@@ -112,6 +94,100 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
 
 }
 
+static Bool
+drmmode_xf86crtc_resize (ScrnInfoPtr pScrn, int width, int height)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn);
+	ScreenPtr screen = screenInfo.screens[pScrn->scrnIndex];
+	I830Ptr pI830 = I830PTR(pScrn);
+	drmmode_crtc_private_ptr drmmode_crtc =	config->crtc[0]->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	Bool ret;
+	i830_memory *new_front, *old_front = pI830->front_buffer;
+	BoxRec mem_box;
+	Bool tiled;
+	uint32_t *output_ids;
+	int output_count = 0;
+	int old_x = pScrn->virtualX;
+	int old_y = pScrn->virtualY;
+	int old_width = pScrn->displayWidth;
+	int old_fb_id = drmmode->fb_id;
+	int i, j;
+	struct drm_mode_modeinfo kmode;
+
+	/* Already have the right size... */
+	if (drmmode->mode_fb->width == width &&
+	    drmmode->mode_fb->height == height)
+		return TRUE;
+
+	pScrn->virtualX = width;
+	pScrn->virtualY = height;
+	pScrn->displayWidth = i830_pad_drawable_width(width, pI830->cpp);
+	tiled = i830_tiled_width(pI830, &pScrn->displayWidth, pI830->cpp);
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Allocating new frame buffer, %dx%d stride %d\n",
+		   width, height, pScrn->displayWidth);
+	new_front = i830_allocate_framebuffer(pScrn, pI830, &mem_box, FALSE);
+	if (!new_front) {
+		pScrn->virtualX = old_x;
+		pScrn->virtualY = old_y;
+		pScrn->displayWidth = old_width;
+		return FALSE;
+	}
+
+	pI830->front_buffer = new_front;
+	i830_set_pixmap_bo(screen->GetScreenPixmap(screen),
+			   new_front->bo);
+	pScrn->fbOffset = pI830->front_buffer->offset;
+	screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen),
+				   width, height, -1, -1,
+				   pScrn->displayWidth * pI830->cpp,
+				   NULL);
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n",
+		   pI830->front_buffer->offset);
+	i830_free_memory(pScrn, old_front);
+
+	output_ids = xnfcalloc(sizeof(uint32_t), config->num_output);
+
+	/* Set each CRTC to point at the new buffer */
+	for (i = 0; i < config->num_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		drmmode_crtc =	config->crtc[i]->driver_private;
+
+		if (!crtc->enabled || crtc->transform_in_use)
+			continue;
+
+		output_count = 0;
+		for (j = 0; j < config->num_output; j++) {
+			xf86OutputPtr output = config->output[j];
+			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++;
+		}
+		drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
+
+		ret = drmModeSetCrtc(drmmode->fd,
+				     drmmode_crtc->mode_crtc->crtc_id,
+				     drmmode->fb_id, crtc->x, crtc->y,
+				     output_ids, output_count,
+				     &kmode);
+		if (ret)
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "Failed to resize crtc %d\n", i);
+	}
+	drmModeRmFB(drmmode->fd, old_fb_id);
+
+	return TRUE;
+}
+
+
 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 	drmmode_xf86crtc_resize
 };
@@ -154,6 +230,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 	output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
 	if (!output_ids) {
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "out of memory\n");
 		ret = FALSE;
 		goto done;
 	}
@@ -181,18 +258,21 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 	drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
 
-
 	fb_id = drmmode->fb_id;
-	if (drmmode_crtc->rotate_fb_id)
+	if (drmmode_crtc->rotate_fb_id) {
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO, "using rotated fb\n");
 		fb_id = drmmode_crtc->rotate_fb_id;
-	ErrorF("fb id is %d\n", fb_id);
+	}
+
 	ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 			     fb_id, x, y, output_ids, output_count, &kmode);
-	if (ret)
+	if (ret) {
 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
-			   "failed to set mode: %s", strerror(-ret));
-	else
+			   "failed to set mode: %s\n", strerror(-ret));
+		ret = FALSE;
+	} else {
 		ret = TRUE;
+	}
 
 done:
 	if (!ret) {
@@ -261,36 +341,48 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
 static void *
 drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
 {
+	ScrnInfoPtr pScrn = crtc->scrn;
+	I830Ptr pI830 = I830PTR(pScrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
-	int size;
+	int size, ret;
 	unsigned long rotate_pitch;
+	BoxRec mem_box;
 
-	rotate_pitch = crtc->scrn->displayWidth * drmmode->cpp;
+	width = i830_pad_drawable_width(width, drmmode->cpp);
+	rotate_pitch = width * drmmode->cpp;
 	size = rotate_pitch * height;
 
-#if 0
-	drmmode_crtc->rotate_bo =
-		dri_bo_alloc(drmmode->bufmgr, "rotate", size, 4096);
-
-	if (!drmmode_crtc->rotate_bo) {
+	drmmode_crtc->rotate_mem = i830_allocate_framebuffer(pScrn, pI830,
+							     &mem_box, FALSE);
+	if (!drmmode_crtc->rotate_mem) {
 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
-			   "Couldn't allocate shadow memory for rotated CRTC\n");
+			   "Couldn't allocate rotated framebuffer\n");
 		return NULL;
 	}
 
-	dri_bo_map(drmmode_crtc->rotate_bo, 1);
+	drm_intel_gem_bo_map_gtt(drmmode_crtc->rotate_mem->bo);
+
+	memset(drmmode_crtc->rotate_mem->bo->virtual, 0xff, size);
 
 	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
 			   crtc->scrn->bitsPerPixel, rotate_pitch,
-			   drmmode_crtc->rotate_bo->handle,
+			   drmmode_crtc->rotate_mem->bo->handle,
 			   &drmmode_crtc->rotate_fb_id);
-	if (ret)
-		ErrorF("failed to add rotate fb\n");
+	if (ret) {
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+			   "failed to add rotate fb\n");
+		drm_intel_bo_unmap(drmmode_crtc->rotate_mem->bo);
+		i830_free_memory(pScrn, drmmode_crtc->rotate_mem);
+		return NULL;
+	}
 
-	return drmmode_crtc->rotate_bo->virtual;
-#endif
-	return NULL;
+	xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
+		   "Allocated shadow fb @ 0x%08lx (id %d)\n",
+		   drmmode_crtc->rotate_mem->offset,
+		   drmmode_crtc->rotate_fb_id);
+
+	return drmmode_crtc->rotate_mem->bo->virtual;
 }
 
 static PixmapPtr
@@ -305,7 +397,11 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 	if (!data)
 		data = drmmode_crtc_shadow_allocate (crtc, width, height);
 
-	rotate_pitch = pScrn->displayWidth * drmmode->cpp;
+	if (!data)
+		return NULL;
+
+	rotate_pitch = i830_pad_drawable_width(width, drmmode->cpp) *
+		drmmode->cpp;
 
 	rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
 					       width, height,
@@ -316,29 +412,34 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 
 	if (rotate_pixmap == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
+			   "Couldn't allocate rotated framebuffer\n");
+		return NULL;
 	}
-	return rotate_pixmap;
 
+	i830_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_mem->bo);
+
+	return rotate_pixmap;
 }
 
 static void
-drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap,
+			    void *data)
 {
+	ScrnInfoPtr pScrn = crtc->scrn;
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
 	if (rotate_pixmap)
 		FreeScratchPixmapHeader(rotate_pixmap);
 
-#if 0
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	if (!data)
+		return;
 
-	if (data) {
-		/* Be sure to sync acceleration before the memory gets unbound. */
-		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
-		drmmode_crtc->rotate_fb_id = 0;
-		dri_bo_unreference(drmmode_crtc->rotate_bo);
-		drmmode_crtc->rotate_bo = NULL;
-	}
-#endif
+	drm_intel_bo_unmap(drmmode_crtc->rotate_mem->bo);
+	drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
+	drmmode_crtc->rotate_fb_id = 0;
+	dri_bo_unreference(drmmode_crtc->rotate_mem->bo);
+	i830_free_memory(pScrn, drmmode_crtc->rotate_mem);
 }
 
 static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
@@ -353,13 +454,7 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
 	.shadow_create = drmmode_crtc_shadow_create,
 	.shadow_allocate = drmmode_crtc_shadow_allocate,
 	.shadow_destroy = drmmode_crtc_shadow_destroy,
-#if 0
-	.gamma_set = i830_crtc_gamma_set,
-	.shadow_create = i830_crtc_shadow_create,
-	.shadow_allocate = i830_crtc_shadow_allocate,
-	.shadow_destroy = i830_crtc_shadow_destroy,
-	.set_cursor_colors = i830_crtc_set_cursor_colors,
-#endif
+
 	.destroy = NULL, /* XXX */
 };
 
@@ -474,26 +569,50 @@ drmmode_output_destroy(xf86OutputPtr output)
 	output->driver_private = NULL;
 }
 
+static drmModePropertyPtr
+drmmode_output_find_dpms_prop(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	drmModePropertyPtr prop;
+	int i;
+
+	/* Find the DPMS property on this output */
+	for (i = 0; i < koutput->count_props; i++) {
+		prop = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+		if (!prop)
+			continue;
+
+		if (!strcmp(prop->name, "DPMS"))
+			return prop;
+		drmModeFreeProperty(prop);
+	}
+
+	return NULL;
+}
+
 static void
 drmmode_output_dpms(xf86OutputPtr output, int mode)
 {
-	return;
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	drmModePropertyPtr prop;
+
+	prop = drmmode_output_find_dpms_prop(output);
+	if (!prop)
+		return;
+
+	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
+				    prop->prop_id, mode);
+	drmModeFreeProperty(prop);
 }
 
 static const xf86OutputFuncsRec drmmode_output_funcs = {
 	.dpms = drmmode_output_dpms,
-#if 0
-
-	.save = drmmode_crt_save,
-	.restore = drmmode_crt_restore,
-	.mode_fixup = drmmode_crt_mode_fixup,
-	.prepare = drmmode_output_prepare,
-	.mode_set = drmmode_crt_mode_set,
-	.commit = drmmode_output_commit,
-#endif
 	.detect = drmmode_output_detect,
 	.mode_valid = drmmode_output_mode_valid,
-
 	.get_modes = drmmode_output_get_modes,
 	.destroy = drmmode_output_destroy
 };
@@ -544,7 +663,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 	snprintf(name, 32, "%s%d", output_names[koutput->connector_type],
 		 koutput->connector_type_id);
 
-	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
+	output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
 	if (!output) {
 		drmModeFreeEncoder(kencoder);
 		drmModeFreeConnector(koutput);
@@ -609,21 +728,12 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId,
 	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
 		drmmode_output_init(pScrn, drmmode, i);
 
-	xf86InitialConfiguration(pScrn, FALSE);
+	xf86InitialConfiguration(pScrn, TRUE);
 
 	return TRUE;
 }
 
-#if 0
-Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
-			dri_bufmgr *bufmgr)
-{
-	drmmode->bufmgr = bufmgr;
-	return TRUE;
-}
-#endif
-
-void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width,
+Bool drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width,
 		    int height, int pitch, dri_bo *bo)
 {
 	int ret;
@@ -633,22 +743,17 @@ void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width,
 			   &drmmode->fb_id);
 
 	if (ret) {
-		ErrorF("Failed to add fb: %s\n", strerror(-ret));
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "Failed to add fb: %s\n", strerror(-ret));
+		return FALSE;
 	}
 
 	drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
-	if (!drmmode->mode_fb)
-		return;
-
-
-	ErrorF("Add fb id %d %d %d\n", drmmode->fb_id, width, height);
+	return TRUE;
 }
 
 Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo)
 {
-	return FALSE;
-
-#if 0
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn);
 	int i;
 
@@ -656,53 +761,16 @@ Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo)
 		xf86CrtcPtr crtc = config->crtc[i];
 		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 
-		if (!drmmode_crtc->rotate_bo)
+		if (!drmmode_crtc->rotate_mem->bo)
 			continue;
 
-		if (drmmode_crtc->rotate_bo->virtual == pPixData) {
-			*bo = drmmode_crtc->rotate_bo;
+		if (drmmode_crtc->rotate_mem->bo->virtual == pPixData) {
+			*bo = drmmode_crtc->rotate_mem->bo;
 			return TRUE;
 		}
 	}
 	return FALSE;
-#endif
-}
-
-static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width,
-			      int height)
-{
-	uint32_t handle;
-	int pitch;
-	int ret;
-
-	return FALSE;
-
-	if (drmmode->mode_fb->width == width &&
-	    drmmode->mode_fb->height == height)
-		return TRUE;
-
-	if (!drmmode->create_new_fb)
-		return FALSE;
-
-	handle = drmmode->create_new_fb(scrn, width, height, &pitch);
-	if (handle == 0)
-		return FALSE;
-
-	ret = drmModeReplaceFB(drmmode->fd, drmmode->fb_id,
-			       width, height,
-			       scrn->depth, scrn->bitsPerPixel, pitch,
-			       handle);
-
-	if (ret)
-		return FALSE;
-
-	drmModeFreeFB(drmmode->mode_fb);
-	drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
-	if (!drmmode->mode_fb)
-		return FALSE;
-
-	return TRUE;
 }
 
-#endif
+#endif /* XF86DRM_MODE */
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index ee51c95..cb0c046 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -32,23 +32,22 @@
 #include "intel_bufmgr.h"
 #include "xf86drmMode.h"
 
+struct _i830_memory;
+
 typedef struct {
     int fd;
     uint32_t fb_id;
     drmModeResPtr mode_res;
     drmModeFBPtr mode_fb;
     int cpp;
-    uint32_t (*create_new_fb)(ScrnInfoPtr pScrn, int width, int height,
-			      int *pitch);
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
-
     drmmode_ptr drmmode;
     drmModeCrtcPtr mode_crtc;
     dri_bo *cursor;
-    dri_bo *rotate_bo;
-    int rotate_fb_id;
+    struct _i830_memory *rotate_mem;
+    unsigned int rotate_fb_id;
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
@@ -62,7 +61,7 @@ typedef struct {
 
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
 			     char *busId, char *driver_name, int cpp);
-extern void drmmode_set_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int width,
+extern Bool drmmode_set_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int width,
 			   int height, int pitch, dri_bo *bo);
 extern Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData,
 				     dri_bo **bo);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2c4ea07..be1cc87 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1741,13 +1741,12 @@ I830DrmModeInit(ScrnInfoPtr pScrn)
 	return FALSE;
     }
 
-    pI830->drmmode.create_new_fb = i830_create_new_fb;
-
     pI830->drmSubFD = pI830->drmmode.fd;
     xfree(bus_id);
 
     pI830->directRenderingType = DRI_NONE;
     pI830->allocate_classic_textures = FALSE;
+    pI830->can_resize = TRUE;
 
     i830_init_bufmgr(pScrn);
 #endif
diff --git a/src/i830_memory.c b/src/i830_memory.c
index f3c55a3..cc271df 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1294,10 +1294,12 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
 
     if (pI830->use_drm_mode) {
 #ifdef XF86DRM_MODE
-	ErrorF("setting kernel fb to new front buffer\n");
-	ErrorF("front_buffer->bo->size: %ld\n", front_buffer->bo->size);
-        drmmode_set_fb(pScrn, &pI830->drmmode, pScrn->virtualX, fb_height,
-		       pScrn->displayWidth * pI830->cpp, front_buffer->bo);
+        if (!drmmode_set_fb(pScrn, &pI830->drmmode, pScrn->virtualX, fb_height,
+			    pScrn->displayWidth * pI830->cpp,
+			    front_buffer->bo)) {
+	    i830_free_memory(pScrn, front_buffer);
+	    return NULL;
+	}
 #endif
     } else if (pI830->FbBase)
 	memset (pI830->FbBase + front_buffer->offset, 0, size);



More information about the Intel-gfx mailing list