diff options
Diffstat (limited to 'driver/xf86-video-ati/src/drmmode_display.c')
-rw-r--r-- | driver/xf86-video-ati/src/drmmode_display.c | 494 |
1 files changed, 376 insertions, 118 deletions
diff --git a/driver/xf86-video-ati/src/drmmode_display.c b/driver/xf86-video-ati/src/drmmode_display.c index 4c8931eea..63d99b1a8 100644 --- a/driver/xf86-video-ati/src/drmmode_display.c +++ b/driver/xf86-video-ati/src/drmmode_display.c @@ -36,10 +36,17 @@ #include "damagestr.h" #include "micmap.h" #include "xf86cmap.h" +#include "xf86Priv.h" #include "radeon.h" +#include "radeon_bo_helper.h" #include "radeon_glamor.h" +#include "radeon_list.h" #include "radeon_reg.h" +#ifdef RADEON_PIXMAP_SHARING +#include <dri.h> +#endif + #include "drmmode_display.h" /* DPMS */ @@ -91,19 +98,28 @@ RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name) static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, int width, int height, int depth, int bpp, - int pitch, int tiling, + int pitch, struct radeon_bo *bo, struct radeon_surface *psurf) { RADEONInfoPtr info = RADEONPTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; PixmapPtr pixmap; struct radeon_surface *surface; + uint32_t tiling; pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, RADEON_CREATE_PIXMAP_SCANOUT); if (!pixmap) return NULL; + if (pitch <= 0 && + (radeon_bo_get_tiling(bo, &tiling, (uint32_t*)&pitch) != 0 || + pitch <= 0)) { + ErrorF("radeon_bo_get_tiling failed to determine pitch\n"); + pScreen->DestroyPixmap(pixmap); + return NULL; + } + if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height, depth, bpp, pitch, NULL)) { return NULL; @@ -133,6 +149,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); + tiling = radeon_get_pixmap_tiling_flags(pixmap); if (tiling & RADEON_TILING_MICRO) { surface->flags = RADEON_SURF_CLR(surface->flags, MODE); surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); @@ -286,9 +303,15 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) CARD64 ust; int ret; + drmmode_crtc->pending_dpms_mode = mode; + if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { drmVBlank vbl; + /* Wait for any pending flip to finish */ + if (drmmode_crtc->flip_pending) + return; + /* * On->Off transition: record the last vblank time, * sequence number and frame period. @@ -346,14 +369,20 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) drmmode_ptr drmmode = drmmode_crtc->drmmode; /* Disable unused CRTCs */ - if (!crtc->enabled || mode != DPMSModeOn) + if (!crtc->enabled || mode != DPMSModeOn) { + /* Wait for any pending flip to finish */ + if (drmmode_crtc->flip_pending) + return; + drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, NULL, 0, NULL); - else if (drmmode_crtc->dpms_mode != DPMSModeOn) + } else if (drmmode_crtc->dpms_mode != DPMSModeOn) crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); } +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 + static PixmapPtr create_pixmap_for_fbcon(drmmode_ptr drmmode, ScrnInfoPtr pScrn, int fbcon_id) @@ -391,8 +420,8 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, } pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, - fbcon->depth, fbcon->bpp, - fbcon->pitch, 0, bo, NULL); + fbcon->depth, fbcon->bpp, fbcon->pitch, + bo, NULL); info->fbcon_pixmap = pixmap; radeon_bo_unref(bo); out_free_fb: @@ -417,8 +446,6 @@ destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn) info->fbcon_pixmap = NULL; } -#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 - void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -522,13 +549,13 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, int width, int height) { ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; - int aligned_height; - int size; + struct radeon_surface surface; + uint32_t tiling = RADEON_CREATE_PIXMAP_TILING_MACRO; int ret; - unsigned long rotate_pitch; - int base_align; + int pitch; if (scanout->bo) { if (scanout->width == width && scanout->height == height) @@ -537,22 +564,18 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, drmmode_crtc_scanout_destroy(drmmode, scanout); } - rotate_pitch = - RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) - * drmmode->cpp; - aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, 0)); - base_align = drmmode_get_base_align(pScrn, drmmode->cpp, 0); - size = RADEON_ALIGN(rotate_pitch * aligned_height, RADEON_GPU_PAGE_SIZE); - - scanout->bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, - RADEON_GEM_DOMAIN_VRAM, 0); + if (info->ChipFamily >= CHIP_FAMILY_R600) + tiling |= RADEON_CREATE_PIXMAP_TILING_MICRO; + scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth, + tiling, pScrn->bitsPerPixel, + &pitch, &surface, &tiling); if (scanout->bo == NULL) return NULL; radeon_bo_map(scanout->bo, 1); ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth, - pScrn->bitsPerPixel, rotate_pitch, + pScrn->bitsPerPixel, pitch, scanout->bo->handle, &scanout->fb_id); if (ret) { @@ -574,7 +597,6 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, ScrnInfoPtr pScrn = crtc->scrn; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; - unsigned long rotate_pitch; if (scanout->pixmap) { if (scanout->width == width && scanout->height == height) @@ -588,15 +610,11 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, return NULL; } - rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) - * drmmode->cpp; - scanout->pixmap = drmmode_create_bo_pixmap(pScrn, width, height, pScrn->depth, pScrn->bitsPerPixel, - rotate_pitch, - 0, scanout->bo, NULL); + -1, scanout->bo, NULL); if (scanout->pixmap == NULL) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't allocate scanout pixmap for CRTC\n"); @@ -613,10 +631,70 @@ radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure) } static Bool +drmmode_can_use_hw_cursor(xf86CrtcPtr crtc) +{ + RADEONInfoPtr info = RADEONPTR(crtc->scrn); + + /* Check for Option "SWcursor" */ + if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) + return FALSE; + + /* Fall back to SW cursor if the CRTC is transformed */ + if (crtc->transformPresent) + return FALSE; + +#if XF86_CRTC_VERSION >= 4 + /* Xorg doesn't correctly handle cursor position transform in the + * rotation case + */ + if (crtc->driverIsPerformingTransform && + (crtc->rotation & 0xf) != RR_Rotate_0) + return FALSE; +#endif + +#ifdef RADEON_PIXMAP_SHARING + /* HW cursor not supported yet with RandR 1.4 multihead */ + if (!xorg_list_is_empty(&crtc->scrn->pScreen->pixmap_dirty_list)) + return FALSE; +#endif + + return TRUE; +} + +#if XF86_CRTC_VERSION >= 4 + +static Bool +drmmode_handle_transform(xf86CrtcPtr crtc) +{ + RADEONInfoPtr info = RADEONPTR(crtc->scrn); + Bool ret; + + crtc->driverIsPerformingTransform = info->tear_free && + !crtc->transformPresent && crtc->rotation != RR_Rotate_0; + + ret = xf86CrtcRotate(crtc); + + crtc->driverIsPerformingTransform &= ret && crtc->transform_in_use; + + return ret; +} + +#else + +static Bool +drmmode_handle_transform(xf86CrtcPtr crtc) +{ + return xf86CrtcRotate(crtc); +} + +#endif + +static Bool drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) { ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = pScrn->pScreen; RADEONInfoPtr info = RADEONPTR(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; @@ -669,7 +747,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, crtc->x = x; crtc->y = y; crtc->rotation = rotation; - crtc->transformPresent = FALSE; output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); if (!output_ids) { @@ -677,8 +754,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, goto done; } - ScreenPtr pScreen = pScrn->pScreen; - for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; drmmode_output_private_ptr drmmode_output; @@ -691,9 +766,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, output_count++; } - if (!xf86CrtcRotate(crtc)) { + if (!drmmode_handle_transform(crtc)) goto done; - } + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, crtc->gamma_blue, crtc->gamma_size); @@ -715,7 +790,11 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]); drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]); - } else if (info->tear_free || info->shadow_primary) { + } else if (info->tear_free || +#if XF86_CRTC_VERSION >= 4 + crtc->driverIsPerformingTransform || +#endif + info->shadow_primary) { for (i = 0; i < (info->tear_free ? 2 : 1); i++) { drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[i], @@ -741,8 +820,17 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, pBox = RegionExtents(pRegion); pBox->x1 = min(pBox->x1, x); pBox->y1 = min(pBox->y1, y); - pBox->x2 = max(pBox->x2, x + mode->HDisplay); - pBox->y2 = max(pBox->y2, y + mode->VDisplay); + + switch (crtc->rotation & 0xf) { + case RR_Rotate_90: + case RR_Rotate_270: + pBox->x2 = max(pBox->x2, x + mode->VDisplay); + pBox->y2 = max(pBox->y2, y + mode->HDisplay); + break; + default: + pBox->x2 = max(pBox->x2, x + mode->HDisplay); + pBox->y2 = max(pBox->y2, y + mode->VDisplay); + } } } @@ -752,10 +840,16 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, fb_id = drmmode_crtc->scanout[0].fb_id; x = y = 0; - radeon_scanout_update_handler(pScrn, 0, 0, crtc); + radeon_scanout_update_handler(crtc, 0, 0, drmmode_crtc); radeon_bo_wait(drmmode_crtc->scanout[0].bo); } } + + /* Wait for any pending flip to finish */ + do {} while (drmmode_crtc->flip_pending && + drmHandleEvent(drmmode->fd, + &drmmode->event_context) > 0); + if (drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, fb_id, x, y, output_ids, @@ -767,8 +861,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } else ret = TRUE; - if (crtc->scrn->pScreen) - xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen); + if (pScreen) + xf86CrtcSetScreenSubpixelOrder(pScreen); drmmode_crtc->need_modeset = FALSE; @@ -783,9 +877,23 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } } - if (pScrn->pScreen && - !xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) - xf86_reload_cursors(pScrn->pScreen); + /* Compute index of this CRTC into xf86_config->crtc */ + for (i = 0; i < xf86_config->num_crtc; i++) { + if (xf86_config->crtc[i] != crtc) + continue; + + if (!crtc->enabled || drmmode_can_use_hw_cursor(crtc)) + info->hwcursor_disabled &= ~(1 << i); + else + info->hwcursor_disabled |= 1 << i; + + break; + } + +#ifndef HAVE_XF86_CURSOR_RESET_CURSOR + if (!info->hwcursor_disabled) + xf86_reload_cursors(pScreen); +#endif done: if (!ret) { @@ -793,11 +901,9 @@ done: crtc->y = saved_y; crtc->rotation = saved_rotation; crtc->mode = saved_mode; - } -#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3 - else + } else crtc->active = TRUE; -#endif + free(output_ids); return ret; @@ -815,26 +921,103 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; +#if XF86_CRTC_VERSION >= 4 + if (crtc->driverIsPerformingTransform) { + x += crtc->x; + y += crtc->y; + xf86CrtcTransformCursorPos(crtc, &x, &y); + } +#endif + drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); } +#if XF86_CRTC_VERSION >= 4 + +static int +drmmode_cursor_src_offset(Rotation rotation, int width, int height, + int x_dst, int y_dst) +{ + int t; + + switch (rotation & 0xf) { + case RR_Rotate_90: + t = x_dst; + x_dst = height - y_dst - 1; + y_dst = t; + break; + case RR_Rotate_180: + x_dst = width - x_dst - 1; + y_dst = height - y_dst - 1; + break; + case RR_Rotate_270: + t = x_dst; + x_dst = y_dst; + y_dst = width - t - 1; + break; + } + + if (rotation & RR_Reflect_X) + x_dst = width - x_dst - 1; + if (rotation & RR_Reflect_Y) + y_dst = height - y_dst - 1; + + return y_dst * height + x_dst; +} + +#endif + static void drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - int i; uint32_t *ptr; - uint32_t cursor_size = info->cursor_w * info->cursor_h; /* cursor should be mapped already */ ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); - for (i = 0; i < cursor_size; i++) - ptr[i] = cpu_to_le32(image[i]); +#if XF86_CRTC_VERSION >= 4 + if (crtc->driverIsPerformingTransform) { + uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h; + int dstx, dsty; + int srcoffset; + + for (dsty = 0; dsty < cursor_h; dsty++) { + for (dstx = 0; dstx < cursor_w; dstx++) { + srcoffset = drmmode_cursor_src_offset(crtc->rotation, + cursor_w, + cursor_h, + dstx, dsty); + + ptr[dsty * info->cursor_w + dstx] = + cpu_to_le32(image[srcoffset]); + } + } + } else +#endif + { + uint32_t cursor_size = info->cursor_w * info->cursor_h; + int i; + + for (i = 0; i < cursor_size; i++) + ptr[i] = cpu_to_le32(image[i]); + } +} + +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) + +static Bool drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 * image) +{ + if (!drmmode_can_use_hw_cursor(crtc)) + return FALSE; + + drmmode_load_cursor_argb(crtc, image); + return TRUE; } +#endif static void drmmode_hide_cursor (xf86CrtcPtr crtc) @@ -952,7 +1135,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) if (max_height < iter->mode.VDisplay) max_height = iter->mode.VDisplay; } -#ifndef HAS_DIRTYTRACKING2 +#if !defined(HAS_DIRTYTRACKING_ROTATION) && !defined(HAS_DIRTYTRACKING2) if (iter != crtc) { ErrorF("Cannot do multiple crtcs without X server dirty tracking 2 interface\n"); return FALSE; @@ -991,6 +1174,9 @@ static xf86CrtcFuncsRec drmmode_crtc_funcs = { .show_cursor = drmmode_show_cursor, .hide_cursor = drmmode_hide_cursor, .load_cursor_argb = drmmode_load_cursor_argb, +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) + .load_cursor_argb_check = drmmode_load_cursor_argb_check, +#endif .gamma_set = drmmode_crtc_gamma_set, .shadow_create = drmmode_crtc_shadow_create, @@ -1043,6 +1229,8 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]); drmmode_crtc->drmmode = drmmode; + drmmode_crtc->dpms_mode = DPMSModeOff; + drmmode_crtc->pending_dpms_mode = DPMSModeOff; crtc->driver_private = drmmode_crtc; drmmode_crtc_hw_id(crtc); @@ -1168,9 +1356,16 @@ drmmode_output_dpms(xf86OutputPtr output, int mode) if (!koutput) return; - if (mode != DPMSModeOn && crtc) + if (mode != DPMSModeOn && crtc) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_do_crtc_dpms(crtc, mode); + /* Wait for any pending flip to finish */ + if (drmmode_crtc->flip_pending) + return; + } + drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, drmmode_output->dpms_enum_id, mode); @@ -1898,7 +2093,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, info->shadow_primary ? RADEON_GEM_DOMAIN_GTT : - RADEON_GEM_DOMAIN_VRAM, 0); + RADEON_GEM_DOMAIN_VRAM, + tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0); if (!info->front_bo) goto fail; @@ -1999,56 +2195,77 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { drmmode_xf86crtc_resize }; -static void -drmmode_flip_free(drmmode_flipevtcarrier_ptr flipcarrier) +void +drmmode_clear_pending_flip(xf86CrtcPtr crtc) { - drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - free(flipcarrier); + drmmode_crtc->flip_pending = FALSE; - if (--flipdata->flip_count > 0) - return; + if (!crtc->enabled || + (drmmode_crtc->pending_dpms_mode != DPMSModeOn && + drmmode_crtc->dpms_mode != drmmode_crtc->pending_dpms_mode)) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + int o; + + for (o = 0; o < xf86_config->num_output; o++) { + xf86OutputPtr output = xf86_config->output[o]; - free(flipdata); + if (output->crtc != crtc) + continue; + + drmmode_output_dpms(output, drmmode_crtc->pending_dpms_mode); + } + + drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode); + } } static void -drmmode_flip_abort(ScrnInfoPtr scrn, void *event_data) +drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) { - drmmode_flipevtcarrier_ptr flipcarrier = event_data; - drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; + drmmode_flipdata_ptr flipdata = event_data; - if (flipdata->flip_count == 1) - flipdata->abort(scrn, flipdata->event_data); + if (--flipdata->flip_count == 0) { + if (!flipdata->fe_crtc) + flipdata->fe_crtc = crtc; + flipdata->abort(flipdata->fe_crtc, flipdata->event_data); + free(flipdata); + } - drmmode_flip_free(flipcarrier); + drmmode_clear_pending_flip(crtc); } static void -drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data) +drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data) { - drmmode_flipevtcarrier_ptr flipcarrier = event_data; - drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; + RADEONInfoPtr info = RADEONPTR(crtc->scrn); + drmmode_flipdata_ptr flipdata = event_data; /* Is this the event whose info shall be delivered to higher level? */ - if (flipcarrier->dispatch_me) { + if (crtc == flipdata->fe_crtc) { /* Yes: Cache msc, ust for later delivery. */ flipdata->fe_frame = frame; flipdata->fe_usec = usec; } - if (flipdata->flip_count == 1) { - /* Deliver cached msc, ust from reference crtc to flip event handler */ - if (flipdata->event_data) - flipdata->handler(scrn, flipdata->fe_frame, - flipdata->fe_usec, - flipdata->event_data); + if (--flipdata->flip_count == 0) { + /* Deliver MSC & UST from reference/current CRTC to flip event + * handler + */ + if (flipdata->fe_crtc) + flipdata->handler(flipdata->fe_crtc, flipdata->fe_frame, + flipdata->fe_usec, flipdata->event_data); + else + flipdata->handler(crtc, frame, usec, flipdata->event_data); /* Release framebuffer */ - drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id); + drmModeRmFB(info->drmmode.fd, flipdata->old_fb_id); + + free(flipdata); } - drmmode_flip_free(flipcarrier); + drmmode_clear_pending_flip(crtc); } @@ -2070,6 +2287,9 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) int i, num_dvi = 0, num_hdmi = 0; drmModeResPtr mode_res; unsigned int crtcs_needed = 0; +#ifdef RADEON_PIXMAP_SHARING + char *bus_id_string, *provider_name; +#endif xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); @@ -2112,7 +2332,11 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) drmmode_clones_init(pScrn, drmmode, mode_res); #ifdef RADEON_PIXMAP_SHARING - xf86ProviderSetup(pScrn, NULL, "radeon"); + bus_id_string = DRICreatePCIBusID(info->PciInfo); + XNFasprintf(&provider_name, "%s @ %s", pScrn->chipset, bus_id_string); + free(bus_id_string); + xf86ProviderSetup(pScrn, NULL, provider_name); + free(provider_name); #endif xf86InitialConfiguration(pScrn, TRUE); @@ -2146,8 +2370,10 @@ void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) { + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); + int c; if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited) return; @@ -2158,6 +2384,14 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, drm_wakeup_handler, drmmode); } + + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + drmmode_crtc_scanout_destroy(&info->drmmode, &drmmode_crtc->scanout[0]); + drmmode_crtc_scanout_destroy(&info->drmmode, &drmmode_crtc->scanout[1]); + } } @@ -2251,8 +2485,8 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, crtc->rotation = crtc->desiredRotation; crtc->x = crtc->desiredX; crtc->y = crtc->desiredY; - if (!xf86CrtcRotate(crtc)) - return FALSE; + if (!drmmode_handle_transform(crtc)) + return FALSE; } } return TRUE; @@ -2347,10 +2581,12 @@ void radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); drmModeResPtr mode_res; - int i, j; + int i, j, s; Bool found; Bool changed = FALSE; + int num_dvi = 0, num_hdmi = 0; mode_res = drmModeGetResources(drmmode->fd); if (!mode_res) @@ -2386,25 +2622,53 @@ restart_destroy: for (i = 0; i < mode_res->count_connectors; i++) { found = FALSE; - for (j = 0; j < config->num_output; j++) { - xf86OutputPtr output = config->output[j]; - drmmode_output_private_ptr drmmode_output; + for (s = 0; !found && s < xf86NumScreens; s++) { + ScrnInfoPtr loop_scrn = xf86Screens[s]; + xf86CrtcConfigPtr loop_config = + XF86_CRTC_CONFIG_PTR(loop_scrn); - drmmode_output = output->driver_private; - if (mode_res->connectors[i] == drmmode_output->output_id) { - found = TRUE; - break; + if (strcmp(loop_scrn->driverName, scrn->driverName) || + RADEONEntPriv(loop_scrn) != pRADEONEnt) + continue; + + for (j = 0; !found && j < loop_config->num_output; j++) { + xf86OutputPtr output = loop_config->output[j]; + drmmode_output_private_ptr drmmode_output; + + drmmode_output = output->driver_private; + if (mode_res->connectors[i] == + drmmode_output->output_id) { + found = TRUE; + + switch(drmmode_output->mode_output->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_DVIA: + num_dvi++; + break; + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + num_hdmi++; + break; + } + } } } if (found) continue; - changed = TRUE; - drmmode_output_init(scrn, drmmode, mode_res, i, NULL, NULL, 1); + if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi, + &num_hdmi, 1) != 0) + changed = TRUE; } - if (changed) { + if (changed && dixPrivateKeyRegistered(rrPrivKey)) { +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) RRSetChanged(xf86ScrnToScreen(scrn)); +#else + rrScrPrivPtr rrScrPriv = rrGetScrPriv(scrn->pScreen); + rrScrPriv->changed = TRUE; +#endif RRTellChanged(xf86ScrnToScreen(scrn)); } @@ -2484,14 +2748,14 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, { RADEONInfoPtr info = RADEONPTR(scrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc = NULL; drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; unsigned int pitch; int i; uint32_t tiling_flags = 0; drmmode_flipdata_ptr flipdata; - drmmode_flipevtcarrier_ptr flipcarrier = NULL; - struct radeon_drm_queue_entry *drm_queue = NULL; + uintptr_t drm_queue_seq = 0; if (info->allowColorTiling) { if (info->ChipFamily >= CHIP_FAMILY_R600) @@ -2533,35 +2797,29 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, */ flipdata->event_data = data; - flipdata->drmmode = drmmode; flipdata->handler = handler; flipdata->abort = abort; for (i = 0; i < config->num_crtc; i++) { - if (!config->crtc[i]->enabled) + crtc = config->crtc[i]; + + if (!crtc->enabled) continue; flipdata->flip_count++; - drmmode_crtc = config->crtc[i]->driver_private; - - flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec)); - if (!flipcarrier) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "flip queue: carrier alloc failed.\n"); - goto error; - } + drmmode_crtc = crtc->driver_private; /* Only the reference crtc will finally deliver its page flip * completion event. All other crtc's events will be discarded. */ - flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id); - flipcarrier->flipdata = flipdata; - - drm_queue = radeon_drm_queue_alloc(scrn, client, id, - flipcarrier, - drmmode_flip_handler, - drmmode_flip_abort); - if (!drm_queue) { + if (drmmode_crtc->hw_id == ref_crtc_hw_id) + flipdata->fe_crtc = crtc; + + drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, + flipdata, + drmmode_flip_handler, + drmmode_flip_abort); + if (!drm_queue_seq) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue event entry failed.\n"); goto error; @@ -2569,13 +2827,13 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, - drm_queue)) { + (void*)drm_queue_seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed: %s\n", strerror(errno)); goto error; } - flipcarrier = NULL; - drm_queue = NULL; + drmmode_crtc->flip_pending = TRUE; + drm_queue_seq = 0; } if (flipdata->flip_count > 0) @@ -2587,10 +2845,10 @@ error: drmmode->fb_id = flipdata->old_fb_id; } - if (drm_queue) - radeon_drm_abort_entry(drm_queue); - else if (flipcarrier) - drmmode_flip_abort(scrn, flipcarrier); + if (drm_queue_seq) + radeon_drm_abort_entry(drm_queue_seq); + else if (crtc) + drmmode_flip_abort(crtc, flipdata); else if (flipdata && flipdata->flip_count <= 1) free(flipdata); |