summaryrefslogtreecommitdiff
path: root/driver/xf86-video-ati/src/drmmode_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/xf86-video-ati/src/drmmode_display.c')
-rw-r--r--driver/xf86-video-ati/src/drmmode_display.c494
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);