diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2019-03-08 21:59:58 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2019-03-08 21:59:58 +0000 |
commit | c4f0a5e3d3fc40d0a80cc31ee710e05fa0cce5c5 (patch) | |
tree | a9367808d33e2560613403402f0ff352d274b04c /driver/xf86-video-ati/src | |
parent | 62278a148bb5b51b727d8fdceca73da2c7223a42 (diff) |
update to xf86-video-ati 19.0.0
fixes Xorg segfault reported by Mihai Popescu
ok matthieu@
Diffstat (limited to 'driver/xf86-video-ati/src')
-rw-r--r-- | driver/xf86-video-ati/src/drmmode_display.c | 330 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/drmmode_display.h | 20 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon.h | 3 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_bo_helper.c | 2 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_dri2.c | 29 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_dri3.c | 41 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_drm_queue.c | 129 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_drm_queue.h | 3 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_glamor.c | 9 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_kms.c | 266 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_present.c | 11 | ||||
-rw-r--r-- | driver/xf86-video-ati/src/radeon_probe.h | 4 |
12 files changed, 560 insertions, 287 deletions
diff --git a/driver/xf86-video-ati/src/drmmode_display.c b/driver/xf86-video-ati/src/drmmode_display.c index 8445ef2a7..c5fccd2aa 100644 --- a/driver/xf86-video-ati/src/drmmode_display.c +++ b/driver/xf86-video-ati/src/drmmode_display.c @@ -508,8 +508,17 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, } 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, @@ -772,11 +781,17 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, *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), - extents); - RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage)); - radeon_finish(scrn, 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_glamor_finish(scrn); + + if (!drmmode_crtc->flip_pending) { + radeon_drm_abort_entry(drmmode_crtc-> + scanout_update_pending); + } + } } } @@ -848,6 +863,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; @@ -915,6 +931,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } radeon_drm_wait_pending_flip(crtc); + handle_deferred = TRUE; if (!drmmode_set_mode(crtc, fb, mode, x, y)) goto done; @@ -967,16 +984,16 @@ done: if (drmmode_crtc->scanout[scanout_id].pixmap && fb != radeon_pixmap_get_fb(drmmode_crtc-> scanout[scanout_id].pixmap)) { - radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); - drmmode_crtc->scanout_update_pending = 0; - drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc_scanout_free(crtc); } else if (!drmmode_crtc->tear_free) { drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]); } } - radeon_drm_queue_handle_deferred(crtc); + if (handle_deferred) + radeon_drm_queue_handle_deferred(crtc); + return ret; } @@ -1000,6 +1017,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); } @@ -1038,29 +1058,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 @@ -1069,10 +1122,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) { @@ -1080,16 +1144,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 @@ -1098,8 +1165,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); } } @@ -1126,7 +1205,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 @@ -1136,56 +1215,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); + ret = drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR2, &arg); if (ret == -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 @@ -1265,7 +1361,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) } } - drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc_scanout_free(crtc); drmmode_crtc->prime_scanout_pixmap = NULL; if (!ppix) @@ -1280,7 +1376,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; } @@ -2049,9 +2145,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; } } @@ -2557,12 +2651,14 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even flipdata->fe_usec = usec; } - if (drmmode_crtc->flip_pending == *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); } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb); - drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); if (--flipdata->flip_count == 0) { /* Deliver MSC & UST from reference/current CRTC to flip event @@ -2669,6 +2765,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); @@ -2707,16 +2804,26 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) 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); @@ -2770,6 +2877,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 @@ -2780,9 +2890,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); } @@ -2892,15 +2999,6 @@ miPointerSpriteFuncRec drmmode_sprite_funcs = { }; -void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = xf86_config->crtc[id]; - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - - drmmode_crtc->cursor_bo = bo; -} - void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -3004,7 +3102,8 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, } /* Validate leases on VT re-entry */ - drmmode_validate_leases(pScrn); + if (dixPrivateKeyRegistered(rrPrivKey)) + drmmode_validate_leases(pScrn); return TRUE; } @@ -3159,13 +3258,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, @@ -3176,7 +3276,7 @@ restart_destroy: /* Check to see if a lessee has disappeared */ drmmode_validate_leases(scrn); - if (changed && dixPrivateKeyRegistered(rrPrivKey)) { + if (changed) { #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) RRSetChanged(xf86ScrnToScreen(scrn)); #else @@ -3276,6 +3376,7 @@ 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 crtc_id; uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; drmmode_flipdata_ptr flipdata; Bool handle_deferred = FALSE; @@ -3283,7 +3384,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, struct drmmode_fb *fb; int i = 0; - flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc * + flipdata = calloc(1, sizeof(*flipdata) + drmmode_crtc->drmmode->count_crtcs * sizeof(flipdata->fb[0])); if (!flipdata) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -3315,6 +3416,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, for (i = 0; i < config->num_crtc; i++) { 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)) @@ -3325,7 +3427,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"); @@ -3348,9 +3451,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto next; } - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!flipdata->fb[i]) { + if (!flipdata->fb[crtc_id]) { ErrorF("Failed to get FB for TearFree flip\n"); goto error; } @@ -3366,13 +3469,13 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, drmmode_crtc->scanout_update_pending = 0; } } else { - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], fb); + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], fb); } if (crtc == ref_crtc) { if (drmmode_page_flip_target_absolute(pRADEONEnt, drmmode_crtc, - flipdata->fb[i]->handle, + flipdata->fb[crtc_id]->handle, flip_flags, drm_queue_seq, target_msc) != 0) @@ -3380,7 +3483,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } else { if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - flipdata->fb[i]->handle, + flipdata->fb[crtc_id]->handle, flip_flags, drm_queue_seq, 0) != 0) goto flip_error; @@ -3391,9 +3494,10 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, drmmode_crtc->ignore_damage = TRUE; } - next: drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - flipdata->fb[i]); + flipdata->fb[crtc_id]); + + next: drm_queue_seq = 0; } diff --git a/driver/xf86-video-ati/src/drmmode_display.h b/driver/xf86-video-ati/src/drmmode_display.h index bc66eda65..2c2c3d57f 100644 --- a/driver/xf86-video-ati/src/drmmode_display.h +++ b/driver/xf86-video-ati/src/drmmode_display.h @@ -71,6 +71,12 @@ struct drmmode_fb { uint32_t handle; }; +enum drmmode_scanout_status { + DRMMODE_SCANOUT_OK, + DRMMODE_SCANOUT_FLIP_FAILED = 1u << 0, + DRMMODE_SCANOUT_VBLANK_FAILED = 1u << 1, +}; + struct drmmode_scanout { struct radeon_buffer *bo; PixmapPtr pixmap; @@ -81,7 +87,15 @@ typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; int hw_id; - struct radeon_bo *cursor_bo; + + CursorPtr cursor; + int cursor_x; + int cursor_y; + int cursor_xhot; + int cursor_yhot; + unsigned cursor_id; + struct radeon_bo *cursor_bo[2]; + struct drmmode_scanout rotate; struct drmmode_scanout scanout[2]; DamagePtr scanout_damage; @@ -90,6 +104,7 @@ typedef struct { unsigned scanout_id; uintptr_t scanout_update_pending; Bool tear_free; + enum drmmode_scanout_status scanout_status; PixmapPtr prime_scanout_pixmap; @@ -206,7 +221,6 @@ extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp); extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr); -extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo); void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y); extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw); @@ -215,7 +229,7 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn); extern void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, struct drmmode_scanout *scanout); -void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc); +void drmmode_crtc_scanout_free(xf86CrtcPtr crtc); PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, int width, int height); diff --git a/driver/xf86-video-ati/src/radeon.h b/driver/xf86-video-ati/src/radeon.h index b1d5f5af4..74454c307 100644 --- a/driver/xf86-video-ati/src/radeon.h +++ b/driver/xf86-video-ati/src/radeon.h @@ -560,7 +560,7 @@ typedef struct { /* Number of SW cursors currently visible on this screen */ int sprites_visible; - Bool IsSecondary; + int instance_id; Bool r600_shadow_fb; void *fb_shadow; @@ -572,7 +572,6 @@ typedef struct { struct radeon_cs_manager *csm; struct radeon_cs *cs; - struct radeon_bo *cursor_bo[32]; uint64_t vram_size; uint64_t gart_size; drmmode_rec drmmode; diff --git a/driver/xf86-video-ati/src/radeon_bo_helper.c b/driver/xf86-video-ati/src/radeon_bo_helper.c index da5a484f2..8b3e57974 100644 --- a/driver/xf86-video-ati/src/radeon_bo_helper.c +++ b/driver/xf86-video-ati/src/radeon_bo_helper.c @@ -39,6 +39,8 @@ radeon_get_gbm_format(int depth, int bitsPerPixel) case 8: return GBM_FORMAT_R8; #endif + case 15: + return GBM_FORMAT_ARGB1555; case 16: return GBM_FORMAT_RGB565; case 32: diff --git a/driver/xf86-video-ati/src/radeon_dri2.c b/driver/xf86-video-ati/src/radeon_dri2.c index 4d12fc09a..a9f14e8d8 100644 --- a/driver/xf86-video-ati/src/radeon_dri2.c +++ b/driver/xf86-video-ati/src/radeon_dri2.c @@ -252,6 +252,12 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, } else if (is_glamor_pixmap) { pixmap = radeon_glamor_set_pixmap_bo(drawable, pixmap); pixmap->refcnt++; + + /* The copy operation from radeon_glamor_set_pixmap_bo needs to + * be flushed to the kernel driver before the client starts + * using the pixmap storage for direct rendering. + */ + radeon_cs_flush_indirect(pScrn); } if (!radeon_get_flink_name(pRADEONEnt, pixmap, &buffers->name)) @@ -973,12 +979,18 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) if (ret) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); - if (event_info->drm_queue_seq) + + if (event_info->drm_queue_seq) { drmmode_crtc->drmmode->event_context. vblank_handler(pRADEONEnt->fd, 0, 0, 0, (void*)event_info->drm_queue_seq); - else + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(crtc); + + } else { radeon_dri2_frame_event_handler(crtc, 0, 0, data); + } + return 0; } /* @@ -989,13 +1001,18 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) delta_seq = delta_t * drmmode_crtc->dpms_last_fps; delta_seq /= 1000000; frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq; - if (event_info->drm_queue_seq) + + if (event_info->drm_queue_seq) { drmmode_crtc->drmmode->event_context. vblank_handler(pRADEONEnt->fd, frame, drm_now / 1000000, drm_now % 1000000, (void*)event_info->drm_queue_seq); - else + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(crtc); + } else { radeon_dri2_frame_event_handler(crtc, frame, drm_now, data); + } + return 0; } @@ -1076,7 +1093,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, wait_info, radeon_dri2_frame_event_handler, - radeon_dri2_frame_event_abort); + radeon_dri2_frame_event_abort, FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue event entry failed.\n"); @@ -1215,7 +1232,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, swap_info, radeon_dri2_frame_event_handler, - radeon_dri2_frame_event_abort); + radeon_dri2_frame_event_abort, FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue entry failed.\n"); diff --git a/driver/xf86-video-ati/src/radeon_dri3.c b/driver/xf86-video-ati/src/radeon_dri3.c index 7e89a2f0b..73353bf51 100644 --- a/driver/xf86-video-ati/src/radeon_dri3.c +++ b/driver/xf86-video-ati/src/radeon_dri3.c @@ -37,6 +37,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <gbm.h> #include <errno.h> #include <libgen.h> @@ -212,20 +213,46 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen, CARD16 *stride, CARD32 *size) { - struct radeon_bo *bo; + struct radeon_buffer *bo; int fd; #ifdef USE_GLAMOR ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONInfoPtr info = RADEONPTR(scrn); - if (info->use_glamor) - return glamor_fd_from_pixmap(screen, pixmap, stride, size); + if (info->use_glamor) { + Bool need_flush = TRUE; + int ret = -1; +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,19,99,904,0) + struct gbm_bo *gbm_bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + + if (gbm_bo) { + ret = gbm_bo_get_fd(gbm_bo); + gbm_bo_destroy(gbm_bo); + + if (ret >= 0) + need_flush = FALSE; + } +#endif + + if (ret < 0) + ret = glamor_fd_from_pixmap(screen, pixmap, stride, size); + + /* glamor might have needed to reallocate the pixmap storage and + * copy the pixmap contents to the new storage. The copy + * operation needs to be flushed to the kernel driver before the + * client starts using the pixmap storage for direct rendering. + */ + if (ret >= 0 && need_flush) + radeon_cs_flush_indirect(scrn); + + return ret; + } #endif - bo = radeon_get_pixmap_bo(pixmap)->bo.radeon; + bo = radeon_get_pixmap_bo(pixmap); if (!bo) { exaMoveInPixmap(pixmap); - bo = radeon_get_pixmap_bo(pixmap)->bo.radeon; + bo = radeon_get_pixmap_bo(pixmap); if (!bo) return -1; } @@ -233,11 +260,11 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen, if (pixmap->devKind > UINT16_MAX) return -1; - if (radeon_gem_prime_share_bo(bo, &fd) < 0) + if (radeon_gem_prime_share_bo(bo->bo.radeon, &fd) < 0) return -1; *stride = pixmap->devKind; - *size = bo->size; + *size = bo->bo.radeon->size; return fd; } diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.c b/driver/xf86-video-ati/src/radeon_drm_queue.c index ea78e8e2b..fc0436058 100644 --- a/driver/xf86-video-ati/src/radeon_drm_queue.c +++ b/driver/xf86-video-ati/src/radeon_drm_queue.c @@ -30,6 +30,8 @@ #include "config.h" #endif +#include <errno.h> + #include <xorg-server.h> #include <X11/Xdefs.h> #include <list.h> @@ -48,6 +50,7 @@ struct radeon_drm_queue_entry { xf86CrtcPtr crtc; radeon_drm_handler_proc handler; radeon_drm_abort_proc abort; + Bool is_flip; unsigned int frame; }; @@ -55,6 +58,7 @@ static int radeon_drm_queue_refcnt; static struct xorg_list radeon_drm_queue; static struct xorg_list radeon_drm_flip_signalled; static struct xorg_list radeon_drm_vblank_signalled; +static struct xorg_list radeon_drm_vblank_deferred; static uintptr_t radeon_drm_queue_seq; @@ -72,9 +76,22 @@ radeon_drm_queue_handle_one(struct radeon_drm_queue_entry *e) free(e); } +/* + * Abort one queued DRM entry, removing it + * from the list, calling the abort function and + * freeing the memory + */ static void -radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame, - unsigned int sec, unsigned int usec, void *user_ptr) +radeon_drm_abort_one(struct radeon_drm_queue_entry *e) +{ + xorg_list_del(&e->list); + e->abort(e->crtc, e->data); + free(e); +} + +static void +radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec, + unsigned int usec, void *user_ptr) { uintptr_t seq = (uintptr_t)user_ptr; struct radeon_drm_queue_entry *e, *tmp; @@ -82,39 +99,44 @@ radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame, xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) { if (e->seq == seq) { if (!e->handler) { - radeon_drm_queue_handle_one(e); + radeon_drm_abort_one(e); break; } xorg_list_del(&e->list); e->usec = (uint64_t)sec * 1000000 + usec; e->frame = frame; - xorg_list_append(&e->list, signalled); + xorg_list_append(&e->list, e->is_flip ? + &radeon_drm_flip_signalled : + &radeon_drm_vblank_signalled); break; } } } /* - * Signal a DRM page flip event + * Handle signalled vblank events. If we're waiting for a flip event, + * put events for that CRTC in the vblank_deferred list. */ static void -radeon_drm_page_flip_handler(int fd, unsigned int frame, unsigned int sec, - unsigned int usec, void *user_ptr) +radeon_drm_handle_vblank_signalled(void) { - radeon_drm_queue_handler(&radeon_drm_flip_signalled, frame, sec, usec, - user_ptr); -} + drmmode_crtc_private_ptr drmmode_crtc; + struct radeon_drm_queue_entry *e; -/* - * Signal a DRM vblank event - */ -static void -radeon_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec, - unsigned int usec, void *user_ptr) -{ - radeon_drm_queue_handler(&radeon_drm_vblank_signalled, frame, sec, usec, - user_ptr); + while (!xorg_list_is_empty(&radeon_drm_vblank_signalled)) { + e = xorg_list_first_entry(&radeon_drm_vblank_signalled, + struct radeon_drm_queue_entry, list); + drmmode_crtc = e->crtc->driver_private; + + if (drmmode_crtc->wait_flip_nesting_level == 0) { + radeon_drm_queue_handle_one(e); + continue; + } + + xorg_list_del(&e->list); + xorg_list_append(&e->list, &radeon_drm_vblank_deferred); + } } /* @@ -133,12 +155,18 @@ radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc) --drmmode_crtc->wait_flip_nesting_level > 0) return; - xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) { - drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private; + /* Put previously deferred vblank events for this CRTC back in the + * signalled queue + */ + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) { + if (e->crtc != crtc) + continue; - if (drmmode_crtc->wait_flip_nesting_level == 0) - radeon_drm_queue_handle_one(e); + xorg_list_del(&e->list); + xorg_list_append(&e->list, &radeon_drm_vblank_signalled); } + + radeon_drm_handle_vblank_signalled(); } /* @@ -149,7 +177,8 @@ uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, uint64_t id, void *data, radeon_drm_handler_proc handler, - radeon_drm_abort_proc abort) + radeon_drm_abort_proc abort, + Bool is_flip) { struct radeon_drm_queue_entry *e; @@ -167,6 +196,7 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, e->data = data; e->handler = handler; e->abort = abort; + e->is_flip = is_flip; xorg_list_append(&e->list, &radeon_drm_queue); @@ -174,19 +204,6 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, } /* - * Abort one queued DRM entry, removing it - * from the list, calling the abort function and - * freeing the memory - */ -static void -radeon_drm_abort_one(struct radeon_drm_queue_entry *e) -{ - xorg_list_del(&e->list); - e->abort(e->crtc, e->data); - free(e); -} - -/* * Abort drm queue entries for a client * * NOTE: This keeps the entries in the list until the DRM event arrives, @@ -222,6 +239,13 @@ radeon_drm_abort_entry(uintptr_t seq) } } + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) { + if (e->seq == seq) { + radeon_drm_abort_one(e); + return; + } + } + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) { if (e->seq == seq) { radeon_drm_abort_one(e); @@ -252,10 +276,23 @@ radeon_drm_abort_id(uint64_t id) int radeon_drm_handle_event(int fd, drmEventContext *event_context) { - struct radeon_drm_queue_entry *e, *tmp; + struct radeon_drm_queue_entry *e; int r; - r = drmHandleEvent(fd, event_context); + /* Retry drmHandleEvent if it was interrupted by a signal in read() */ + do { + r = drmHandleEvent(fd, event_context); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + + if (r < 0) { + static Bool printed; + + if (!printed) { + ErrorF("%s: drmHandleEvent returned %d, errno=%d (%s)\n", + __func__, r, errno, strerror(errno)); + printed = TRUE; + } + } while (!xorg_list_is_empty(&radeon_drm_flip_signalled)) { e = xorg_list_first_entry(&radeon_drm_flip_signalled, @@ -263,12 +300,7 @@ radeon_drm_handle_event(int fd, drmEventContext *event_context) radeon_drm_queue_handle_one(e); } - xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) { - drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private; - - if (drmmode_crtc->wait_flip_nesting_level == 0) - radeon_drm_queue_handle_one(e); - } + radeon_drm_handle_vblank_signalled(); return r; } @@ -293,7 +325,7 @@ void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc) while (drmmode_crtc->flip_pending && radeon_drm_handle_event(pRADEONEnt->fd, - &drmmode_crtc->drmmode->event_context) > 0); + &drmmode_crtc->drmmode->event_context) >= 0); } /* @@ -306,8 +338,8 @@ radeon_drm_queue_init(ScrnInfoPtr scrn) drmmode_ptr drmmode = &info->drmmode; drmmode->event_context.version = 2; - drmmode->event_context.vblank_handler = radeon_drm_vblank_handler; - drmmode->event_context.page_flip_handler = radeon_drm_page_flip_handler; + drmmode->event_context.vblank_handler = radeon_drm_queue_handler; + drmmode->event_context.page_flip_handler = radeon_drm_queue_handler; if (radeon_drm_queue_refcnt++) return; @@ -315,6 +347,7 @@ radeon_drm_queue_init(ScrnInfoPtr scrn) xorg_list_init(&radeon_drm_queue); xorg_list_init(&radeon_drm_flip_signalled); xorg_list_init(&radeon_drm_vblank_signalled); + xorg_list_init(&radeon_drm_vblank_deferred); } /* diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.h b/driver/xf86-video-ati/src/radeon_drm_queue.h index 334c4ca63..19d42e930 100644 --- a/driver/xf86-video-ati/src/radeon_drm_queue.h +++ b/driver/xf86-video-ati/src/radeon_drm_queue.h @@ -44,7 +44,8 @@ void radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc); uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, uint64_t id, void *data, radeon_drm_handler_proc handler, - radeon_drm_abort_proc abort); + radeon_drm_abort_proc abort, + Bool is_flip); void radeon_drm_abort_client(ClientPtr client); void radeon_drm_abort_entry(uintptr_t seq); void radeon_drm_abort_id(uint64_t id); diff --git a/driver/xf86-video-ati/src/radeon_glamor.c b/driver/xf86-video-ati/src/radeon_glamor.c index b0da8537f..eae351fbf 100644 --- a/driver/xf86-video-ati/src/radeon_glamor.c +++ b/driver/xf86-video-ati/src/radeon_glamor.c @@ -109,9 +109,14 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn) "glamor may not work (well) with GPUs < RV515.\n"); } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,99,0,0) if (scrn->depth < 24) { +#else + if (scrn->depth < 15) { +#endif xf86DrvMsg(scrn->scrnIndex, s ? X_ERROR : X_WARNING, - "glamor requires depth >= 24, disabling.\n"); + "Depth %d not supported with glamor, disabling\n", + scrn->depth); return FALSE; } @@ -233,7 +238,7 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (info->shadow_primary) { if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) return fbCreatePixmap(screen, w, h, depth, usage); - } else { + } else if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) { pixmap = glamor_create_pixmap(screen, w, h, depth, usage); if (pixmap) return pixmap; diff --git a/driver/xf86-video-ati/src/radeon_kms.c b/driver/xf86-video-ati/src/radeon_kms.c index ae69f3353..ff4f8dcf6 100644 --- a/driver/xf86-video-ati/src/radeon_kms.c +++ b/driver/xf86-video-ati/src/radeon_kms.c @@ -202,6 +202,10 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn) if (!pScrn) return; + pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); + pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex); + pRADEONEnt = pPriv->ptr; + info = RADEONPTR(pScrn); if (info) { if (info->fbcon_pixmap) @@ -217,15 +221,12 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn) gbm_device_destroy(info->gbm); #endif - pEnt = info->pEnt; + pRADEONEnt->scrn[info->instance_id] = NULL; + pRADEONEnt->num_scrns--; free(pScrn->driverPrivate); pScrn->driverPrivate = NULL; - } else { - pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); } - pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; if (pRADEONEnt->fd > 0) { DevUnion *pPriv; RADEONEntPtr pRADEONEnt; @@ -348,13 +349,13 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) RROutputChanged(rrScrPriv->primaryOutput, FALSE); rrScrPriv->layoutChanged = TRUE; } + + drmmode_uevent_init(pScrn, &info->drmmode); } if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU)) return FALSE; - drmmode_uevent_init(pScrn, &info->drmmode); - if (info->r600_shadow_fb) { pixmap = pScreen->GetScreenPixmap(pScreen); @@ -525,10 +526,14 @@ radeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct drmmode_fb *fb = event_data; drmmode_crtc->scanout_update_pending = 0; - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - NULL); + + if (drmmode_crtc->flip_pending == fb) { + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + NULL); + } } static void @@ -537,9 +542,9 @@ radeon_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec, { RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct drmmode_fb *fb = event_data; - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, - drmmode_crtc->flip_pending); + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb); radeon_scanout_flip_abort(crtc, event_data); } @@ -751,6 +756,7 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) { ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty); drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; @@ -768,23 +774,45 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, NULL, radeon_prime_scanout_update_handler, - radeon_prime_scanout_update_abort); + radeon_prime_scanout_update_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "radeon_drm_queue_alloc failed for PRIME update\n"); + radeon_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL); return; } + drmmode_crtc->scanout_update_pending = drm_queue_seq; + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 1, drm_queue_seq, NULL, NULL)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmmode_wait_vblank failed for PRIME update: %s\n", - strerror(errno)); - radeon_drm_abort_entry(drm_queue_seq); + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "drmmode_wait_vblank failed for PRIME update: %s\n", + strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED; + } + + drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd, + 0, 0, 0, + (void*)drm_queue_seq); + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(xf86_crtc); return; } - drmmode_crtc->scanout_update_pending = drm_queue_seq; + if (drmmode_crtc->scanout_status == + (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) { + /* The page flip and vblank ioctls failed before, but the vblank + * ioctl is working again, so we can try re-enabling TearFree + */ + xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode, + xf86_crtc->rotation, + xf86_crtc->x, xf86_crtc->y); + } + + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED; } static void @@ -797,52 +825,61 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent) drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; unsigned scanout_id; + struct drmmode_fb *fb; if (!crtc || !crtc->enabled) return; drmmode_crtc = crtc->driver_private; + scanout_id = drmmode_crtc->scanout_id ^ 1; if (drmmode_crtc->scanout_update_pending || - !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || + !drmmode_crtc->scanout[scanout_id].pixmap || drmmode_crtc->dpms_mode != DPMSModeOn) return; - scanout_id = drmmode_crtc->scanout_id ^ 1; if (!radeon_prime_scanout_do_update(crtc, scanout_id)) return; + fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for PRIME flip.\n"); + return; + } + drm_queue_seq = radeon_drm_queue_alloc(crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, - RADEON_DRM_QUEUE_ID_DEFAULT, - NULL, + RADEON_DRM_QUEUE_ID_DEFAULT, fb, radeon_scanout_flip_handler, - radeon_scanout_flip_abort); + radeon_scanout_flip_abort, TRUE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM event queue entry failed for PRIME flip.\n"); return; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!drmmode_crtc->flip_pending) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to get FB for PRIME flip.\n"); + if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, + fb->handle, 0, drm_queue_seq, 1) + != 0) { + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed in %s: %s, TearFree inactive\n", + __func__, strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED; + } + radeon_drm_abort_entry(drm_queue_seq); return; } - if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode_crtc->flip_pending->handle, - 0, drm_queue_seq, 0) != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", - __func__, strerror(errno)); - radeon_drm_abort_entry(drm_queue_seq); - return; + if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; } drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = drm_queue_seq; + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb); } static void @@ -1020,8 +1057,9 @@ static void radeon_scanout_update(xf86CrtcPtr xf86_crtc) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + ScrnInfoPtr scrn = xf86_crtc->scrn; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); uintptr_t drm_queue_seq; - ScrnInfoPtr scrn; DamagePtr pDamage; RegionPtr pRegion; BoxRec extents; @@ -1046,29 +1084,50 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) return; } - scrn = xf86_crtc->scrn; drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, drmmode_crtc, radeon_scanout_update_handler, - radeon_scanout_update_abort); + radeon_scanout_update_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "radeon_drm_queue_alloc failed for scanout update\n"); + radeon_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc); return; } + drmmode_crtc->scanout_update_pending = drm_queue_seq; + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 1, drm_queue_seq, NULL, NULL)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmmode_wait_vblank failed for scanout update: %s\n", - strerror(errno)); - radeon_drm_abort_entry(drm_queue_seq); + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "drmmode_wait_vblank failed for scanout update: %s\n", + strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED; + } + + drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd, + 0, 0, 0, + (void*)drm_queue_seq); + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(xf86_crtc); return; } - drmmode_crtc->scanout_update_pending = drm_queue_seq; + if (drmmode_crtc->scanout_status == + (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) { + /* The page flip and vblank ioctls failed before, but the vblank + * ioctl is working again, so we can try re-enabling TearFree + */ + xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode, + xf86_crtc->rotation, + xf86_crtc->x, xf86_crtc->y); + } + + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED; } static void @@ -1081,6 +1140,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); uintptr_t drm_queue_seq; unsigned scanout_id; + struct drmmode_fb *fb; if (drmmode_crtc->scanout_update_pending || drmmode_crtc->flip_pending || @@ -1096,33 +1156,34 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, radeon_cs_flush_indirect(scrn); RegionEmpty(region); + fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for scanout flip.\n"); + return; + } + drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, - RADEON_DRM_QUEUE_ID_DEFAULT, - NULL, + RADEON_DRM_QUEUE_ID_DEFAULT, fb, radeon_scanout_flip_handler, - radeon_scanout_flip_abort); + radeon_scanout_flip_abort, TRUE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM event queue entry failed.\n"); return; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!drmmode_crtc->flip_pending) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to get FB for scanout flip.\n"); - radeon_drm_abort_entry(drm_queue_seq); - return; - } - if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode_crtc->flip_pending->handle, - 0, drm_queue_seq, 0) != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, " - "TearFree inactive until next modeset\n", - __func__, strerror(errno)); + fb->handle, 0, drm_queue_seq, 1) + != 0) { + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed in %s: %s, TearFree inactive\n", + __func__, strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED; + } + radeon_drm_abort_entry(drm_queue_seq); RegionCopy(DamageRegion(drmmode_crtc->scanout_damage), &drmmode_crtc->scanout_last_region); @@ -1134,8 +1195,14 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, return; } + if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; + } + drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = drm_queue_seq; + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb); } static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) @@ -1689,7 +1756,6 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) RADEONInfoPtr info; RADEONEntPtr pRADEONEnt; MessageType from; - DevUnion* pPriv; Gamma zeros = { 0.0, 0.0, 0.0 }; uint32_t tiling = 0; int cpp; @@ -1700,10 +1766,23 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONPreInit_KMS\n"); if (pScrn->numEntities != 1) return FALSE; + + pRADEONEnt = xf86GetEntityPrivate(pScrn->entityList[0], + getRADEONEntityIndex())->ptr; + if (pRADEONEnt->num_scrns == ARRAY_SIZE(pRADEONEnt->scrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Only up to %u Zaphod instances supported\n", + (unsigned)ARRAY_SIZE(pRADEONEnt->scrn)); + return FALSE; + } + if (!RADEONGetRec(pScrn)) return FALSE; info = RADEONPTR(pScrn); - info->IsSecondary = FALSE; + + info->instance_id = pRADEONEnt->num_scrns++; + pRADEONEnt->scrn[info->instance_id] = pScrn; + info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); if (info->pEnt->location.type != BUS_PCI #ifdef XSERVER_PLATFORM_BUS @@ -1712,27 +1791,11 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) ) return FALSE; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - getRADEONEntityIndex()); - pRADEONEnt = pPriv->ptr; - - if(xf86IsEntityShared(pScrn->entityList[0])) - { - if(xf86IsPrimInitDone(pScrn->entityList[0])) - { - info->IsSecondary = TRUE; - } - else - { - xf86SetPrimInitDone(pScrn->entityList[0]); - } + if (xf86IsEntityShared(pScrn->entityList[0]) && + info->instance_id == 0) { + xf86SetPrimInitDone(pScrn->entityList[0]); } - if (info->IsSecondary) - pRADEONEnt->secondary_scrn = pScrn; - else - pRADEONEnt->primary_scrn = pScrn; - info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); pScrn->monitor = pScrn->confScreen->monitor; @@ -2614,7 +2677,7 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, None, pRADEONEnt); } else { - drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc_scanout_free(crtc); } } } @@ -2694,28 +2757,29 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) { int cursor_size; - int c; + int c, i; cursor_size = info->cursor_w * info->cursor_h * 4; cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE); for (c = 0; c < xf86_config->num_crtc; c++) { - /* cursor objects */ - if (!info->cursor_bo[c]) { - info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0, - cursor_size, 0, - RADEON_GEM_DOMAIN_VRAM, 0); - if (!info->cursor_bo[c]) { - ErrorF("Failed to allocate cursor buffer memory\n"); - return FALSE; - } - - if (radeon_bo_map(info->cursor_bo[c], 1)) { - ErrorF("Failed to map cursor buffer memory\n"); - } - - drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]); - } - } + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; + + for (i = 0; i < 2; i++) { + if (!drmmode_crtc->cursor_bo[i]) { + drmmode_crtc->cursor_bo[i] = + radeon_bo_open(info->bufmgr, 0, cursor_size, 0, + RADEON_GEM_DOMAIN_VRAM, 0); + + if (!(drmmode_crtc->cursor_bo[i])) { + ErrorF("Failed to allocate cursor buffer memory\n"); + return FALSE; + } + + if (radeon_bo_map(drmmode_crtc->cursor_bo[i], 1)) + ErrorF("Failed to map cursor buffer memory\n"); + } + } + } } if (!info->front_buffer) { @@ -2779,7 +2843,9 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size) int c; for (c = 0; c < xf86_config->num_crtc; c++) { - if (info->cursor_bo[c]) + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; + + if (drmmode_crtc->cursor_bo[0]) new_fb_size += (64 * 4 * 64); } diff --git a/driver/xf86-video-ati/src/radeon_present.c b/driver/xf86-video-ati/src/radeon_present.c index d0a0c68ca..38a9a6b79 100644 --- a/driver/xf86-video-ati/src/radeon_present.c +++ b/driver/xf86-video-ati/src/radeon_present.c @@ -157,7 +157,8 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) RADEON_DRM_QUEUE_CLIENT_DEFAULT, event_id, event, radeon_present_vblank_handler, - radeon_present_vblank_abort); + radeon_present_vblank_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { free(event); return BadAlloc; @@ -255,7 +256,7 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, ScrnInfoPtr scrn = xf86_crtc->scrn; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); RADEONInfoPtr info = RADEONPTR(scrn); - PixmapPtr screen_pixmap; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); int num_crtcs_on; int i; @@ -271,10 +272,14 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, if (info->drmmode.dri2_flipping) return FALSE; +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(1, 20, 99, 1, 0) + if (pixmap->devKind != screen_pixmap->devKind) + return FALSE; +#endif + /* The kernel driver doesn't handle flipping between BOs with different * tiling parameters correctly yet */ - screen_pixmap = screen->GetScreenPixmap(screen); if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) return FALSE; diff --git a/driver/xf86-video-ati/src/radeon_probe.h b/driver/xf86-video-ati/src/radeon_probe.h index be82f9aea..7cb29b916 100644 --- a/driver/xf86-video-ati/src/radeon_probe.h +++ b/driver/xf86-video-ati/src/radeon_probe.h @@ -140,8 +140,8 @@ typedef struct unsigned long fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */ int fd_wakeup_ref; unsigned int assigned_crtcs; - ScrnInfoPtr primary_scrn; - ScrnInfoPtr secondary_scrn; + unsigned int num_scrns; + ScrnInfoPtr scrn[6]; #ifdef XSERVER_PLATFORM_BUS struct xf86_platform_device *platform_dev; #endif |