summaryrefslogtreecommitdiff
path: root/src/drmmode_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r--src/drmmode_display.c1389
1 files changed, 929 insertions, 460 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 369c1efc..a58f24dd 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -34,8 +34,10 @@
#include <time.h>
#include "cursorstr.h"
#include "damagestr.h"
+#include "inputstr.h"
#include "list.h"
#include "micmap.h"
+#include "mipointrst.h"
#include "xf86cmap.h"
#include "xf86Priv.h"
#include "radeon.h"
@@ -43,7 +45,9 @@
#include "radeon_glamor.h"
#include "radeon_reg.h"
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,99,1,0)
#include <dri.h>
+#endif
#include "drmmode_display.h"
@@ -98,24 +102,15 @@ RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
}
-/* Wait for the boolean condition to be FALSE */
-#define drmmode_crtc_wait_pending_event(drmmode_crtc, fd, condition) \
- do {} while ((condition) && \
- drmHandleEvent(fd, &drmmode_crtc->drmmode->event_context) \
- > 0);
-
-
static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
int width, int height,
int depth, int bpp,
int pitch,
- struct radeon_bo *bo, struct radeon_surface *psurf)
+ struct radeon_buffer *bo)
{
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);
@@ -133,48 +128,16 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
if (!radeon_set_pixmap_bo(pixmap, bo))
goto fail;
- if (info->ChipFamily >= CHIP_FAMILY_R600) {
- surface = radeon_get_pixmap_surface(pixmap);
- if (surface && psurf)
- *surface = *psurf;
- else if (surface) {
- memset(surface, 0, sizeof(struct radeon_surface));
- surface->npix_x = width;
- surface->npix_y = height;
- surface->npix_z = 1;
- surface->blk_w = 1;
- surface->blk_h = 1;
- surface->blk_d = 1;
- surface->array_size = 1;
- surface->last_level = 0;
- surface->bpe = bpp / 8;
- surface->nsamples = 1;
- surface->flags = RADEON_SURF_SCANOUT;
- /* we are requiring a recent enough libdrm version */
- 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);
- }
- if (tiling & RADEON_TILING_MACRO) {
- surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
- surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- if (radeon_surface_best(info->surf_man, surface)) {
- goto fail;
- }
- if (radeon_surface_init(info->surf_man, surface)) {
- goto fail;
- }
- }
+ if (info->surf_man && !info->use_glamor) {
+ struct radeon_surface *surface = radeon_get_pixmap_surface(pixmap);
+
+ if (!radeon_surface_initialize(info, surface, width, height, bpp / 8,
+ radeon_get_pixmap_tiling_flags(pixmap), 0))
+ goto fail;
}
if (!info->use_glamor ||
- radeon_glamor_create_textured_pixmap(pixmap,
- radeon_get_pixmap_private(pixmap)))
+ radeon_glamor_create_textured_pixmap(pixmap, bo))
return pixmap;
fail:
@@ -338,8 +301,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
uint32_t seq;
- drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
- drmmode_crtc->flip_pending);
+ radeon_drm_wait_pending_flip(crtc);
/*
* On->Off transition: record the last vblank time,
@@ -364,6 +326,9 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
nominal_frame_rate /= pix_in_frame;
drmmode_crtc->dpms_last_fps = nominal_frame_rate;
}
+
+ drmmode_crtc->dpms_mode = mode;
+ radeon_drm_queue_handle_deferred(crtc);
} else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) {
/*
* Off->On transition: calculate and accumulate the
@@ -381,8 +346,9 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
drmmode_crtc->interpolated_vblanks += delta_seq;
}
+
+ drmmode_crtc->dpms_mode = DPMSModeOn;
}
- drmmode_crtc->dpms_mode = mode;
}
static void
@@ -393,8 +359,7 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
/* Disable unused CRTCs */
if (!crtc->enabled || mode != DPMSModeOn) {
- drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
- drmmode_crtc->flip_pending);
+ drmmode_do_crtc_dpms(crtc, DPMSModeOff);
drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
0, 0, 0, NULL, 0, NULL);
drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
@@ -410,7 +375,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
RADEONInfoPtr info = RADEONPTR(pScrn);
PixmapPtr pixmap = info->fbcon_pixmap;
- struct radeon_bo *bo;
+ struct radeon_buffer *bo;
drmModeFBPtr fbcon;
struct drm_gem_flink flink;
@@ -418,7 +383,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
return pixmap;
fbcon = drmModeGetFB(pRADEONEnt->fd, fbcon_id);
- if (fbcon == NULL)
+ if (!fbcon)
return NULL;
if (fbcon->depth != pScrn->depth ||
@@ -433,18 +398,26 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
goto out_free_fb;
}
- bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
- if (bo == NULL) {
+ bo = calloc(1, sizeof(struct radeon_buffer));
+ if (!bo) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Couldn't allocate bo for fbcon handle\n");
+ "Couldn't allocate BO for fbcon handle\n");
+ goto out_free_fb;
+ }
+ bo->ref_count = 1;
+
+ bo->bo.radeon = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
+ if (!bo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't open BO for fbcon handle\n");
goto out_free_fb;
}
pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
fbcon->depth, fbcon->bpp, fbcon->pitch,
- bo, NULL);
+ bo);
info->fbcon_pixmap = pixmap;
- radeon_bo_unref(bo);
+ radeon_buffer_unref(&bo);
out_free_fb:
drmModeFreeFB(fbcon);
return pixmap;
@@ -458,8 +431,14 @@ destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn)
/* XXX: The current GPUVM support in the kernel doesn't allow removing
* the virtual address range for this BO, so we need to keep around
* the pixmap to avoid breaking glamor with GPUVM
+ *
+ * Similarly, need to keep around the pixmap with current glamor, to
+ * avoid issues due to a GEM handle lifetime conflict between us and
+ * Mesa
*/
- if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN)
+ if (info->use_glamor &&
+ (info->ChipFamily >= CHIP_FAMILY_CAYMAN ||
+ xorgGetVersion() >= XORG_VERSION_NUMERIC(1,19,99,1,0)))
return;
if (info->fbcon_pixmap)
@@ -527,16 +506,21 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
scanout->pixmap = NULL;
}
- if (scanout->bo) {
- radeon_bo_unmap(scanout->bo);
- radeon_bo_unref(scanout->bo);
- scanout->bo = NULL;
- }
+ radeon_buffer_unref(&scanout->bo);
}
void
-drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
+drmmode_crtc_scanout_free(xf86CrtcPtr crtc)
{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (drmmode_crtc->scanout_update_pending) {
+ radeon_drm_wait_pending_flip(crtc);
+ radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
+ drmmode_crtc->scanout_update_pending = 0;
+ radeon_drm_queue_handle_deferred(crtc);
+ }
+
drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
&drmmode_crtc->scanout[0]);
drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
@@ -579,7 +563,7 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
width, height,
pScrn->depth,
pScrn->bitsPerPixel,
- pitch, scanout->bo, NULL);
+ pitch, scanout->bo);
if (!scanout->pixmap) {
ErrorF("failed to create CRTC scanout pixmap\n");
goto error;
@@ -691,13 +675,9 @@ drmmode_handle_transform(xf86CrtcPtr crtc)
Bool ret;
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
- if (crtc->transformPresent || crtc->rotation != RR_Rotate_0)
- crtc->driverIsPerformingTransform = XF86DriverTransformOutput;
- else
- crtc->driverIsPerformingTransform = XF86DriverTransformNone;
+ crtc->driverIsPerformingTransform = XF86DriverTransformOutput;
#else
crtc->driverIsPerformingTransform = !crtc->transformPresent &&
- crtc->rotation != RR_Rotate_0 &&
(crtc->rotation & 0xf) == RR_Rotate_0;
#endif
@@ -742,7 +722,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list,
ent) {
if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
- dirty->slave_dst =
+ dirty->secondary_dst =
drmmode_crtc->scanout[scanout_id].pixmap;
break;
}
@@ -757,8 +737,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
gc, 0, 0, mode->HDisplay, mode->VDisplay,
0, 0);
FreeScratchGC(gc);
- radeon_cs_flush_indirect(scrn);
- radeon_bo_wait(drmmode_crtc->scanout[0].bo);
+ radeon_finish(scrn, drmmode_crtc->scanout[0].bo);
}
}
@@ -788,8 +767,8 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
if (drmmode_crtc->scanout[scanout_id].pixmap &&
(!drmmode_crtc->tear_free ||
drmmode_crtc->scanout[scanout_id ^ 1].pixmap)) {
- RegionPtr region;
- BoxPtr box;
+ BoxRec extents = { .x1 = 0, .y1 = 0,
+ .x2 = scrn->virtualX, .y2 = scrn->virtualY };
if (!drmmode_crtc->scanout_damage) {
drmmode_crtc->scanout_damage =
@@ -801,22 +780,20 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_crtc->scanout_damage);
}
- region = DamageRegion(drmmode_crtc->scanout_damage);
- RegionUninit(region);
- region->data = NULL;
- box = RegionExtents(region);
- box->x1 = 0;
- box->y1 = 0;
- box->x2 = max(box->x2, scrn->virtualX);
- box->y2 = max(box->y2, scrn->virtualY);
-
*fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
*x = *y = 0;
- radeon_scanout_do_update(crtc, scanout_id,
- screen->GetWindowPixmap(screen->root),
- box);
- radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo);
+ if (radeon_scanout_do_update(crtc, scanout_id,
+ screen->GetWindowPixmap(screen->root),
+ extents)) {
+ RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage));
+ radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo);
+
+ if (!drmmode_crtc->flip_pending) {
+ radeon_drm_abort_entry(drmmode_crtc->
+ scanout_update_pending);
+ }
+ }
}
}
@@ -888,6 +865,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ Bool handle_deferred = FALSE;
unsigned scanout_id = 0;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int saved_x, saved_y;
@@ -920,9 +898,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_crtc_update_tear_free(crtc);
if (drmmode_crtc->tear_free)
scanout_id = drmmode_crtc->scanout_id;
-
- drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, crtc->gamma_green,
- crtc->gamma_blue, crtc->gamma_size);
+ else
+ drmmode_crtc->scanout_id = 0;
if (drmmode_crtc->prime_scanout_pixmap) {
drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id,
@@ -942,11 +919,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (!fb)
fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root));
if (!fb) {
- fb = radeon_fb_create(pRADEONEnt->fd, pScrn->virtualX,
- pScrn->virtualY, pScrn->depth,
- pScrn->bitsPerPixel,
+ fb = radeon_fb_create(pScrn, pRADEONEnt->fd,
+ pScrn->virtualX, pScrn->virtualY,
pScrn->displayWidth * info->pixel_bytes,
- info->front_bo->handle);
+ info->front_buffer->bo.radeon->handle);
/* Prevent refcnt of ad-hoc FBs from reaching 2 */
drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
drmmode_crtc->fb = fb;
@@ -956,8 +932,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
goto done;
}
- drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
- drmmode_crtc->flip_pending);
+ radeon_drm_wait_pending_flip(crtc);
+ handle_deferred = TRUE;
if (!drmmode_set_mode(crtc, fb, mode, x, y))
goto done;
@@ -1009,14 +985,17 @@ done:
if (drmmode_crtc->scanout[scanout_id].pixmap &&
fb != radeon_pixmap_get_fb(drmmode_crtc->
- scanout[scanout_id].pixmap))
- drmmode_crtc_scanout_free(drmmode_crtc);
- else if (!drmmode_crtc->tear_free) {
+ scanout[scanout_id].pixmap)) {
+ drmmode_crtc_scanout_free(crtc);
+ } else if (!drmmode_crtc->tear_free) {
drmmode_crtc_scanout_destroy(drmmode,
&drmmode_crtc->scanout[1]);
}
}
+ if (handle_deferred)
+ radeon_drm_queue_handle_deferred(crtc);
+
return ret;
}
@@ -1040,6 +1019,9 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
}
#endif
+ drmmode_crtc->cursor_x = x;
+ drmmode_crtc->cursor_y = y;
+
drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
}
@@ -1078,29 +1060,62 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height,
#endif
-static uint32_t
-drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb)
+static Bool
+drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied,
+ Bool *apply_gamma)
{
- uint32_t alpha = argb >> 24;
+ uint32_t alpha = *argb >> 24;
uint32_t rgb[3];
int i;
- if (!alpha)
- return 0;
+ if (premultiplied) {
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0)
+ if (alpha == 0 && (*argb & 0xffffff) != 0) {
+ /* Doesn't look like premultiplied alpha */
+ *premultiplied = FALSE;
+ return FALSE;
+ }
+#endif
- if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
- return argb;
+ if (!(*apply_gamma))
+ return TRUE;
+
+ if (*argb > (alpha | alpha << 8 | alpha << 16 | alpha << 24)) {
+ /* Un-premultiplied R/G/B would overflow gamma LUT,
+ * don't apply gamma correction
+ */
+ *apply_gamma = FALSE;
+ return FALSE;
+ }
+ }
+
+ if (!alpha) {
+ *argb = 0;
+ return TRUE;
+ }
- /* Un-premultiply alpha */
+ /* Extract RGB */
for (i = 0; i < 3; i++)
- rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha;
+ rgb[i] = (*argb >> (i * 8)) & 0xff;
- /* Apply gamma correction and pre-multiply alpha */
- rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff;
- rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff;
- rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff;
+ if (premultiplied) {
+ /* Un-premultiply alpha */
+ for (i = 0; i < 3; i++)
+ rgb[i] = rgb[i] * 0xff / alpha;
+ }
+
+ if (*apply_gamma) {
+ rgb[0] = crtc->gamma_blue[rgb[0]] >> 8;
+ rgb[1] = crtc->gamma_green[rgb[1]] >> 8;
+ rgb[2] = crtc->gamma_red[rgb[2]] >> 8;
+ }
- return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+ /* Premultiply alpha */
+ for (i = 0; i < 3; i++)
+ rgb[i] = rgb[i] * alpha / 0xff;
+
+ *argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+ return TRUE;
}
static void
@@ -1109,10 +1124,21 @@ 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;
+ unsigned id = drmmode_crtc->cursor_id;
+ Bool premultiplied = TRUE;
+ Bool apply_gamma = TRUE;
+ uint32_t argb;
uint32_t *ptr;
+ if (drmmode_crtc->cursor &&
+ XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor)
+ id ^= 1;
+
/* cursor should be mapped already */
- ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
+ ptr = (uint32_t *)(drmmode_crtc->cursor_bo[id]->ptr);
+
+ if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
+ apply_gamma = FALSE;
#if XF86_CRTC_VERSION < 7
if (crtc->driverIsPerformingTransform) {
@@ -1120,16 +1146,19 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
int dstx, dsty;
int srcoffset;
+retry_transform:
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);
+ argb = image[srcoffset];
+ if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied,
+ &apply_gamma))
+ goto retry_transform;
- ptr[dsty * info->cursor_w + dstx] =
- cpu_to_le32(drmmode_cursor_gamma(crtc,
- image[srcoffset]));
+ ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb);
}
}
} else
@@ -1138,8 +1167,20 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
uint32_t cursor_size = info->cursor_w * info->cursor_h;
int i;
- for (i = 0; i < cursor_size; i++)
- ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i]));
+retry:
+ for (i = 0; i < cursor_size; i++) {
+ argb = image[i];
+ if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied,
+ &apply_gamma))
+ goto retry;
+
+ ptr[i] = cpu_to_le32(argb);
+ }
+ }
+
+ if (id != drmmode_crtc->cursor_id) {
+ drmmode_crtc->cursor_id = id;
+ crtc->funcs->show_cursor(crtc);
}
}
@@ -1166,7 +1207,7 @@ drmmode_hide_cursor (xf86CrtcPtr crtc)
drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
info->cursor_w, info->cursor_h);
-
+ drmmode_crtc->cursor = NULL;
}
static void
@@ -1176,56 +1217,73 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
- uint32_t handle = drmmode_crtc->cursor_bo->handle;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ CursorPtr cursor = xf86_config->cursor;
+ int xhot = cursor->bits->xhot;
+ int yhot = cursor->bits->yhot;
static Bool use_set_cursor2 = TRUE;
+ struct drm_mode_cursor2 arg;
+
+ drmmode_crtc->cursor = xf86_config->cursor;
+
+ memset(&arg, 0, sizeof(arg));
+
+ arg.handle = drmmode_crtc->cursor_bo[drmmode_crtc->cursor_id]->handle;
+ arg.flags = DRM_MODE_CURSOR_BO;
+ arg.crtc_id = drmmode_crtc->mode_crtc->crtc_id;
+ arg.width = info->cursor_w;
+ arg.height = info->cursor_h;
+
+ if (crtc->rotation != RR_Rotate_0 &&
+ crtc->rotation != (RR_Rotate_180 | RR_Reflect_X |
+ RR_Reflect_Y)) {
+ int t;
+
+ /* Reflect & rotate hotspot position */
+ if (crtc->rotation & RR_Reflect_X)
+ xhot = info->cursor_w - xhot - 1;
+ if (crtc->rotation & RR_Reflect_Y)
+ yhot = info->cursor_h - yhot - 1;
+
+ switch (crtc->rotation & 0xf) {
+ case RR_Rotate_90:
+ t = xhot;
+ xhot = yhot;
+ yhot = info->cursor_w - t - 1;
+ break;
+ case RR_Rotate_180:
+ xhot = info->cursor_w - xhot - 1;
+ yhot = info->cursor_h - yhot - 1;
+ break;
+ case RR_Rotate_270:
+ t = xhot;
+ xhot = info->cursor_h - yhot - 1;
+ yhot = t;
+ }
+ }
+
+ if (xhot != drmmode_crtc->cursor_xhot || yhot != drmmode_crtc->cursor_yhot) {
+ arg.flags |= DRM_MODE_CURSOR_MOVE;
+ arg.x = drmmode_crtc->cursor_x += drmmode_crtc->cursor_xhot - xhot;
+ arg.y = drmmode_crtc->cursor_y += drmmode_crtc->cursor_yhot - yhot;
+ drmmode_crtc->cursor_xhot = xhot;
+ drmmode_crtc->cursor_yhot = yhot;
+ }
if (use_set_cursor2) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
- CursorPtr cursor = xf86_config->cursor;
- int xhot = cursor->bits->xhot;
- int yhot = cursor->bits->yhot;
int ret;
- if (crtc->rotation != RR_Rotate_0 &&
- crtc->rotation != (RR_Rotate_180 | RR_Reflect_X |
- RR_Reflect_Y)) {
- int t;
-
- /* Reflect & rotate hotspot position */
- if (crtc->rotation & RR_Reflect_X)
- xhot = info->cursor_w - xhot - 1;
- if (crtc->rotation & RR_Reflect_Y)
- yhot = info->cursor_h - yhot - 1;
-
- switch (crtc->rotation & 0xf) {
- case RR_Rotate_90:
- t = xhot;
- xhot = yhot;
- yhot = info->cursor_w - t - 1;
- break;
- case RR_Rotate_180:
- xhot = info->cursor_w - xhot - 1;
- yhot = info->cursor_h - yhot - 1;
- break;
- case RR_Rotate_270:
- t = xhot;
- xhot = info->cursor_h - yhot - 1;
- yhot = t;
- }
- }
+ arg.hot_x = xhot;
+ arg.hot_y = yhot;
- ret =
- drmModeSetCursor2(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
- handle, info->cursor_w, info->cursor_h,
- xhot, yhot);
- if (ret == -EINVAL)
+ ret = drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR2, &arg);
+ if (ret == -1 && errno == EINVAL)
use_set_cursor2 = FALSE;
else
return;
}
- drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
- info->cursor_w, info->cursor_h);
+ drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR, &arg);
}
/* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and
@@ -1300,12 +1358,12 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
- PixmapStopDirtyTracking(dirty->src, dirty->slave_dst);
+ PixmapStopDirtyTracking(dirty->src, dirty->secondary_dst);
break;
}
}
- drmmode_crtc_scanout_free(drmmode_crtc);
+ drmmode_crtc_scanout_free(crtc);
drmmode_crtc->prime_scanout_pixmap = NULL;
if (!ppix)
@@ -1320,7 +1378,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
ppix->drawable.width,
ppix->drawable.height)) {
- drmmode_crtc_scanout_free(drmmode_crtc);
+ drmmode_crtc_scanout_free(crtc);
return FALSE;
}
@@ -1394,9 +1452,10 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
xf86CrtcPtr crtc;
drmmode_crtc_private_ptr drmmode_crtc;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ RADEONInfoPtr info = RADEONPTR(pScrn);
- crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
- if (crtc == NULL)
+ crtc = xf86CrtcCreate(pScrn, &info->drmmode_crtc_funcs);
+ if (!crtc)
return 0;
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
@@ -1414,6 +1473,72 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
return 1;
}
+/*
+ * Update all of the property values for an output
+ */
+static void
+drmmode_output_update_properties(xf86OutputPtr output)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ int i, j, k;
+ int err;
+ drmModeConnectorPtr koutput;
+
+ /* Use the most recently fetched values from the kernel */
+ koutput = drmmode_output->mode_output;
+
+ if (!koutput)
+ return;
+
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+
+ for (j = 0; j < koutput->count_props; j++) {
+ if (koutput->props[j] != p->mode_prop->prop_id)
+ continue;
+
+ /* Check to see if the property value has changed */
+ if (koutput->prop_values[j] == p->value)
+ break;
+
+ p->value = koutput->prop_values[j];
+
+ if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+ INT32 value = p->value;
+
+ err = RRChangeOutputProperty(output->randr_output,
+ p->atoms[0], XA_INTEGER,
+ 32, PropModeReplace, 1,
+ &value, FALSE, TRUE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n",
+ err);
+ }
+ } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+ for (k = 0; k < p->mode_prop->count_enums; k++) {
+ if (p->mode_prop->enums[k].value == p->value)
+ break;
+ }
+ if (k < p->mode_prop->count_enums) {
+ err = RRChangeOutputProperty(output->randr_output,
+ p->atoms[0], XA_ATOM,
+ 32, PropModeReplace, 1,
+ &p->atoms[k + 1], FALSE,
+ TRUE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n",
+ err);
+ }
+ }
+ }
+
+ break;
+ }
+ }
+}
+
static xf86OutputStatus
drmmode_output_detect(xf86OutputPtr output)
{
@@ -1423,9 +1548,14 @@ drmmode_output_detect(xf86OutputPtr output)
xf86OutputStatus status;
drmModeFreeConnector(drmmode_output->mode_output);
- drmmode_output->mode_output = drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id);
- if (!drmmode_output->mode_output)
+ drmmode_output->mode_output =
+ drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id);
+ if (!drmmode_output->mode_output) {
+ drmmode_output->output_id = -1;
return XF86OutputStatusDisconnected;
+ }
+
+ drmmode_output_update_properties(output);
switch (drmmode_output->mode_output->connection) {
case DRM_MODE_CONNECTED:
@@ -1448,6 +1578,96 @@ drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
return MODE_OK;
}
+static void
+drmmode_output_attach_tile(xf86OutputPtr output)
+{
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0)
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
+ struct xf86CrtcTileInfo tile_info, *set = NULL;
+ int i;
+
+ if (!koutput) {
+ xf86OutputSetTile(output, NULL);
+ return;
+ }
+
+ /* look for a TILE property */
+ for (i = 0; i < koutput->count_props; i++) {
+ drmModePropertyPtr props;
+ props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]);
+ if (!props)
+ continue;
+
+ if (!(props->flags & DRM_MODE_PROP_BLOB)) {
+ drmModeFreeProperty(props);
+ continue;
+ }
+
+ if (!strcmp(props->name, "TILE")) {
+ drmModeFreePropertyBlob(drmmode_output->tile_blob);
+ drmmode_output->tile_blob =
+ drmModeGetPropertyBlob(pRADEONEnt->fd,
+ koutput->prop_values[i]);
+ }
+ drmModeFreeProperty(props);
+ }
+ if (drmmode_output->tile_blob) {
+ if (xf86OutputParseKMSTile(drmmode_output->tile_blob->data,
+ drmmode_output->tile_blob->length,
+ &tile_info) == TRUE)
+ set = &tile_info;
+ }
+ xf86OutputSetTile(output, set);
+#endif
+}
+
+static int
+koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput,
+ int type, const char *name)
+{
+ int idx = -1;
+
+ for (int i = 0; i < koutput->count_props; i++) {
+ drmModePropertyPtr prop = drmModeGetProperty(fd, koutput->props[i]);
+
+ if (!prop)
+ continue;
+
+ if (drm_property_type_is(prop, type) && !strcmp(prop->name, name))
+ idx = i;
+
+ drmModeFreeProperty(prop);
+
+ if (idx > -1)
+ break;
+ }
+
+ return idx;
+}
+
+static int
+koutput_get_prop_id(int fd, drmModeConnectorPtr koutput,
+ int type, const char *name)
+{
+ int idx = koutput_get_prop_idx(fd, koutput, type, name);
+
+ return (idx > -1) ? koutput->props[idx] : -1;
+}
+
+static drmModePropertyBlobPtr
+koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name)
+{
+ drmModePropertyBlobPtr blob = NULL;
+ int idx = koutput_get_prop_idx(fd, koutput, DRM_MODE_PROP_BLOB, name);
+
+ if (idx > -1)
+ blob = drmModeGetPropertyBlob(fd, koutput->prop_values[idx]);
+
+ return blob;
+}
+
static DisplayModePtr
drmmode_output_get_modes(xf86OutputPtr output)
{
@@ -1456,25 +1676,16 @@ drmmode_output_get_modes(xf86OutputPtr output)
RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
int i;
DisplayModePtr Modes = NULL, Mode;
- drmModePropertyPtr props;
xf86MonPtr mon = NULL;
if (!koutput)
return NULL;
+ drmModeFreePropertyBlob(drmmode_output->edid_blob);
+
/* look for an EDID property */
- for (i = 0; i < koutput->count_props; i++) {
- props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]);
- if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
- if (!strcmp(props->name, "EDID")) {
- if (drmmode_output->edid_blob)
- drmModeFreePropertyBlob(drmmode_output->edid_blob);
- drmmode_output->edid_blob = drmModeGetPropertyBlob(pRADEONEnt->fd, koutput->prop_values[i]);
- }
- }
- if (props)
- drmModeFreeProperty(props);
- }
+ drmmode_output->edid_blob =
+ koutput_get_prop_blob(pRADEONEnt->fd, koutput, "EDID");
if (drmmode_output->edid_blob) {
mon = xf86InterpretEDID(output->scrn->scrnIndex,
@@ -1484,6 +1695,8 @@ drmmode_output_get_modes(xf86OutputPtr output)
}
xf86OutputSetEDID(output, mon);
+ drmmode_output_attach_tile(output);
+
/* modes should already be available */
for (i = 0; i < koutput->count_modes; i++) {
Mode = xnfalloc(sizeof(DisplayModeRec));
@@ -1501,8 +1714,11 @@ drmmode_output_destroy(xf86OutputPtr output)
drmmode_output_private_ptr drmmode_output = output->driver_private;
int i;
- if (drmmode_output->edid_blob)
- drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ drmModeFreePropertyBlob(drmmode_output->edid_blob);
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0)
+ drmModeFreePropertyBlob(drmmode_output->tile_blob);
+#endif
+
for (i = 0; i < drmmode_output->num_props; i++) {
drmModeFreeProperty(drmmode_output->props[i].mode_prop);
free(drmmode_output->props[i].atoms);
@@ -1571,6 +1787,28 @@ drmmode_output_create_resources(xf86OutputPtr output)
RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
drmModePropertyPtr drmmode_prop, tearfree_prop;
int i, j, err;
+ Atom name;
+
+ /* Create CONNECTOR_ID property */
+ name = MakeAtom("CONNECTOR_ID", 12, TRUE);
+ if (name != BAD_RESOURCE) {
+ INT32 value = mode_output->connector_id;
+
+ err = RRConfigureOutputProperty(output->randr_output, name,
+ FALSE, FALSE, TRUE, 1, &value);
+ if (err != Success) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+
+ err = RRChangeOutputProperty(output->randr_output, name,
+ XA_INTEGER, 32, PropModeReplace, 1,
+ &value, FALSE, FALSE);
+ if (err != Success) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ }
drmmode_output->props = calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec));
if (!drmmode_output->props)
@@ -1592,14 +1830,14 @@ drmmode_output_create_resources(xf86OutputPtr output)
/* Userspace-only property for TearFree */
tearfree_prop = calloc(1, sizeof(*tearfree_prop));
tearfree_prop->flags = DRM_MODE_PROP_ENUM;
- strncpy(tearfree_prop->name, "TearFree", 8);
+ strcpy(tearfree_prop->name, "TearFree");
tearfree_prop->count_enums = 3;
tearfree_prop->enums = calloc(tearfree_prop->count_enums,
sizeof(*tearfree_prop->enums));
- strncpy(tearfree_prop->enums[0].name, "off", 3);
- strncpy(tearfree_prop->enums[1].name, "on", 2);
+ strcpy(tearfree_prop->enums[0].name, "off");
+ strcpy(tearfree_prop->enums[1].name, "on");
tearfree_prop->enums[1].value = 1;
- strncpy(tearfree_prop->enums[2].name, "auto", 4);
+ strcpy(tearfree_prop->enums[2].name, "auto");
tearfree_prop->enums[2].value = 2;
drmmode_output->props[j].mode_prop = tearfree_prop;
drmmode_output->props[j].value = info->tear_free;
@@ -1667,6 +1905,22 @@ drmmode_output_create_resources(xf86OutputPtr output)
}
}
+static void
+drmmode_output_set_tear_free(RADEONEntPtr pRADEONEnt,
+ drmmode_output_private_ptr drmmode_output,
+ xf86CrtcPtr crtc, int tear_free)
+{
+ if (drmmode_output->tear_free == tear_free)
+ return;
+
+ drmmode_output->tear_free = tear_free;
+
+ if (crtc) {
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
+ }
+}
+
static Bool
drmmode_output_set_property(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
@@ -1707,16 +1961,8 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property,
for (j = 0; j < p->mode_prop->count_enums; j++) {
if (!strcmp(p->mode_prop->enums[j].name, name)) {
if (i == (drmmode_output->num_props - 1)) {
- if (drmmode_output->tear_free != j) {
- xf86CrtcPtr crtc = output->crtc;
-
- drmmode_output->tear_free = j;
- if (crtc) {
- drmmode_set_mode_major(crtc, &crtc->mode,
- crtc->rotation,
- crtc->x, crtc->y);
- }
- }
+ drmmode_output_set_tear_free(pRADEONEnt, drmmode_output,
+ output->crtc, j);
} else {
drmModeConnectorSetProperty(pRADEONEnt->fd,
drmmode_output->output_id,
@@ -1744,15 +1990,6 @@ static const xf86OutputFuncsRec drmmode_output_funcs = {
.create_resources = drmmode_output_create_resources,
.set_property = drmmode_output_set_property,
.get_property = drmmode_output_get_property,
-#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,
@@ -1895,8 +2132,10 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
drmModeConnectorPtr koutput;
drmModeEncoderPtr *kencoders = NULL;
drmmode_output_private_ptr drmmode_output;
- drmModePropertyPtr props;
drmModePropertyBlobPtr path_blob = NULL;
+#if XF86_CRTC_VERSION >= 8
+ Bool nonDesktop = FALSE;
+#endif
char name[32];
int i;
const char *s;
@@ -1905,17 +2144,14 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
if (!koutput)
return 0;
- for (i = 0; i < koutput->count_props; i++) {
- props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]);
- if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
- if (!strcmp(props->name, "PATH")) {
- path_blob = drmModeGetPropertyBlob(pRADEONEnt->fd, koutput->prop_values[i]);
- drmModeFreeProperty(props);
- break;
- }
- drmModeFreeProperty(props);
- }
- }
+ path_blob = koutput_get_prop_blob(pRADEONEnt->fd, koutput, "PATH");
+
+#if XF86_CRTC_VERSION >= 8
+ i = koutput_get_prop_idx(pRADEONEnt->fd, koutput, DRM_MODE_PROP_RANGE,
+ "non-desktop");
+ if (i >= 0)
+ nonDesktop = koutput->prop_values[i] != 0;
+#endif
kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
if (!kencoders) {
@@ -1946,6 +2182,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
drmmode_output = output->driver_private;
drmmode_output->output_id = mode_res->connectors[num];
drmmode_output->mode_output = koutput;
+#if XF86_CRTC_VERSION >= 8
+ output->non_desktop = nonDesktop;
+#endif
for (i = 0; i < koutput->count_encoders; i++)
drmModeFreeEncoder(kencoders[i]);
free(kencoders);
@@ -1958,9 +2197,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
if (!RADEONZaphodStringMatches(pScrn, s, name))
goto out_free_encoders;
} else {
- if (!info->IsSecondary && (num != 0))
- goto out_free_encoders;
- else if (info->IsSecondary && (num != 1))
+ if (info->instance_id != num)
goto out_free_encoders;
}
}
@@ -1987,6 +2224,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
output->interlaceAllowed = TRUE;
output->doubleScanAllowed = TRUE;
output->driver_private = drmmode_output;
+#if XF86_CRTC_VERSION >= 8
+ output->non_desktop = nonDesktop;
+#endif
output->possible_crtcs = 0xffffffff;
for (i = 0; i < koutput->count_encoders; i++) {
@@ -1995,17 +2235,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
/* work out the possible clones later */
output->possible_clones = 0;
- for (i = 0; i < koutput->count_props; i++) {
- props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]);
- if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
- if (!strcmp(props->name, "DPMS")) {
- drmmode_output->dpms_enum_id = koutput->props[i];
- drmModeFreeProperty(props);
- break;
- }
- drmModeFreeProperty(props);
- }
- }
+ drmmode_output->dpms_enum_id =
+ koutput_get_prop_id(pRADEONEnt->fd, koutput, DRM_MODE_PROP_ENUM,
+ "DPMS");
if (dynamic) {
output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
@@ -2176,144 +2408,83 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
RADEONInfoPtr info = RADEONPTR(scrn);
- struct radeon_bo *old_front = NULL;
+ struct radeon_buffer *old_front = NULL;
ScreenPtr screen = xf86ScrnToScreen(scrn);
int i, pitch, old_width, old_height, old_pitch;
- int aligned_height;
- uint32_t screen_size;
+ int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP;
int cpp = info->pixel_bytes;
- struct radeon_bo *front_bo;
- struct radeon_surface surface;
- struct radeon_surface *psurface;
- uint32_t tiling_flags = 0, base_align;
+ uint32_t tiling_flags;
PixmapPtr ppix = screen->GetScreenPixmap(screen);
void *fb_shadow;
if (scrn->virtualX == width && scrn->virtualY == height)
return TRUE;
- front_bo = info->front_bo;
- radeon_cs_flush_indirect(scrn);
-
- if (front_bo)
- radeon_bo_wait(front_bo);
-
- if (info->allowColorTiling && !info->shadow_primary) {
- if (info->ChipFamily >= CHIP_FAMILY_R600) {
- if (info->allowColorTiling2D) {
- tiling_flags |= RADEON_TILING_MACRO;
- } else {
- tiling_flags |= RADEON_TILING_MICRO;
- }
- } else
- tiling_flags |= RADEON_TILING_MACRO;
+ if (width > xf86_config->maxWidth || height > xf86_config->maxHeight) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Xorg tried resizing screen to %dx%d, but maximum "
+ "supported is %dx%d\n", width, height,
+ xf86_config->maxWidth, xf86_config->maxHeight);
+ return FALSE;
}
- pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
- aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
- screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
- base_align = 4096;
- if (info->ChipFamily >= CHIP_FAMILY_R600) {
- memset(&surface, 0, sizeof(struct radeon_surface));
- surface.npix_x = width;
- surface.npix_y = height;
- surface.npix_z = 1;
- surface.blk_w = 1;
- surface.blk_h = 1;
- surface.blk_d = 1;
- surface.array_size = 1;
- surface.last_level = 0;
- surface.bpe = cpp;
- surface.nsamples = 1;
- surface.flags = RADEON_SURF_SCANOUT;
- /* we are requiring a recent enough libdrm version */
- 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);
- if (tiling_flags & RADEON_TILING_MICRO) {
- surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
- surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- }
- if (tiling_flags & RADEON_TILING_MACRO) {
- surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
- surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- if (radeon_surface_best(info->surf_man, &surface)) {
- return FALSE;
- }
- if (radeon_surface_init(info->surf_man, &surface)) {
- return FALSE;
- }
- screen_size = surface.bo_size;
- base_align = surface.bo_alignment;
- pitch = surface.level[0].pitch_bytes;
- tiling_flags = 0;
- switch (surface.level[0].mode) {
- case RADEON_SURF_MODE_2D:
- tiling_flags |= RADEON_TILING_MACRO;
- tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
- tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
- tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
- if (surface.tile_split)
- tiling_flags |= eg_tile_split(surface.tile_split)
- << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
- break;
- case RADEON_SURF_MODE_1D:
- tiling_flags |= RADEON_TILING_MICRO;
- break;
- default:
- break;
- }
- info->front_surface = surface;
+ if (info->allowColorTiling && !info->shadow_primary) {
+ if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D)
+ usage |= RADEON_CREATE_PIXMAP_TILING_MACRO;
+ else
+ usage |= RADEON_CREATE_PIXMAP_TILING_MICRO;
}
- xf86DrvMsg(scrn->scrnIndex, X_INFO,
- "Allocate new frame buffer %dx%d stride %d\n",
- width, height, pitch / cpp);
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d\n",
+ width, height);
old_width = scrn->virtualX;
old_height = scrn->virtualY;
old_pitch = scrn->displayWidth;
- old_front = info->front_bo;
+ old_front = info->front_buffer;
scrn->virtualX = width;
scrn->virtualY = height;
- scrn->displayWidth = pitch / cpp;
- info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
- info->shadow_primary ?
- RADEON_GEM_DOMAIN_GTT :
- RADEON_GEM_DOMAIN_VRAM,
- tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0);
- if (!info->front_bo)
+ info->front_buffer = radeon_alloc_pixmap_bo(scrn, scrn->virtualX,
+ scrn->virtualY, scrn->depth,
+ usage, scrn->bitsPerPixel,
+ &pitch,
+ &info->front_surface,
+ &tiling_flags);
+ if (!info->front_buffer)
goto fail;
+ scrn->displayWidth = pitch / cpp;
+
+ if (!info->use_glamor) {
#if X_BYTE_ORDER == X_BIG_ENDIAN
- switch (cpp) {
- case 4:
- tiling_flags |= RADEON_TILING_SWAP_32BIT;
- break;
- case 2:
- tiling_flags |= RADEON_TILING_SWAP_16BIT;
- break;
- }
- if (info->ChipFamily < CHIP_FAMILY_R600 &&
- info->r600_shadow_fb && tiling_flags)
- tiling_flags |= RADEON_TILING_SURFACE;
+ switch (cpp) {
+ case 4:
+ tiling_flags |= RADEON_TILING_SWAP_32BIT;
+ break;
+ case 2:
+ tiling_flags |= RADEON_TILING_SWAP_16BIT;
+ break;
+ }
+ if (info->ChipFamily < CHIP_FAMILY_R600 &&
+ info->r600_shadow_fb && tiling_flags)
+ tiling_flags |= RADEON_TILING_SURFACE;
#endif
- if (tiling_flags)
- radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
+ if (tiling_flags)
+ radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
+ }
if (!info->r600_shadow_fb) {
- psurface = radeon_get_pixmap_surface(ppix);
- *psurface = info->front_surface;
+ if (info->surf_man && !info->use_glamor)
+ *radeon_get_pixmap_surface(ppix) = info->front_surface;
screen->ModifyPixmapHeader(ppix,
width, height, -1, -1, pitch, NULL);
} else {
- if (radeon_bo_map(info->front_bo, 1))
+ if (radeon_bo_map(info->front_buffer->bo.radeon, 1))
goto fail;
- fb_shadow = calloc(1, screen_size);
- if (fb_shadow == NULL)
+ fb_shadow = calloc(1, pitch * scrn->virtualY);
+ if (!fb_shadow)
goto fail;
free(info->fb_shadow);
info->fb_shadow = fb_shadow;
@@ -2326,13 +2497,12 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
radeon_glamor_create_screen_resources(scrn->pScreen);
if (!info->r600_shadow_fb) {
- if (!radeon_set_pixmap_bo(ppix, info->front_bo))
+ if (!radeon_set_pixmap_bo(ppix, info->front_buffer))
goto fail;
}
radeon_pixmap_clear(ppix);
- radeon_cs_flush_indirect(scrn);
- radeon_bo_wait(info->front_bo);
+ radeon_finish(scrn, info->front_buffer);
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -2344,16 +2514,14 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
crtc->rotation, crtc->x, crtc->y);
}
- if (old_front)
- radeon_bo_unref(old_front);
+ radeon_buffer_unref(&old_front);
- radeon_kms_update_vram_limit(scrn, screen_size);
+ radeon_kms_update_vram_limit(scrn, pitch * scrn->virtualY);
return TRUE;
fail:
- if (info->front_bo)
- radeon_bo_unref(info->front_bo);
- info->front_bo = old_front;
+ radeon_buffer_unref(&info->front_buffer);
+ info->front_buffer = old_front;
scrn->virtualX = old_width;
scrn->virtualY = old_height;
scrn->displayWidth = old_pitch;
@@ -2361,8 +2529,139 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
return FALSE;
}
+static void
+drmmode_validate_leases(ScrnInfoPtr scrn)
+{
+#ifdef XF86_LEASE_VERSION
+ ScreenPtr screen = scrn->pScreen;
+ rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
+ drmModeLesseeListPtr lessees;
+ RRLeasePtr lease, next;
+ int l;
+
+ /* We can't talk to the kernel about leases when VT switched */
+ if (!scrn->vtSema)
+ return;
+
+ lessees = drmModeListLessees(pRADEONEnt->fd);
+ if (!lessees)
+ return;
+
+ xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) {
+ drmmode_lease_private_ptr lease_private = lease->devPrivate;
+
+ for (l = 0; l < lessees->count; l++) {
+ if (lessees->lessees[l] == lease_private->lessee_id)
+ break;
+ }
+
+ /* check to see if the lease has gone away */
+ if (l == lessees->count) {
+ free(lease_private);
+ lease->devPrivate = NULL;
+ xf86CrtcLeaseTerminated(lease);
+ }
+ }
+
+ free(lessees);
+#endif
+}
+
+#ifdef XF86_LEASE_VERSION
+
+static int
+drmmode_create_lease(RRLeasePtr lease, int *fd)
+{
+ ScreenPtr screen = lease->screen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
+ drmmode_lease_private_ptr lease_private;
+ int noutput = lease->numOutputs;
+ int ncrtc = lease->numCrtcs;
+ uint32_t *objects;
+ size_t nobjects;
+ int lease_fd;
+ int c, o;
+ int i;
+
+ nobjects = ncrtc + noutput;
+ if (nobjects == 0 || nobjects > (SIZE_MAX / 4) ||
+ ncrtc > (SIZE_MAX - noutput))
+ return BadValue;
+
+ lease_private = calloc(1, sizeof (drmmode_lease_private_rec));
+ if (!lease_private)
+ return BadAlloc;
+
+ objects = malloc(nobjects * 4);
+ if (!objects) {
+ free(lease_private);
+ return BadAlloc;
+ }
+
+ i = 0;
+
+ /* Add CRTC ids */
+ for (c = 0; c < ncrtc; c++) {
+ xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ objects[i++] = drmmode_crtc->mode_crtc->crtc_id;
+ }
+
+ /* Add connector ids */
+ for (o = 0; o < noutput; o++) {
+ xf86OutputPtr output = lease->outputs[o]->devPrivate;
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+ objects[i++] = drmmode_output->mode_output->connector_id;
+ }
+
+ /* call kernel to create lease */
+ assert (i == nobjects);
+
+ lease_fd = drmModeCreateLease(pRADEONEnt->fd, objects, nobjects, 0,
+ &lease_private->lessee_id);
+
+ free(objects);
+
+ if (lease_fd < 0) {
+ free(lease_private);
+ return BadMatch;
+ }
+
+ lease->devPrivate = lease_private;
+
+ xf86CrtcLeaseStarted(lease);
+
+ *fd = lease_fd;
+ return Success;
+}
+
+static void
+drmmode_terminate_lease(RRLeasePtr lease)
+{
+ drmmode_lease_private_ptr lease_private = lease->devPrivate;
+ ScreenPtr screen = lease->screen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
+
+ if (drmModeRevokeLease(pRADEONEnt->fd, lease_private->lessee_id) == 0) {
+ free(lease_private);
+ lease->devPrivate = NULL;
+ xf86CrtcLeaseTerminated(lease);
+ }
+}
+
+#endif // XF86_LEASE_VERSION
+
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
- drmmode_xf86crtc_resize
+ .resize = drmmode_xf86crtc_resize,
+#ifdef XF86_LEASE_VERSION
+ .create_lease = drmmode_create_lease,
+ .terminate_lease = drmmode_terminate_lease
+#endif
};
static void
@@ -2371,17 +2670,21 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
drmmode_flipdata_ptr flipdata = event_data;
+ int crtc_id = drmmode_get_crtc_id(crtc);
+ struct drmmode_fb **fb = &flipdata->fb[crtc_id];
+
+ if (drmmode_crtc->flip_pending == *fb) {
+ drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
+ NULL);
+ }
+ drmmode_fb_reference(pRADEONEnt->fd, fb, NULL);
if (--flipdata->flip_count == 0) {
if (!flipdata->fe_crtc)
flipdata->fe_crtc = crtc;
flipdata->abort(flipdata->fe_crtc, flipdata->event_data);
- drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
free(flipdata);
}
-
- drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
- NULL);
}
static void
@@ -2390,6 +2693,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
drmmode_flipdata_ptr flipdata = event_data;
+ int crtc_id = drmmode_get_crtc_id(crtc);
+ struct drmmode_fb **fb = &flipdata->fb[crtc_id];
/* Is this the event whose info shall be delivered to higher level? */
if (crtc == flipdata->fe_crtc) {
@@ -2398,12 +2703,13 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
flipdata->fe_usec = usec;
}
- drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
- flipdata->fb);
- if (drmmode_crtc->tear_free ||
- drmmode_crtc->flip_pending == flipdata->fb) {
- drmmode_fb_reference(pRADEONEnt->fd,
- &drmmode_crtc->flip_pending, NULL);
+ if (*fb) {
+ if (drmmode_crtc->flip_pending == *fb) {
+ drmmode_fb_reference(pRADEONEnt->fd,
+ &drmmode_crtc->flip_pending, NULL);
+ }
+ drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb);
+ drmmode_fb_reference(pRADEONEnt->fd, fb, NULL);
}
if (--flipdata->flip_count == 0) {
@@ -2416,7 +2722,6 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
else
flipdata->handler(crtc, frame, usec, flipdata->event_data);
- drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
free(flipdata);
}
}
@@ -2430,9 +2735,8 @@ static void
drm_wakeup_handler(pointer data, int err, pointer p)
#endif
{
- ScrnInfoPtr scrn = data;
- RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
- RADEONInfoPtr info = RADEONPTR(scrn);
+ drmmode_ptr drmmode = data;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(drmmode->scrn);
#if !HAVE_NOTIFY_FD
fd_set *read_mask = p;
@@ -2440,7 +2744,7 @@ drm_wakeup_handler(pointer data, int err, pointer p)
if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask))
#endif
{
- drmHandleEvent(pRADEONEnt->fd, &info->drmmode.event_context);
+ radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context);
}
}
@@ -2513,6 +2817,7 @@ 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;
+ unsigned int crtcs_got = 0;
char *bus_id_string, *provider_name;
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
@@ -2530,26 +2835,47 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
"%d crtcs needed for screen.\n", crtcs_needed);
+ /* Need per-screen drmmode_crtc_funcs, based on our global template,
+ * so we can disable some functions, depending on screen settings.
+ */
+ info->drmmode_crtc_funcs = drmmode_crtc_funcs;
+
if (info->r600_shadow_fb) {
/* Rotation requires hardware acceleration */
- drmmode_crtc_funcs.shadow_allocate = NULL;
- drmmode_crtc_funcs.shadow_create = NULL;
- drmmode_crtc_funcs.shadow_destroy = NULL;
+ info->drmmode_crtc_funcs.shadow_allocate = NULL;
+ info->drmmode_crtc_funcs.shadow_create = NULL;
+ info->drmmode_crtc_funcs.shadow_destroy = NULL;
}
+ /* Hw gamma lut's are currently bypassed by the hw at color depth 30,
+ * so spare the server the effort to compute and update the cluts.
+ */
+ if (pScrn->depth == 30)
+ info->drmmode_crtc_funcs.gamma_set = NULL;
+
drmmode->count_crtcs = mode_res->count_crtcs;
xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height);
- for (i = 0; i < mode_res->count_crtcs; i++)
+ for (i = 0; i < mode_res->count_crtcs; i++) {
if (!xf86IsEntityShared(pScrn->entityList[0]) ||
- (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
- crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
+ (crtcs_got < crtcs_needed &&
+ !(pRADEONEnt->assigned_crtcs & (1 << i))))
+ crtcs_got += drmmode_crtc_init(pScrn, drmmode, mode_res, i);
+ }
/* All ZaphodHeads outputs provided with matching crtcs? */
- if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
+ if (crtcs_got < crtcs_needed) {
+ if (crtcs_got == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No ZaphodHeads CRTC available, needed %u\n",
+ crtcs_needed);
+ return FALSE;
+ }
+
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
crtcs_needed);
+ }
/* workout clones */
drmmode_clones_init(pScrn, drmmode, mode_res);
@@ -2562,10 +2888,6 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
xf86InitialConfiguration(pScrn, TRUE);
- drmmode->event_context.version = 2;
- drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
- drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
-
pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt);
drmModeFreeResources(mode_res);
@@ -2583,11 +2905,13 @@ void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
info->drmmode_inited = TRUE;
if (pRADEONEnt->fd_wakeup_registered != serverGeneration) {
#if HAVE_NOTIFY_FD
- SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, pScrn);
+ SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ,
+ &info->drmmode);
#else
AddGeneralSocket(pRADEONEnt->fd);
RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
- drm_wakeup_handler, pScrn);
+ drm_wakeup_handler,
+ &info->drmmode);
#endif
pRADEONEnt->fd_wakeup_registered = serverGeneration;
pRADEONEnt->fd_wakeup_ref = 1;
@@ -2605,6 +2929,9 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited)
return;
+ for (c = 0; c < config->num_crtc; c++)
+ drmmode_crtc_scanout_free(config->crtc[c]);
+
if (pRADEONEnt->fd_wakeup_registered == serverGeneration &&
!--pRADEONEnt->fd_wakeup_ref) {
#if HAVE_NOTIFY_FD
@@ -2615,9 +2942,6 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
drm_wakeup_handler, pScrn);
#endif
}
-
- for (c = 0; c < config->num_crtc; c++)
- drmmode_crtc_scanout_free(config->crtc[c]->driver_private);
}
@@ -2628,16 +2952,105 @@ Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo
}
+static void drmmode_sprite_do_set_cursor(struct radeon_device_priv *device_priv,
+ ScrnInfoPtr scrn, int x, int y)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ CursorPtr cursor = device_priv->cursor;
+ Bool sprite_visible = device_priv->sprite_visible;
+
+ if (cursor) {
+ x -= cursor->bits->xhot;
+ y -= cursor->bits->yhot;
-void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
+ device_priv->sprite_visible =
+ x < scrn->virtualX && y < scrn->virtualY &&
+ (x + cursor->bits->width > 0) &&
+ (y + cursor->bits->height > 0);
+ } else {
+ device_priv->sprite_visible = FALSE;
+ }
+
+ info->sprites_visible += device_priv->sprite_visible - sprite_visible;
+}
+
+static void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, int x, int y)
{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- xf86CrtcPtr crtc = xf86_config->crtc[id];
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_device_priv *device_priv =
+ dixLookupScreenPrivate(&pDev->devPrivates,
+ &radeon_device_private_key, pScreen);
+
+ device_priv->cursor = pCursor;
+ drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
+
+ info->SpriteFuncs->SetCursor(pDev, pScreen, pCursor, x, y);
+}
+
+static void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_device_priv *device_priv =
+ dixLookupScreenPrivate(&pDev->devPrivates,
+ &radeon_device_private_key, pScreen);
+
+ drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
+
+ info->SpriteFuncs->MoveCursor(pDev, pScreen, x, y);
+}
+
+static Bool drmmode_sprite_realize_realize_cursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
- drmmode_crtc->cursor_bo = bo;
+ return info->SpriteFuncs->RealizeCursor(pDev, pScreen, pCursor);
}
+static Bool drmmode_sprite_realize_unrealize_cursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ return info->SpriteFuncs->UnrealizeCursor(pDev, pScreen, pCursor);
+}
+
+static Bool drmmode_sprite_device_cursor_initialize(DeviceIntPtr pDev,
+ ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ return info->SpriteFuncs->DeviceCursorInitialize(pDev, pScreen);
+}
+
+static void drmmode_sprite_device_cursor_cleanup(DeviceIntPtr pDev,
+ ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->SpriteFuncs->DeviceCursorCleanup(pDev, pScreen);
+}
+
+miPointerSpriteFuncRec drmmode_sprite_funcs = {
+ .RealizeCursor = drmmode_sprite_realize_realize_cursor,
+ .UnrealizeCursor = drmmode_sprite_realize_unrealize_cursor,
+ .SetCursor = drmmode_sprite_set_cursor,
+ .MoveCursor = drmmode_sprite_move_cursor,
+ .DeviceCursorInitialize = drmmode_sprite_device_cursor_initialize,
+ .DeviceCursorCleanup = drmmode_sprite_device_cursor_cleanup,
+};
+
+
void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -2654,27 +3067,30 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
Bool set_hw)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
- RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ unsigned num_desired = 0, num_on = 0;
int c;
+ /* First, disable all unused CRTCs */
+ if (set_hw) {
+ for (c = 0; c < config->num_crtc; c++) {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ /* Skip disabled CRTCs */
+ if (crtc->enabled)
+ continue;
+
+ drmmode_crtc_dpms(crtc, DPMSModeOff);
+ }
+ }
+
+ /* Then, try setting the chosen mode on each CRTC */
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
xf86OutputPtr output = NULL;
int o;
- /* Skip disabled CRTCs */
- if (!crtc->enabled) {
- if (set_hw) {
- drmmode_do_crtc_dpms(crtc, DPMSModeOff);
- drmModeSetCrtc(pRADEONEnt->fd,
- drmmode_crtc->mode_crtc->crtc_id,
- 0, 0, 0, NULL, 0, NULL);
- drmmode_fb_reference(pRADEONEnt->fd,
- &drmmode_crtc->fb, NULL);
- }
+ if (!crtc->enabled)
continue;
- }
if (config->output[config->compat_output]->crtc == crtc)
output = config->output[config->compat_output];
@@ -2691,14 +3107,19 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
if (!output)
continue;
+ num_desired++;
+
/* Mark that we'll need to re-set the mode for sure */
memset(&crtc->mode, 0, sizeof(crtc->mode));
if (!crtc->desiredMode.CrtcHDisplay)
{
DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
- if (!mode)
- return FALSE;
+ if (!mode) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to find mode for CRTC %d\n", c);
+ continue;
+ }
crtc->desiredMode = *mode;
crtc->desiredRotation = RR_Rotate_0;
crtc->desiredX = 0;
@@ -2706,40 +3127,68 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
}
if (set_hw) {
- if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
- crtc->desiredX, crtc->desiredY))
- return FALSE;
+ if (crtc->funcs->set_mode_major(crtc, &crtc->desiredMode,
+ crtc->desiredRotation,
+ crtc->desiredX,
+ crtc->desiredY)) {
+ num_on++;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set mode on CRTC %d\n", c);
+ RRCrtcSet(crtc->randr_crtc, NULL, crtc->x, crtc->y,
+ crtc->rotation, 0, NULL);
+ }
} else {
crtc->mode = crtc->desiredMode;
crtc->rotation = crtc->desiredRotation;
crtc->x = crtc->desiredX;
crtc->y = crtc->desiredY;
- if (!drmmode_handle_transform(crtc))
- return FALSE;
+ if (drmmode_handle_transform(crtc))
+ num_on++;
}
}
+
+ if (num_on == 0 && num_desired > 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to enable any CRTC\n");
+ return FALSE;
+ }
+
+ /* Validate leases on VT re-entry */
+ if (dixPrivateKeyRegistered(rrPrivKey))
+ drmmode_validate_leases(pScrn);
+
return TRUE;
}
Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
if (xf86_config->num_crtc) {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
"Initializing kms color map\n");
if (!miCreateDefColormap(pScreen))
return FALSE;
- /* all radeons support 10 bit CLUTs */
- if (!xf86HandleColormaps(pScreen, 256, 10,
- NULL, NULL,
- CMAP_PALETTED_TRUECOLOR
-#if 0 /* This option messes up text mode! (eich@suse.de) */
- | CMAP_LOAD_EVEN_IF_OFFSCREEN
-#endif
- | CMAP_RELOAD_ON_MODE_SWITCH))
- return FALSE;
+
+ /* All radeons support 10 bit CLUTs. They get bypassed at depth 30. */
+ if (pScrn->depth != 30) {
+ if (!xf86HandleColormaps(pScreen, 256, 10, NULL, NULL,
+ CMAP_PALETTED_TRUECOLOR
+ | CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+
+ for (i = 0; i < xf86_config->num_crtc; i++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+ drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red,
+ crtc->gamma_green,
+ crtc->gamma_blue,
+ crtc->gamma_size);
+ }
+ }
}
+
return TRUE;
}
@@ -2796,23 +3245,23 @@ radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
*/
for (i = 0; i < config->num_output; i++) {
xf86OutputPtr output = config->output[i];
+ xf86CrtcPtr crtc = output->crtc;
drmmode_output_private_ptr drmmode_output = output->driver_private;
- uint32_t con_id = drmmode_output->mode_output->connector_id;
- drmModeConnectorPtr koutput;
+
+ drmmode_output_detect(output);
+
+ if (!crtc || !drmmode_output->mode_output)
+ continue;
/* Get an updated view of the properties for the current connector and
* look for the link-status property
*/
- koutput = drmModeGetConnectorCurrent(pRADEONEnt->fd, con_id);
- for (j = 0; koutput && j < koutput->count_props; j++) {
- drmModePropertyPtr props;
- props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[j]);
- if (props && props->flags & DRM_MODE_PROP_ENUM &&
- !strcmp(props->name, "link-status") &&
- koutput->prop_values[j] == DRM_MODE_LINK_STATUS_BAD) {
- xf86CrtcPtr crtc = output->crtc;
- if (!crtc)
- continue;
+ for (j = 0; j < drmmode_output->num_props; j++) {
+ drmmode_prop_ptr p = &drmmode_output->props[j];
+
+ if (!strcmp(p->mode_prop->name, "link-status")) {
+ if (p->value != DRM_MODE_LINK_STATUS_BAD)
+ break;
/* the connector got a link failure, re-set the current mode */
drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
@@ -2820,12 +3269,13 @@ radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"hotplug event: connector %u's link-state is BAD, "
- "tried resetting the current mode. You may be left "
- "with a black screen if this fails...\n", con_id);
+ "tried resetting the current mode. You may be left"
+ "with a black screen if this fails...\n",
+ drmmode_output->mode_output->connector_id);
+
+ break;
}
- drmModeFreeProperty(props);
}
- drmModeFreeConnector(koutput);
}
mode_res = drmModeGetResources(pRADEONEnt->fd);
@@ -2860,13 +3310,14 @@ restart_destroy:
/* find new output ids we don't have outputs for */
for (i = 0; i < mode_res->count_connectors; i++) {
- if (drmmode_find_output(pRADEONEnt->primary_scrn,
- mode_res->connectors[i],
- &num_dvi, &num_hdmi) ||
- (pRADEONEnt->secondary_scrn &&
- drmmode_find_output(pRADEONEnt->secondary_scrn,
- mode_res->connectors[i],
- &num_dvi, &num_hdmi)))
+ for (j = 0; j < pRADEONEnt->num_scrns; j++) {
+ if (drmmode_find_output(pRADEONEnt->scrn[j],
+ mode_res->connectors[i],
+ &num_dvi, &num_hdmi))
+ break;
+ }
+
+ if (j < pRADEONEnt->num_scrns)
continue;
if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi,
@@ -2874,7 +3325,10 @@ restart_destroy:
changed = TRUE;
}
- if (changed && dixPrivateKeyRegistered(rrPrivKey)) {
+ /* Check to see if a lessee has disappeared */
+ drmmode_validate_leases(scrn);
+
+ if (changed) {
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
RRSetChanged(xf86ScrnToScreen(scrn));
#else
@@ -2974,21 +3428,24 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
xf86CrtcPtr crtc = NULL;
drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
- int i;
+ int crtc_id;
uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0;
drmmode_flipdata_ptr flipdata;
+ Bool handle_deferred = FALSE;
uintptr_t drm_queue_seq = 0;
+ struct drmmode_fb *fb;
+ int i = 0;
- flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
+ flipdata = calloc(1, sizeof(*flipdata) + drmmode_crtc->drmmode->count_crtcs *
+ sizeof(flipdata->fb[0]));
if (!flipdata) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue: data alloc failed.\n");
goto error;
}
- drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb,
- radeon_pixmap_get_fb(new_front));
- if (!flipdata->fb) {
+ fb = radeon_pixmap_get_fb(new_front);
+ if (!fb) {
ErrorF("Failed to get FB for flip\n");
goto error;
}
@@ -3009,10 +3466,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
flipdata->fe_crtc = ref_crtc;
for (i = 0; i < config->num_crtc; i++) {
- struct drmmode_fb *fb = flipdata->fb;
-
crtc = config->crtc[i];
drmmode_crtc = crtc->driver_private;
+ crtc_id = drmmode_get_crtc_id(crtc);
if (!drmmode_crtc_can_flip(crtc) ||
(drmmode_crtc->tear_free && crtc != ref_crtc))
@@ -3023,7 +3479,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id,
flipdata,
drmmode_flip_handler,
- drmmode_flip_abort);
+ drmmode_flip_abort,
+ TRUE);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue event entry failed.\n");
@@ -3046,23 +3503,31 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
goto next;
}
- fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
- if (!fb) {
+ drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id],
+ radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
+ if (!flipdata->fb[crtc_id]) {
ErrorF("Failed to get FB for TearFree flip\n");
goto error;
}
radeon_scanout_do_update(crtc, scanout_id, new_front,
- &extents);
-
- drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
- drmmode_crtc->scanout_update_pending);
+ extents);
+ radeon_cs_flush_indirect(crtc->scrn);
+
+ if (drmmode_crtc->scanout_update_pending) {
+ radeon_drm_wait_pending_flip(crtc);
+ handle_deferred = TRUE;
+ radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
+ drmmode_crtc->scanout_update_pending = 0;
+ }
+ } else {
+ drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], fb);
}
if (crtc == ref_crtc) {
if (drmmode_page_flip_target_absolute(pRADEONEnt,
drmmode_crtc,
- fb->handle,
+ flipdata->fb[crtc_id]->handle,
flip_flags,
drm_queue_seq,
target_msc) != 0)
@@ -3070,7 +3535,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
} else {
if (drmmode_page_flip_target_relative(pRADEONEnt,
drmmode_crtc,
- fb->handle,
+ flipdata->fb[crtc_id]->handle,
flip_flags,
drm_queue_seq, 0) != 0)
goto flip_error;
@@ -3081,12 +3546,15 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
drmmode_crtc->ignore_damage = TRUE;
}
+ drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
+ flipdata->fb[crtc_id]);
+
next:
- drmmode_fb_reference(pRADEONEnt->fd,
- &drmmode_crtc->flip_pending, fb);
drm_queue_seq = 0;
}
+ if (handle_deferred)
+ radeon_drm_queue_handle_deferred(ref_crtc);
if (flipdata->flip_count > 0)
return TRUE;
@@ -3101,11 +3569,12 @@ error:
drmmode_flip_abort(crtc, flipdata);
else {
abort(NULL, data);
- drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
free(flipdata);
}
xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
strerror(errno));
+ if (handle_deferred)
+ radeon_drm_queue_handle_deferred(ref_crtc);
return FALSE;
}