[Intel-gfx] [RFC] resize & rotate support for KMS
Jesse Barnes
jbarnes at virtuousgeek.org
Thu Jan 29 23:27:38 CET 2009
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.
Thanks,
--
Jesse Barnes, Intel Open Source Technology Center
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 4994251..99bbea2 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,105 @@ 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,
+ "Allocate 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];
+ drmModeCrtcPtr crtc_mode;
+
+ drmmode_crtc = config->crtc[i]->driver_private;
+
+ crtc_mode = drmModeGetCrtc(drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id);
+
+ if (!crtc->enabled || crtc->transform_in_use ||
+ !crtc_mode->mode_valid)
+ 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,
+ &crtc_mode->mode);
+ 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 +235,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 +263,19 @@ 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)
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
+ ret = FALSE;
+ } else {
ret = TRUE;
+ }
done:
if (!ret) {
@@ -261,36 +344,42 @@ 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;
- 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);
+ drmmode_crtc->rotate_bo = dri_bo_alloc(pI830->bufmgr, "rotated crtc",
+ size, 4096);
if (!drmmode_crtc->rotate_bo) {
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_bo);
ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
crtc->scrn->bitsPerPixel, rotate_pitch,
drmmode_crtc->rotate_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_bo);
+ dri_bo_unreference(drmmode_crtc->rotate_bo);
+ drmmode_crtc->rotate_bo = NULL;
+ return NULL;
+ }
return drmmode_crtc->rotate_bo->virtual;
-#endif
- return NULL;
}
static PixmapPtr
@@ -305,7 +394,8 @@ 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;
+ rotate_pitch = i830_pad_drawable_width(width, drmmode->cpp) *
+ drmmode->cpp;
rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
width, height,
@@ -316,29 +406,33 @@ 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_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)
{
+ 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_bo);
+ 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;
}
static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
@@ -353,13 +447,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 +562,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 +656,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);
@@ -614,16 +726,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr
drmmode, char *busId,
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 +736,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;
@@ -665,44 +763,7 @@ Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer
pPixData, dri_bo **bo)
}
}
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..cebd109 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -38,17 +38,14 @@ typedef struct {
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;
+ unsigned int rotate_fb_id;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
@@ -62,7 +59,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