summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2010-06-07 10:02:44 -0700
committerKeith Packard <keithp@keithp.com>2010-06-07 10:02:44 -0700
commit2dcf547829c9163f1fb869d0583f7b93a0613294 (patch)
treecf50e678dbe61d1abf10ac5b11c6ea5e1c55fc56
parentd56ea7a852d7090360fe080acec268de55ee908d (diff)
Support RandR 1.4 interface changes for per-crtc pixmapsrandr-1.4
Export crtc setting and scanout buffer allocation functions. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/drmmode_display.c265
-rw-r--r--src/i830.h2
-rw-r--r--src/i830_uxa.c4
3 files changed, 193 insertions, 78 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3ea9b0fe..91835ce0 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -300,27 +300,36 @@ drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
}
+#ifndef RANDR_14_INTERFACE
+typedef enum _xf86CrtcSetFlags {
+ XF86CrtcSetMode = 1, /* mode */
+ XF86CrtcSetOutput = 2, /* outputs */
+ XF86CrtcSetOrigin = 4, /* x/y */
+ XF86CrtcSetTransform = 8, /* transform */
+ XF86CrtcSetRotation = 16, /* rotation */
+ XF86CrtcSetProperty = 32, /* output property */
+ XF86CrtcSetScanoutPixmap = 64, /* scanout pixmap */
+} xf86CrtcSetFlags;
+#endif
+
static Bool
-drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
- Rotation rotation, int x, int y)
+drmmode_set(xf86CrtcPtr crtc, xf86CrtcSetFlags flags)
{
ScrnInfoPtr scrn = crtc->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- int saved_x, saved_y;
- Rotation saved_rotation;
- DisplayModeRec saved_mode;
uint32_t *output_ids;
int output_count = 0;
int ret = TRUE;
int i;
int fb_id;
+ int x, y;
drmModeModeInfo kmode;
- unsigned int pitch = scrn->displayWidth * intel->cpp;
if (drmmode->fb_id == 0) {
+ unsigned int pitch = scrn->displayWidth * intel->cpp;
ret = drmModeAddFB(drmmode->fd,
scrn->virtualX, scrn->virtualY,
scrn->depth, scrn->bitsPerPixel,
@@ -332,16 +341,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
}
}
- saved_mode = crtc->mode;
- saved_x = crtc->x;
- saved_y = crtc->y;
- saved_rotation = crtc->rotation;
-
- crtc->mode = *mode;
- crtc->x = x;
- crtc->y = y;
- crtc->rotation = rotation;
-
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
if (!output_ids) {
ret = FALSE;
@@ -374,15 +373,33 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
crtc->gamma_blue, crtc->gamma_size);
#endif
- drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
-
+ drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
fb_id = drmmode->fb_id;
+ x = crtc->x;
+ y = crtc->y;
if (drmmode_crtc->rotate_fb_id) {
fb_id = drmmode_crtc->rotate_fb_id;
- x = 0;
- y = 0;
+ x = y = 0;
+#ifdef RANDR_14_INTERFACE
+ } else if (crtc->scanoutPixmap) {
+ PixmapPtr pixmap = crtc->scanoutPixmap;
+ struct intel_pixmap *intel_pixmap = i830_get_pixmap_intel(pixmap);
+ if (intel_pixmap) {
+ if (!intel_pixmap->scanout_fb_id) {
+ drmModeAddFB(drmmode->fd,
+ pixmap->drawable.width, pixmap->drawable.height,
+ pixmap->drawable.depth, pixmap->drawable.bitsPerPixel,
+ pixmap->devKind,
+ intel_pixmap->bo->handle,
+ &intel_pixmap->scanout_fb_id);
+ }
+ if (intel_pixmap->scanout_fb_id)
+ fb_id = intel_pixmap->scanout_fb_id;
+ }
+#endif
}
+
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
fb_id, x, y, output_ids, output_count, &kmode);
if (ret)
@@ -406,21 +423,33 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (scrn->pScreen)
xf86_reload_cursors(scrn->pScreen);
done:
- if (!ret) {
- crtc->x = saved_x;
- crtc->y = saved_y;
- crtc->rotation = saved_rotation;
- crtc->mode = saved_mode;
- }
return ret;
}
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
+{
+ return drmmode_set(crtc, XF86CrtcSetMode|XF86CrtcSetOutput|
+ XF86CrtcSetOrigin|XF86CrtcSetTransform|XF86CrtcSetRotation|
+ XF86CrtcSetProperty);
+}
+
static void
drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
{
}
+void
+drmmode_free_scanout_id(ScrnInfoPtr scrn, uint32_t scanout_id)
+{
+ 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;
+ drmModeRmFB(drmmode->fd, scanout_id);
+}
+
static void
drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
{
@@ -466,42 +495,101 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
drmmode_crtc->cursor->handle, 64, 64);
}
-static void *
-drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+/*
+ * Allocate a scanout buffer for rotation support or per-crtc pixmaps,
+ * registering the buffer with the kernel as a frame buffer
+ */
+static dri_bo *
+drmmode_crtc_scanout_allocate(ScrnInfoPtr scrn, int width, int height,
+ int depth, int bpp, uint32_t *fb_id)
{
- ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
intel_screen_private *intel = intel_get_screen_private(scrn);
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_crtc_private_ptr
+ drmmode_crtc = xf86_config->crtc[0]->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- int size, ret;
- unsigned long rotate_pitch;
+ int size;
+ unsigned long pitch;
+ dri_bo *scanout;
+ int ret;
width = i830_pad_drawable_width(width);
- rotate_pitch = width * drmmode->cpp;
- size = rotate_pitch * height;
+ pitch = width * (bpp / 8);
+ size = pitch * height;
- drmmode_crtc->rotate_bo =
- drm_intel_bo_alloc(intel->bufmgr, "rotate", size, 4096);
+ scanout = drm_intel_bo_alloc(intel->bufmgr, "scanout", size, 4096);
- if (!drmmode_crtc->rotate_bo) {
- xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "Couldn't allocate shadow memory for rotated CRTC\n");
+ if (!scanout)
return NULL;
- }
- drm_intel_bo_disable_reuse(drmmode_crtc->rotate_bo);
+ drm_intel_bo_disable_reuse(scanout);
+
+ ret = drmModeAddFB(drmmode->fd, width, height, depth, bpp,
+ pitch, scanout->handle, fb_id);
- 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");
- drm_intel_bo_unreference(drmmode_crtc->rotate_bo);
+ drm_intel_bo_unreference(scanout);
return NULL;
}
- return drmmode_crtc->rotate_bo;
+ return scanout;
+}
+
+/*
+ * Allocate a shadow frame buffer for rotation support
+ */
+static void *
+drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ dri_bo *scanout;
+
+ scanout = drmmode_crtc_scanout_allocate(scrn, width, height,
+ scrn->depth, scrn->bitsPerPixel,
+ &drmmode_crtc->rotate_fb_id);
+
+ if (scanout)
+ drmmode_crtc->rotate_bo = scanout;
+ else
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+ "Couldn't allocate shadow memory for rotated CRTC\n");
+ return scanout;
+}
+
+static PixmapPtr
+drmmode_crtc_scanout_create(ScrnInfoPtr scrn, dri_bo *pixmap_bo, uint32_t fb_id,
+ int width, int height, int depth, int bpp)
+{
+ ScreenPtr screen = scrn->pScreen;
+ unsigned long pitch;
+ PixmapPtr pixmap;
+ struct intel_pixmap *intel_pixmap;
+
+ pitch = i830_pad_drawable_width(width) * (bpp / 8);
+ pixmap = screen->CreatePixmap (screen, 0, 0, depth, 0);
+ if (pixmap == NULL)
+ return NULL;
+
+ screen->ModifyPixmapHeader (pixmap, width, height, depth, bpp, pitch, NULL);
+ i830_set_pixmap_bo(pixmap, pixmap_bo);
+ intel_pixmap = i830_get_pixmap_intel(pixmap);
+ intel_pixmap->scanout_fb_id = fb_id;
+ return pixmap;
+}
+
+static void
+drmmode_crtc_scanout_destroy(ScrnInfoPtr scrn, dri_bo *bo, uint32_t fb_id)
+{
+ 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;
+
+ /* Be sure to sync acceleration before the memory gets
+ * unbound. */
+ drmModeRmFB(drmmode->fd, fb_id);
+ dri_bo_unreference(bo);
}
static PixmapPtr
@@ -510,8 +598,6 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
ScrnInfoPtr scrn = crtc->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
- unsigned long rotate_pitch;
PixmapPtr rotate_pixmap;
if (!data) {
@@ -523,50 +609,55 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
}
}
- rotate_pitch = i830_pad_drawable_width(width) * drmmode->cpp;
- rotate_pixmap = GetScratchPixmapHeader(scrn->pScreen,
- width, height,
- scrn->depth,
- scrn->bitsPerPixel,
- rotate_pitch,
- NULL);
-
- if (rotate_pixmap == NULL) {
+ rotate_pixmap = drmmode_crtc_scanout_create(scrn, data, drmmode_crtc->rotate_fb_id,
+ width, height, scrn->depth, scrn->bitsPerPixel);
+ if (!rotate_pixmap) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "Couldn't allocate shadow pixmap for rotated CRTC\n");
+ "Couldn't allocate pixmap for rotated CRTC\n");
return NULL;
}
-
- if (drmmode_crtc->rotate_bo)
- i830_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
-
intel->shadow_present = TRUE;
return rotate_pixmap;
}
+#ifdef RANDR_14_INTERFACE
+static PixmapPtr
+drmmode_xf86crtc_create_scanout_pixmap(ScrnInfoPtr scrn, int width, int height,
+ Rotation rotations, xf86CrtcScanoutFormat *format)
+{
+ dri_bo *scanout_bo;
+ uint32_t fb_id;
+ PixmapPtr pixmap;
+
+ scanout_bo = drmmode_crtc_scanout_allocate(scrn, width, height, format->depth,
+ format->bitsPerPixel, &fb_id);
+ if (!scanout_bo)
+ return NullPixmap;
+
+ pixmap = drmmode_crtc_scanout_create(scrn, scanout_bo, fb_id, width, height,
+ format->depth, format->bitsPerPixel);
+ if (!pixmap)
+ drmmode_crtc_scanout_destroy(scrn, scanout_bo, fb_id);
+ return pixmap;
+}
+#endif
+
static void
drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
{
ScrnInfoPtr scrn = crtc->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
if (rotate_pixmap) {
- i830_set_pixmap_bo(rotate_pixmap, NULL);
- FreeScratchPixmapHeader(rotate_pixmap);
- }
-
-
- 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;
+ scrn->pScreen->DestroyPixmap(rotate_pixmap);
+ } else if (data) {
+ drmmode_crtc_scanout_destroy(scrn, drmmode_crtc->rotate_bo,
+ drmmode_crtc->rotate_fb_id);
}
+ drmmode_crtc->rotate_fb_id = 0;
+ drmmode_crtc->rotate_bo = NULL;
intel->shadow_present = FALSE;
}
@@ -1385,7 +1476,10 @@ error_out:
}
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
- drmmode_xf86crtc_resize
+ .resize = drmmode_xf86crtc_resize,
+#ifdef RANDR_14_INTERFACE
+ .create_scanout_pixmap = drmmode_xf86crtc_create_scanout_pixmap,
+#endif
};
static void
@@ -1420,6 +1514,16 @@ drm_wakeup_handler(pointer data, int err, pointer p)
drmHandleEvent(drmmode->fd, &drmmode->event_context);
}
+#ifdef RANDR_14_INTERFACE
+static xf86CrtcScanoutFormat drmmode_scanout_formats[] = {
+ { .depth = 8, .bitsPerPixel = 8, .format = PICT_c8 },
+ { .depth = 15, .bitsPerPixel = 16, .format = PICT_x1r5g5b5 },
+ { .depth = 16, .bitsPerPixel = 16, .format = PICT_r5g6b5 },
+ { .depth = 24, .bitsPerPixel = 32, .format = PICT_x8r8g8b8 },
+};
+#define NUM_DRMMODE_SCANOUT_FORMATS (sizeof drmmode_scanout_formats / sizeof drmmode_scanout_formats[0])
+#endif
+
Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -1450,6 +1554,11 @@ Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
drmmode_output_init(scrn, drmmode, i);
+#ifdef RANDR_14_INTERFACE
+ xf86CrtcSetScanoutFormats(scrn, NUM_DRMMODE_SCANOUT_FORMATS,
+ drmmode_scanout_formats);
+#endif
+
xf86InitialConfiguration(scrn, TRUE);
gp.param = I915_PARAM_HAS_PAGEFLIPPING;
diff --git a/src/i830.h b/src/i830.h
index 4e24c779..93074424 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -152,6 +152,7 @@ struct intel_pixmap {
uint32_t batch_write_domain;
uint32_t batch_read_domains;
struct list flush, batch, in_flight;
+ uint32_t scanout_fb_id;
};
#if HAS_DEVPRIVATEKEYREC
@@ -417,6 +418,7 @@ extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
extern int drmmode_output_dpms_status(xf86OutputPtr output);
extern Bool drmmode_do_pageflip(ScreenPtr screen, dri_bo *new_front, void *data);
+extern void drmmode_free_scanout_id(ScrnInfoPtr scrn, uint32_t scanout_id);
static inline intel_screen_private *
intel_get_screen_private(ScrnInfoPtr scrn)
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index bf364f83..0afcab01 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -613,6 +613,10 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
if (priv->bo == bo)
return;
+ if (priv->scanout_fb_id) {
+ drmmode_free_scanout_id(scrn, priv->scanout_fb_id);
+ priv->scanout_fb_id = 0;
+ }
if (list_is_empty(&priv->batch)) {
dri_bo_unreference(priv->bo);
} else if (!drm_intel_bo_is_reusable(priv->bo)) {