diff options
author | Keith Packard <keithp@keithp.com> | 2010-06-07 10:02:44 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2010-06-07 10:02:44 -0700 |
commit | 2dcf547829c9163f1fb869d0583f7b93a0613294 (patch) | |
tree | cf50e678dbe61d1abf10ac5b11c6ea5e1c55fc56 | |
parent | d56ea7a852d7090360fe080acec268de55ee908d (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.c | 265 | ||||
-rw-r--r-- | src/i830.h | 2 | ||||
-rw-r--r-- | src/i830_uxa.c | 4 |
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; @@ -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)) { |